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

Downstream QUIC/HTTP3 Support #2111

Merged
merged 7 commits into from
Dec 20, 2023
Merged

Conversation

tanujd11
Copy link
Member

What type of PR is this?

Feature

What this PR does / why we need it:

Adds HTTP3 support in envoy gateway

Which issue(s) this PR fixes:

Fixes #422

@tanujd11 tanujd11 requested a review from a team as a code owner October 29, 2023 18:15
@tanujd11 tanujd11 self-assigned this Oct 29, 2023
@codecov
Copy link

codecov bot commented Oct 29, 2023

Codecov Report

Attention: 49 lines in your changes are missing coverage. Please review.

Comparison is base (d13c329) 64.54% compared to head (83cbc59) 64.58%.

Files Patch % Lines
internal/ir/zz_generated.deepcopy.go 0.00% 20 Missing and 1 partial ⚠️
...frastructure/kubernetes/proxy/resource_provider.go 9.09% 9 Missing and 1 partial ⚠️
internal/xds/translator/listener.go 86.36% 6 Missing and 3 partials ⚠️
internal/xds/translator/translator.go 70.00% 6 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2111      +/-   ##
==========================================
+ Coverage   64.54%   64.58%   +0.04%     
==========================================
  Files         112      112              
  Lines       15949    16072     +123     
==========================================
+ Hits        10294    10380      +86     
- Misses       5007     5040      +33     
- Partials      648      652       +4     

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

@arkodg
Copy link
Contributor

arkodg commented Oct 29, 2023

thanks for building this out @tanujd11 ! , will start reviewing this post the v0.6 release

@zirain zirain added this to the Backlog milestone Oct 30, 2023
@arkodg
Copy link
Contributor

arkodg commented Nov 8, 2023

hey @LanceEa can you help review this one ( since you have experience building this out before :) )

@arkodg arkodg requested a review from LanceEa November 8, 2023 14:44
// EnableHTTP3 enables HTTP/3 support on the listener.
// Disabled by default.
// +optional
EnableHTTP3 bool `json:"enableHTTP3,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

lets make this *bool since its optional

Copy link
Contributor

Choose a reason for hiding this comment

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

I would recommend making it an object instead of a bool. This will future proof you more to provide addtional overrides.

For example, in the generated config you have AlpnProtocols: []string{"h3"} hard coded. Not all clients will recognize or support that. If you look at a simple google home page you can see their web server is configured to support h3=":443"; ma=2592000,h3-29=":443"; ma=2592000.

Other examples, are setting different ports to listen for the QUIC traffic on because many cloud providers do not support listening on the same incoming address. TBH, this is the tricky part to setting up H3 and the Envoy config is quite straight forward.

Copy link
Contributor

Choose a reason for hiding this comment

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

Note: you could start with an empty object and check for existence or not if you want to hold off on allow customizations right away but at least an object future proofs you to add going forward without breaking changes.

Copy link
Contributor

@arkodg arkodg Nov 16, 2023

Choose a reason for hiding this comment

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

I would love to just have a enable knob, but agree with @LanceEa, an empty struct maybe a good call for this API because some user may want to modify the listening port, and everyone loves tweaking port values to adhere with corp perimeter policies

Copy link
Contributor

@LanceEa LanceEa left a comment

Choose a reason for hiding this comment

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

I will defer to the maintainers on code coverage and general style but for the most part it looks good. I have left some feedback on the design and recommendations for future proofing it because support for mixedprotocols on the LoadBalancer Service and cloud vendors was limited last I looked.

// EnableHTTP3 enables HTTP/3 support on the listener.
// Disabled by default.
// +optional
EnableHTTP3 bool `json:"enableHTTP3,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

I would recommend making it an object instead of a bool. This will future proof you more to provide addtional overrides.

For example, in the generated config you have AlpnProtocols: []string{"h3"} hard coded. Not all clients will recognize or support that. If you look at a simple google home page you can see their web server is configured to support h3=":443"; ma=2592000,h3-29=":443"; ma=2592000.

Other examples, are setting different ports to listen for the QUIC traffic on because many cloud providers do not support listening on the same incoming address. TBH, this is the tricky part to setting up H3 and the Envoy config is quite straight forward.

