Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

api: Enable controlling the HTTP version used to connect to the backend #2433

Merged
merged 5 commits into from
Apr 23, 2024

Conversation

liorokman
Copy link
Contributor

@liorokman liorokman commented Jan 11, 2024

What this PR does / why we need it:
This PR proposes adding an API to control the HTTP version that will be used when connecting to a backend configured via an HTTPRoute.

kind: BackendTrafficPolicy
spec:
      useClientProtocol: true

The current behavior is that HTTP/2 is explicitly used if the route is a GRPC route, and it's possible to force HTTP/2-over-cleartext (h2c) by setting the appProtocol field in the backend Kubernetes Service to kubernetes.io/h2c. In all other cases EnvoyGateway generates configuration that forces HTTP/1.1 to the upstream.

The proposed API would allow configuring Envoy Proxy to use the same HTTP protocol version when connecting to the backend as was used by the downstream client.

@liorokman liorokman requested a review from a team as a code owner January 11, 2024 14:44
Copy link

codecov bot commented Jan 11, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 66.82%. Comparing base (29946b0) to head (098c989).
Report is 84 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2433      +/-   ##
==========================================
+ Coverage   66.51%   66.82%   +0.31%     
==========================================
  Files         161      163       +2     
  Lines       22673    23274     +601     
==========================================
+ Hits        15080    15554     +474     
- Misses       6720     6812      +92     
- Partials      873      908      +35     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@arkodg
Copy link
Contributor

arkodg commented Jan 11, 2024

hey @liorokman can you raise a GH issue to define the use case ? would like to get input from the community to be understand if this is needed or not

@liorokman
Copy link
Contributor Author

hey @liorokman can you raise a GH issue to define the use case ? would like to get input from the community to be understand if this is needed or not

Opened #2437

Copy link

This pull request has been automatically marked as stale because it has not had activity in the last 30 days. Please feel free to give a status update now, ping for review, when it's ready. Thank you for your contributions!

@github-actions github-actions bot added the stale label Feb 11, 2024
@zirain
Copy link
Contributor

zirain commented Feb 12, 2024

/retest

@github-actions github-actions bot removed the stale label Feb 12, 2024
Copy link

This pull request has been automatically marked as stale because it has not had activity in the last 30 days. Please feel free to give a status update now, ping for review, when it's ready. Thank you for your contributions!

@github-actions github-actions bot added stale and removed stale labels Mar 13, 2024
@guydc
Copy link
Contributor

guydc commented Apr 10, 2024

LGTM. Maybe we need to update the description with an up-to-date example of the API.

guydc
guydc previously approved these changes Apr 10, 2024
@liorokman
Copy link
Contributor Author

Maybe we need to update the description with an up-to-date example of the API.

Done

@@ -98,6 +103,15 @@ type BackendTrafficPolicySpec struct {
Compression []*Compression `json:"compression,omitempty"`
}

