Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions api/envoy/config/core/v3/address.proto
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,20 @@ message Pipe {
}

// The address represents an envoy internal listener.
// [#comment: TODO(lambdai): Make this address available for listener and endpoint.
// TODO(asraa): When address available, remove workaround from test/server/server_fuzz_test.cc:30.]
// [#comment: TODO(asraa): When address available, remove workaround from test/server/server_fuzz_test.cc:30.]
message EnvoyInternalAddress {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe worth to note that this is only used for upstream endpoint address.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

oneof address_name_specifier {
option (validate.required) = true;

// [#not-implemented-hide:] The :ref:`listener name <envoy_v3_api_field_config.listener.v3.Listener.name>` of the destination internal listener.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please keep the comment describing the field.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is not true, address has nothing to do with the listener name.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC the value here needs to point to another listener.
Would it be possible to add a reference to the field that this value will be matched to?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like it changed what the value expect to from the beginning. Maybe worth to ask again whether this field still name correctly, this can be a chance to change the name before expose to the end user.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I agree we need to fix this. I think we should use a dedicated field in InternalListener instead of internal address in the generic address field in Listener. WDYT?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The simplest thing is to just really use the listener name. That keeps LDS to a minimum and I can't think of any reason why more flexibility would be needed here (multiple addresses don't work anyways, but can always be added to InternalListener).

Copy link
Copy Markdown
Member

@soulxu soulxu Aug 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure the usecase of using multiple internal addresses, it seems useless. I guess the multiple internal addresses usecase is internal address mix with IP address. From this point of view, just using the listener name should be fine.

I little prefer just use a string for the internal address, needn't limit that to the listener name. The only reason I have is a soft reason, it seems more straightforward for me when configuring the internal address, just matching the upstream endpoint internal address with the listener internal address. And we needn't add a lot of checks in the code like the user can't specific addresses when this is internal listener...etc. But anyway those are soft reasons.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure the usecase of using multiple internal addresses, it seems useless. I guess the multiple addresses usecase is internal address mix with IP address. From this point of view, just use the listener name should be fine.

suddenly found this may be the multiple internal addresses usecase https://github.com/envoyproxy/envoy/pull/22274/files#r935253240

// Specifies the :ref:`name <envoy_v3_api_field_config.listener.v3.Listener.name>` of the
// internal listener.
string server_listener_name = 1;
}

// Specifies an endpoint identifier to distinguish between multiple endpoints for the same internal listener in a
// single upstream pool. Only used in the upstream addresses for tracking changes to individual endpoints. This, for
// example, may be set to the final destination IP for the target internal listener.
string endpoint_id = 2;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this kind of multiple internal addresses? if yes, then another option is just to support multiple internal addresses here, then you needn't add endpoint_id field for multiple endpoints, just specify multiple internal addresses. but yes, you can't limit the internal address to the listener name anymore.

Copy link
Copy Markdown
Member

@soulxu soulxu Aug 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

after looking at another PR, multiple addresses will bind the number of listener addresses and the number of endpoints together. That means when you add more endpoints to the same internal listener, then you have to update the internal listener with the new internal addresses also, I guess that isn't what people want.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, we want to maximize reuse of the internal listeners - e.g. tunneling shouldn't be coupled to the origin of the traffic. So that implies a possibility of multiple endpoints to the same internal listener in one pool. Upstream de-duplicates endpoints by computing asString so it breaks there.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any typical value of endpoint_id? e.g. the actually L4 address?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lambdai yes exactly

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be confusing to say "L4 address should be here". We don't say a listener corresponds to VIP, or a cluster corresponds to a VIP. That's too prescriptive. I will add an example of the usage.

}

// [#next-free-field: 7]
Expand Down Expand Up @@ -143,7 +148,8 @@ message Address {

Pipe pipe = 2;

// [#not-implemented-hide:]
// Specifies a user-space address handled by :ref:`internal listeners
// <envoy_v3_api_field_config.listener.v3.Listener.internal_listener>`.
EnvoyInternalAddress envoy_internal_address = 3;
}
}
Expand Down
16 changes: 6 additions & 10 deletions api/envoy/config/listener/v3/listener.proto
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ message Listener {
}

// Configuration for envoy internal listener. All the future internal listener features should be added here.
// [#not-implemented-hide:]
message InternalListenerConfig {
}

Expand Down Expand Up @@ -333,24 +332,21 @@ message Listener {
google.protobuf.BoolValue bind_to_port = 26;

// The exclusive listener type and the corresponding config.
// TODO(lambdai): https://github.com/envoyproxy/envoy/issues/15372
// Will create and add TcpListenerConfig. Will add UdpListenerConfig and ApiListener.
// [#not-implemented-hide:]
oneof listener_specifier {
// Used to represent an internal listener which does not listen on OSI L4 address but can be used by the
// :ref:`envoy cluster <envoy_v3_api_msg_config.cluster.v3.Cluster>` to create a user space connection to.
// The internal listener acts as a tcp listener. It supports listener filters and network filter chains.
// The internal listener require :ref:`address <envoy_v3_api_field_config.listener.v3.Listener.address>` has
// field `envoy_internal_address`.
// The internal listener acts as a TCP listener. It supports listener filters and network filter chains.
// Upstream clusters refer to the internal listeners by their :ref:`name
// <envoy_v3_api_field_config.listener.v3.Listener.name>`. :ref:`Address
// <envoy_v3_api_field_config.listener.v3.Listener.address>` must not be set on the internal listeners.
//
// There are some limitations are derived from the implementation. The known limitations include
// There are some limitations that are derived from the implementation. The known limitations include:
//
// * :ref:`ConnectionBalanceConfig <envoy_v3_api_msg_config.listener.v3.Listener.ConnectionBalanceConfig>` is not
// allowed because both cluster connection and listener connection must be owned by the same dispatcher.
// allowed because both the cluster connection and the listener connection must be owned by the same dispatcher.
// * :ref:`tcp_backlog_size <envoy_v3_api_field_config.listener.v3.Listener.tcp_backlog_size>`
// * :ref:`freebind <envoy_v3_api_field_config.listener.v3.Listener.freebind>`
// * :ref:`transparent <envoy_v3_api_field_config.listener.v3.Listener.transparent>`
// [#not-implemented-hide:]
InternalListenerConfig internal_listener = 27;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also maybe worth to note, this will make the listener use the listener name as the internal address. And when this is internal listener, the address field should keep empty.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

}

Expand Down
3 changes: 3 additions & 0 deletions changelogs/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ new_features:
- area: access_log
change: |
updated command operator ``%GRPC_STATUS%`` to suppoprt the snake case.
- area: listener
change: |
expose the implementation of :ref:`internal listener <config_internal_listener>` in xDS API.
- area: ratelimit
change: |
add support for :ref:`adding response headers <envoy_v3_api_field_extensions.filters.http.ratelimit.v3.RateLimit.response_headers_to_add>` to rate-limited responses.
Expand Down
71 changes: 71 additions & 0 deletions configs/encapsulate_http_in_http2_connect.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# This configuration takes incoming HTTP requests on port 10000 and encapsulates it in a CONNECT
# request which is sent upstream port 10001.
bootstrap_extensions:
- name: envoy.bootstrap.internal_listener
typed_config:
"@type": type.googleapis.com/envoy.extensions.bootstrap.internal_listener.v3.InternalListener
static_resources:
listeners:
- name: http
address:
socket_address:
protocol: TCP
address: 127.0.0.1
port_value: 10000
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: encap_cluster
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
- name: encap
internal_listener: {}
filter_chains:
- filters:
- name: tcp
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
stat_prefix: tcp_stats
cluster: cluster_0
tunneling_config:
hostname: host.com:443
clusters:
- name: encap_cluster
load_assignment:
cluster_name: encap_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
envoy_internal_address:
server_listener_name: encap
- name: cluster_0
# This ensures HTTP/2 CONNECT is used for establishing the tunnel.
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicit_http_config:
http2_protocol_options: {}
load_assignment:
cluster_name: cluster_0
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 10001
50 changes: 50 additions & 0 deletions configs/internal_listener_proxy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# This configuration listens on port 9999 and creates TCP connections to port 10000 using an
# intermediate internal listener.
bootstrap_extensions:
- name: envoy.bootstrap.internal_listener
typed_config:
"@type": type.googleapis.com/envoy.extensions.bootstrap.internal_listener.v3.InternalListener
static_resources:
listeners:
- name: ingress
address:
socket_address:
protocol: TCP
address: 127.0.0.1
port_value: 9999
filter_chains:
- filters:
- name: tcp
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
stat_prefix: ingress
cluster: encap_cluster
- name: encap
internal_listener: {}
filter_chains:
- filters:
- name: tcp
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
stat_prefix: encap
cluster: cluster_0
clusters:
- name: encap_cluster
load_assignment:
cluster_name: encap_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
envoy_internal_address:
server_listener_name: encap
- name: cluster_0
load_assignment:
cluster_name: cluster_0
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 10000
78 changes: 78 additions & 0 deletions configs/terminate_http_in_http2_connect.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# This configuration terminates h2 CONNECT on port 10001 and then chains an HTTP filter that always responds with 200 using
# an internal listener.
bootstrap_extensions:
- name: envoy.bootstrap.internal_listener
typed_config:
"@type": type.googleapis.com/envoy.extensions.bootstrap.internal_listener.v3.InternalListener
static_resources:
listeners:
- name: listener_0
address:
socket_address:
protocol: TCP
address: 127.0.0.1
port_value: 10001
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains:
- "*"
routes:
- match:
connect_matcher:
{}
route:
cluster: decap_cluster
upgrade_configs:
- upgrade_type: CONNECT
connect_config:
{}
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
http2_protocol_options:
allow_connect: true
upgrade_configs:
- upgrade_type: CONNECT
- name: decap
internal_listener: {}
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
direct_response:
status: 200
body:
inline_string: "Hello, world!\n"
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: decap_cluster
load_assignment:
cluster_name: decap_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
envoy_internal_address:
server_listener_name: decap
Loading