// EnableHTTP3 enables HTTP/3 support on the listener.
// Disabled by default.
// +optional
EnableHTTP3 bool `json:"enableHTTP3,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Note: you could start with an empty object and check for existence or not if you want to hold off on allow customizations right away but at least an object future proofs you to add going forward without breaking changes.


proxyListener := &ir.ProxyListener{
Name: irHTTPListenerName(listener),
Ports: []ir.ListenerPort{infraPort},
Copy link
Contributor

Choose a reason for hiding this comment

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

If I'm understanding this correctly we are only supporting a single port for this listener and then using the HTTP/3 flag to instruct the single ir.ProxyListener to generate a secondary listener for UDP/QUIC. This means the second listener would inherit the port correct?

If so you are more than likely going to want to allow that to be configurable because most cloud vendors were not supporting this last I knew (6+ months ago was the last time I looked so could have changed)

Copy link
Contributor

Choose a reason for hiding this comment

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

This comment is referring to mixed protocols on a single Service of type Loadbalancer.

Append: &wrapperspb.BoolValue{Value: true},
Header: &corev3.HeaderValue{
Key: "alt-svc",
Value: strings.Join([]string{fmt.Sprintf(`%s=":%d"; ma=86400`, "h3", port)}, ", "),
Copy link
Contributor

Choose a reason for hiding this comment

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

You are going to want this to be configurable in the future, see my previous comment on the design of the ClientTrafficPolicy.

- append: true
header:
key: alt-svc
value: h3=":10443"; ma=86400
Copy link
Contributor

Choose a reason for hiding this comment

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

This port needs to be the port exposed externally outside the cluster to the client. So, in most cases involving a browser it is more than likely going to be :443 and not the listener port. The LoadBalancer of type Service then needs to point traffic to 10443. That is what I was referring to as the tricky part because a single Service doesn't always allow for MixedProtocol. note: that might have change since last time I looked into this but it is the more nuanced part to the setup.

@tanujd11
Copy link
Member Author

Hi @LanceEa @arkodg I have made changes to the API making it as following

http3Settings:
  enabled: true

At the moment only enabled is there. I can raise a follow up PR to expose separate port for QUIC and other alt-svc configs. Till then this feature can be termed as experimental. WDYT?

@tanujd11
Copy link
Member Author

Also it would be great if someone from @envoyproxy/gateway-reviewers / @envoyproxy/gateway-maintainers can try out the feature

@tanujd11
Copy link
Member Author

/retest

1 similar comment
@tanujd11
Copy link
Member Author

/retest

if httpIR.TLS != nil && policySpec.HTTP3 != nil {
httpIR.HTTP3 = &ir.HTTP3Settings{}
var proxyListenerIR *ir.ProxyListener
for _, proxyListener := range infraIR[irKey].Proxy.Listeners {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: can we reuse irListenerName and also check if irListenerName.Proxy != nil

Copy link
Member Author

Choose a reason for hiding this comment

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

Hi, I did not get this point. It seems irListenerName is a string. I need to get infraIR from the corresponding IrListenerName that's why I iterated listeners for a gateway.

@@ -20,7 +20,7 @@ func TestValidateInfra(t *testing.T) {
{
name: "default",
infra: NewInfra(),
expect: false,
expect: true,
Copy link
Contributor

Choose a reason for hiding this comment

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

why is this true ?

Copy link
Member Author

Choose a reason for hiding this comment

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

As we removed NewProxyListener by default and only add it when needed(Since we replaced only 1 listener supported to multiple listener), there is no error generated in this test case, hence false. Before any empty listener was there which failed the validate function.

@@ -80,6 +80,18 @@ func (r *ResourceRender) Service() (*corev1.Service, error) {
TargetPort: target,
}
ports = append(ports, p)

if port.Protocol == ir.HTTPSProtocolType {
Copy link
Contributor

Choose a reason for hiding this comment

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

should this live here on in the Gateway API layer ?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is for opening UDP ports for only those ports which have HTTPS configured, That's a requirement for quic. So this condition is added here.

@@ -137,6 +163,10 @@ func (t *Translator) addXdsHTTPFilterChain(xdsListener *listenerv3.Listener, irL
}
}

if http3Listener {
mgr.CodecType = hcmv3.HttpConnectionManager_HTTP3
Copy link
Contributor

Choose a reason for hiding this comment

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

will auto work ?
is there a way for us to support http3 but also support something else in case the client doesnt support it ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Hi Arko, If HTTP3 is not supported then the other listener will be used. We have created a mirror UDP listener and the connection would be upgraded to HTTP3 according to the alt-svc header. So even if HTTP3 is not supported HTTP/HTTP2 will be used

@tanujd11 tanujd11 requested a review from arkodg November 29, 2023 09:36
@tanujd11
Copy link
Member Author

/retest

1 similar comment
@tanujd11
Copy link
Member Author

/retest

@Xunzhuo Xunzhuo modified the milestones: Backlog, v1.0.0-rc1 Dec 6, 2023
@tanujd11
Copy link
Member Author

Hi @arkodg , welcome back from the vacation. Your reviews on this will be greatly appreciated. Thanks.

Copy link

arkodg
arkodg previously approved these changes Dec 19, 2023
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 for adding this feature !

@arkodg arkodg requested review from a team December 19, 2023 22:22
@Xunzhuo
Copy link
Member

Xunzhuo commented Dec 20, 2023

/retest

Copy link
Member

@Xunzhuo Xunzhuo left a comment

Choose a reason for hiding this comment

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

Great! Thanks for working on it : )

Copy link
Contributor

@shawnh2 shawnh2 left a comment

Choose a reason for hiding this comment

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

lgtm

@Xunzhuo
Copy link
Member

Xunzhuo commented Dec 20, 2023

/cc @arkodg

@arkodg arkodg merged commit da40ccb into envoyproxy:main Dec 20, 2023
18 checks passed
@arkodg arkodg mentioned this pull request Jan 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

HTTP3 support on gateway
6 participants