type HTTPOptions struct {
// UseClientProtocol configures Envoy to prefer sending requests to TLS enabled backends using
Copy link
Contributor

Choose a reason for hiding this comment

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

can you elaborate on why preference this given to TLS enabled backend ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The goal is to use Envoy Proxy's use_downstream_protocol_config feature.

If the underlying transport socket supports TLS, it also supports ALPN. This makes it possible for Envoy to try to use both HTTP/1.1 and HTTP/2 as needed when connecting to it. If TLS is not enabled, then Envoy Proxy will either use HTTP/1.1 or HTTP/2. This means that if the downstream client is using the "wrong" protocol, the connection will simply fail.

It's easier to restrict this feature to TLS enabled upstreams where selection can be done based on ALPN than to try to force the downstream to have the right protocol. Fixing the client protocol selection is hard because:

  1. If the Gateway has multiple HTTPRoutes, each one to a different upstream cluster with different supported protocols, then it's not possible to fix the Listener level ALPN array correctly. The route to be used is based on things that come later (e.g. the request path), so it's possible that one HTTPRoute has an upstream that supports only HTTP/2 and is matched on the /first path, while the other HTTPRoute attached to the same Gateway supports only HTTP/1.1 and is matched on the /second path. Envoy can't know which path is going to be used before the protocol is selected and the request actually sent to Envoy, and by that point it's too late to change the protocol.

  2. If the downstream socket (the Gateway) is not TLS enabled, then there's no ALPN available to affect the client's selection anyways, and there would be a large chance of a misconfiguration that makes some HTTPRoutes unusable.

@@ -98,6 +103,15 @@ type BackendTrafficPolicySpec struct {
Compression []*Compression `json:"compression,omitempty"`
}

type HTTPOptions struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

there are already some HTTP only fields at the top level like FaultInjection, so vote to keep this at a top level
will bring this up in the next envoy gateway community meeting

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK. Will wait for the decision before changing this PR.

@@ -98,6 +103,15 @@ type BackendTrafficPolicySpec struct {
Compression []*Compression `json:"compression,omitempty"`
}

type HTTPOptions struct {
// UseClientProtocol configures Envoy to prefer sending requests to TLS enabled backends using
// the same HTTP protocol that the incoming request used. Defaults to false, which means
Copy link
Contributor

Choose a reason for hiding this comment

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

prefer if we added a line in here saying something along the lines of - this is especially useful when the client (connecting to the gateway) and backend support multiple HTTP versions (e.g. http/1.1 and http/2), and users would like to force the backend to use the same version the client is using

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK. Effectively this means that the backend must be TLS enabled, or it can't support multiple HTTP versions.

Copy link
Contributor

@arkodg arkodg Apr 15, 2024

Choose a reason for hiding this comment

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

can you elaborate on how TLS / ALPN is related here ?
as far as in understand, this knob is proactively deciding the upstream protocol version to use based on downstream connection, so it even applies to non TLS (like h2c to upstream, if downstream is h2c or h2)

Copy link
Contributor Author

@liorokman liorokman Apr 15, 2024

Choose a reason for hiding this comment

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

A backend without TLS will either support HTTP/1.1 or HTTP/2, but never both. That's the point of h2c - it requires pre-knowledge on the part of the client that the server requires HTTP/2.

Since HTTP/2 is a binary protocol, if a client like Envoy Proxy starts a connection by sending a textual HTTP/1.1 request to an HTTP/2 over clear-text server, the server will disconnect it.
Since HTTP/1.1 is a textual protocol, if a client like Envoy Proxy starts a connection by sending an HTTP/2 cleartext request to an HTTP/1.1 server, the server will disconnect it.
Without TLS + ALPN, there is no way for a client like Envoy Proxy to negotiate with the server which protocol it can use, and this means that effectively upstream can't support multiple versions of HTTP without TLS+ALPN.

(like h2c to upstream, if downstream is h2c or h2)

We can configure the Envoy Proxy client to try to connect to upstream with the downstream protocol even without TLS on the upstream protocol. What it would do is automatically fail all requests where the downstream protocol doesn't match the single upstream protocol that is possible without upstream TLS.

Signed-off-by: Lior Okman <lior.okman@sap.com>
community meetings.

Signed-off-by: Lior Okman <lior.okman@sap.com>
API.

Signed-off-by: Lior Okman <lior.okman@sap.com>
upstream TLS backend.

Signed-off-by: Lior Okman <lior.okman@sap.com>
@liorokman
Copy link
Contributor Author

@guydc @arkodg PTAL

Copy link
Contributor

@arkodg arkodg left a comment

Choose a reason for hiding this comment

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

LGTM thanks !

@arkodg arkodg requested a review from guydc April 23, 2024 02:02
@arkodg arkodg added this to the v1.1.0-rc1 milestone Apr 23, 2024
@guydc guydc merged commit aacf359 into envoyproxy:main Apr 23, 2024
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants