-
Notifications
You must be signed in to change notification settings - Fork 680
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
disableCompression: Expose configuration to toggle Envoy GZIP compression on the responses #6546
base: main
Are you sure you want to change the base?
Conversation
Hi @chaosbox! Welcome to our community and thank you for opening your first Pull Request. Someone will review it soon. Thank you for committing to making Contour better. You can also join us on our mailing list and in our channel in the Kubernetes Slack Workspace |
…jectcontour#6543) Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 3.3.0 to 3.4.0. - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](docker/setup-buildx-action@d70bba7...4fd8129) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: chaosbox <[email protected]>
…ponse compression Signed-off-by: chaosbox <[email protected]>
The Contour project currently lacks enough contributors to adequately respond to all PRs. This bot triages PRs according to the following rules:
You can:
Please send feedback to the #contour channel in the Kubernetes Slack |
Ping |
# Conflicts: # .github/workflows/build_main.yaml # .github/workflows/build_tag.yaml # .github/workflows/prbuild.yaml
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've included suggestions inline for some linter nags (link).
Please add the new disableCompression
option in "Configuration File" chapter in site/content/docs/main/configuration.md.
Please add also a changelog file.
}, | ||
ResponseDirectionConfig: &envoy_filter_http_compressor_v3.Compressor_ResponseDirectionConfig{ | ||
CommonConfig: &envoy_filter_http_compressor_v3.Compressor_CommonDirectionConfig{ | ||
ContentType: []string{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possible alternative approach could be to leave the compressor filter in the chain but disable it by setting default to false
in ResponseDirectionConfig.CommonConfig.Enabled
Enabled: &envoy_config_core_v3.RuntimeFeatureFlag{
// If compression is enabled add compressor filter
DefaultValue: wrapperspb.Bool(!b.disableCompression),
RuntimeKey: "contour.compression.response.enabled",
},
but since we do not have "per route" setting, which would override the default, it make sense to me that the whole filter is excluded from the chain when disabled, like suggested in this PR currently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, given
since we do not have "per route" setting
the thought in this PR is to work at the level of the whole filter. The functionality could be extended as described above if needed in future but that would best be left to another PR.
Thanks very much for the feedback @tsaarni 🙇 we'll have a look at this and try to get back with updates as soon as possible. |
Many thanks for taking the time to provide the lint fixes. We'll update the docs and add the changelog as soon as possible. |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #6546 +/- ##
==========================================
- Coverage 81.76% 81.75% -0.02%
==========================================
Files 133 133
Lines 15944 15986 +42
==========================================
+ Hits 13037 13069 +32
- Misses 2614 2623 +9
- Partials 293 294 +1
|
619ac16
to
16f72d7
Compare
Co-authored-by: Tero Saarni <[email protected]> Signed-off-by: Geoff Macartney <[email protected]>
Co-authored-by: Tero Saarni <[email protected]> Signed-off-by: Geoff Macartney <[email protected]>
Co-authored-by: Tero Saarni <[email protected]> Signed-off-by: Geoff Macartney <[email protected]>
Co-authored-by: Tero Saarni <[email protected]> Signed-off-by: Geoff Macartney <[email protected]>
Co-authored-by: Tero Saarni <[email protected]> Signed-off-by: Geoff Macartney <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Just small documentation comments.
// DisableCompression disables GZIP compression HTTP filter from the default Listener filters | ||
// Setting this true will enable Envoy skip "Accept-Encoding: gzip,deflate" request header and always return uncompressed response |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// DisableCompression disables GZIP compression HTTP filter from the default Listener filters | |
// Setting this true will enable Envoy skip "Accept-Encoding: gzip,deflate" request header and always return uncompressed response | |
// DisableCompression disables GZIP compression HTTP filter from the default Listener filters. | |
// Setting this true will enable Envoy skip "Accept-Encoding: gzip,deflate" request header and always return uncompressed response. |
@@ -0,0 +1 @@ | |||
Add disableCompression boolean flag to disable GZIP compression HTTP filter from the default Listener filters. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changelog entry could mention where the flag can be found
Add disableCompression boolean flag to disable GZIP compression HTTP filter from the default Listener filters. | |
Add disableCompression boolean flag in the ContourConfiguration CRD and in configuration file to disable GZIP compression HTTP filter, forcing Envoy to always return uncompressed response. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry for commenting so late in the process but I think given that there are a lot of compression algorithms supported by envoy. Some of them much better than gzip
like zstd
I think we might want to change the api to allow the user to choose the compression algorithm and have an option called nocompression
that disables it
@davinci26 that's an interesting idea. It goes beyond what was mentioned in #310 which -- although it's far from a formal design process (so early in contour's lifecylce) -- is at least some semblance of a "blessing" of the API change in this PR. If we were to go for the alternative API you proposed (which is IMO richer/better overall), would it require going through the proposal process since it's not something that has been (afaik) so far envisioned/discussed? |
Signed-off-by: Geoff Macartney <[email protected]>
Signed-off-by: Geoff Macartney <[email protected]>
Rework as --compression flag. Signed-off-by: Geoff Macartney <[email protected]>
Hi @davinci26 @tsaarni I have updated the branch according to your comment above, so that it is now possible to request different types of compression, including none. Rather than a separate nocompression flag, I've just provided an additional compression option "disabled". The supported types of compression are those included in go-control-plane/envoy/extensions/compression, namely
This can be configured with the flag In-cluster testsTests against a deployment of "podinfo" on an in-house cluster. out-of-the-box default behaviourAsk for gzip encoding and gunzip the output: ~ [56]$ curl -v -H 'Accept-Encoding: gzip,deflate' $URL/env | gzip -d
...
< HTTP/2 200
< content-type: application/json; charset=utf-8
< x-content-type-options: nosniff
< date: Tue, 08 Oct 2024 13:41:14 GMT
< x-envoy-upstream-service-time: 1
< content-encoding: gzip
< vary: Accept-Encoding
< server: envoy
<
{ [283 bytes data]
100 293 0 293 0 0 1421 0 --:--:-- --:--:-- --:--:-- 1422
...
[
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"HOSTNAME=podinfo-9f86b555d-c6cz7",
"PODINFO_UI_COLOR=#34577c", Note the disabledset the flag in config (we hold values for the config in a configmap): apiVersion: v1
data:
contour.yaml: |-
compression: disabled
accesslog-format: json
... Repeat the command above but this time should get text back and not need to un-gzip: ~ $ curl -v -H 'Accept-Encoding: gzip,deflate' $URL/env
...
< HTTP/2 200
< content-type: application/json; charset=utf-8
< x-content-type-options: nosniff
< date: Tue, 08 Oct 2024 13:50:11 GMT
< content-length: 814
< x-envoy-upstream-service-time: 1
< server: envoy
<
[
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"HOSTNAME=podinfo-9f86b555d-c6cz7",
"PODINFO_UI_COLOR=#34577c",
"PODINFO_SERVICE_HOST=192.168.243.43", No brotliRequest brotli encoding on the response and decode it with the brotli CLI tool: ~ $ curl -v -H 'Accept-Encoding: br,deflate' $URL/env | brotli -d
...
< HTTP/2 200
< content-type: application/json; charset=utf-8
< x-content-type-options: nosniff
< date: Tue, 08 Oct 2024 13:53:45 GMT
< x-envoy-upstream-service-time: 1
< content-encoding: br
< vary: Accept-Encoding
< server: envoy
<
{ [287 bytes data]
100 288 0 288 0 0 1020 0 --:--:-- --:--:-- --:--:-- 1021
...
[
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"HOSTNAME=podinfo-9f86b555d-c6cz7",
"PODINFO_UI_COLOR=#34577c", Note zstdRequest zstd encoding on the response and decode it with the zstd CLI tool: ~ $ curl -v -H 'Accept-Encoding: zstd,deflate' $URL/env | zstd -d
...
< HTTP/2 200
< content-type: application/json; charset=utf-8
< x-content-type-options: nosniff
< date: Tue, 08 Oct 2024 14:03:27 GMT
< x-envoy-upstream-service-time: 1
< content-encoding: zstd
< vary: Accept-Encoding
< server: envoy
<
{ [302 bytes data]
100 302 0 302 0 0 1089 0 --:--:-- --:--:-- --:--:-- 1090
...
[
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"HOSTNAME=podinfo-9f86b555d-c6cz7", Note the Invalid settingTest the validation on the compression setting in contour config. Set an invalid value for the compression flag and restart contour pods. Pods fail to start with a simple error message recording the invalid value: ~ $ kubectl --context sky-pre-dev-euwest1 -n contour-main-external logs contour-contour-6fc5b659c5-22d5g
time="2024-10-08T14:07:11Z" level=info msg="maxprocs: Leaving GOMAXPROCS=16: CPU quota undefined"
contour: error: invalid Contour configuration: invalid compression type: "bogus", try --help |
Could you kindly review and enable the build workflows on this to see if they all pass? In the branch where it was built I was getting an odd error on the upgrade tests, as noted here, and I wasn't sure if that might be because that was just a branch.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some small comments but I think this is in the correct direction
// Values: `gzip` (default), `brotli`, `zstd`, `disabled`. | ||
// Setting this to `disabled` will make Envoy skip "Accept-Encoding: gzip,deflate" request header and always return uncompressed response | ||
// +optional | ||
Compression EnvoyCompressionType `json:"compression,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we use // +kubebuilder:validation:Enum=gzip,brotli,zstd,disabled
as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 sounds good, I will add that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hi @davinci26 added this in f7b261b
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Example:
$ kubectl apply -f - <<-EOF
> apiVersion: projectcontour.io/v1alpha1
kind: ContourConfiguration
metadata:
name: example-contour-config-1
spec:
envoy:
listener:
compression: bogus
EOF
The ContourConfiguration "example-contour-config-1" is invalid: spec.envoy.listener.compression: Unsupported value: "bogus": supported values: "gzip", "brotli", "zstd", "disabled"
// Values: `gzip` (default), `brotli`, `zstd`, `disabled`. | ||
// Setting this to `disabled` will make Envoy skip "Accept-Encoding: gzip,deflate" request header and always return uncompressed response | ||
// +optional | ||
Compression EnvoyCompressionType `json:"compression,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The API here is fairly constrained so we might want to think through how would we extend it if anyone comes up with the feature request to tune the API
on different compression levels
I think adding another field called Compression
Strategy might be fine or create a struct that right now has a single object
Compression *EnvoyCompression `json:"compression,omitempty"`
Member
type EnvoyCompression struct {
Aglorithm Algorithm `json:"algorithm,omitempty"
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did think (briefly) about making the configurability greater, and/or having a wider range of compression algorithms. In the end I decided against it, at least for this PR -
- while one could add more compression algorithms I thought that exposing the ones from
envoy/extensions
was a nice and easily explained choice. There are a couple of others incontrib/envoy/extensions
but gzip/br/zstd seems like the ones that are most likely to be widely wanted. And I certainly didn't want to start thinking about making the algorithm choice be more "pluggable"! - as for configurability of algorithms I thought it wasn't something I felt I wanted to start making decisions on - I expect contour project members would perhaps not want to expose all the configuration options for every algorithm, but then this leaves you with the question of how to sensibly define some configuration that supports enough configurability for the different algorithms. It felt like a bit of a rabbit hole and I thought it would be something kept separate from this PR - better to try to keep changes as small as possible, and this one is meaty enough already.
Believe it or not I actually took a bit of inspiration from the Contour Philosophy 😆 (I did read around on how to contribute), particularly the bit on Sensible Defaults. I felt these kind of gave permission to simply offer a choice of a few widely used algorithms, using default settings. While a strategy field could be added here, it would be something of a no-op feature unless we took the time to implement at least basic configurability in it. I feel this would be best left to another PR. Would that be OK?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also now that I think of it, the feature here of most interest to us in our project is the compression disabling, so from an admittedly selfish point of view I would like to leave the configurability to a separate bit of work. Like everyone else we're very busy, and I have ended up having to do most of this work in my own time in the evenings and weekends :-(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be transparent I dont want to design how we extend it but I am trying to think through if we leave enough space to extend the api.
In the end I decided against it, at least for this PR
My only issue is that if we go with the approach here and in 3 months we wanted to add another compression
knob then we have two options:
- Make a breaking change which might be fine due to the fact that this is a
v1alpha1
package. - Add the option topline object in
type EnvoyListenerConfig struct
If we think that these are fine options I think the api is good. I am just proponent of adding another struct
that has a single member so we can extend just that struct
Like everyone else we're very busy, and I have ended up having to do most of this work in my own time in the evenings and weekends :-(
Yeah, a lot of the people contributing to this project to this into this capacity so I feel you.
There was a problem hiding this 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 @projectcontour/maintainers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah now that you have laid it out like that I see what you mean. Let me take a look at it, hopefully this wouldn't be too large a change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hi @davinci26 I have taken a stab at this in 5dcdc33, could you have a look and see what you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still need to test this, I see some failures in e2e and will want also to run it on a local cluster, will try to get that done this week and add results in a comment.
cmd/contour/serve.go
Outdated
@@ -471,6 +473,8 @@ func (s *Server) doServe() error { | |||
SocketOptions: contourConfiguration.Envoy.Listener.SocketOptions, | |||
} | |||
|
|||
s.log.WithField("context", "listenerConfig").Infof("compression setting: %s", listenerConfig.Compression) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this from debugging?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually left this in here deliberately - I think it's quite nice to be able to see the choice of algorithm reflected in the initial log output. But if that's not a typical contour thing to do I'll take it out. Let me know what would be preferred.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
took this out in b68f0b1
Signed-off-by: Geoff Macartney <[email protected]>
Signed-off-by: Geoff Macartney <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, I have one api comment
that I left open but I think the code overall lgtm and useful.
@@ -0,0 +1 @@ | |||
Add "compression" flag to set/disable the compression type applied in the default HTTP filter chain. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this might need update as well based on the new api
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
included in 5dcdc33
Signed-off-by: Geoff Macartney <[email protected]>
Signed-off-by: Geoff Macartney <[email protected]>
Avoid NPE in parameters.Validate also tidy flag handling in registerServe, don't set compression struct unless parameter is supplied. Signed-off-by: Geoff Macartney <[email protected]>
Have added one more fix of a test, but I still need to finish testing on-cluster, will update the ticket when I get that completed. |
Signed-off-by: Geoff Macartney <[email protected]>
Signed-off-by: Geoff Macartney <[email protected]>
Signed-off-by: Geoff Macartney <[email protected]>
Signed-off-by: Geoff Macartney <[email protected]>
Signed-off-by: Geoff Macartney <[email protected]>
Hello @davinci26 @tsaarni, I have updated the code per the proposal to support better API extensibility by wrapping the settings in a struct. I believe this PR is ready for review. Some results below from testing on a cluster: defaultout of the box behaviour curl -v -H "Accept-Encoding: gzip,deflate" $URL | gzip -d
...
< HTTP/2 200
< content-type: application/json; charset=utf-8
< x-content-type-options: nosniff
< date: Tue, 29 Oct 2024 09:36:04 GMT
< x-envoy-upstream-service-time: 1
< content-encoding: gzip
< vary: Accept-Encoding
< server: envoy
<
{
"hostname": "podinfo-5bd5b49f6d-n847k", response was gzip. parameter disabledadded to container args: - --compression=disabled curl: $ curl -v -H "Accept-Encoding: gzip,deflate" $URL
< HTTP/2 200
< content-type: application/json; charset=utf-8
< x-content-type-options: nosniff
< date: Tue, 29 Oct 2024 09:40:55 GMT
< content-length: 353
< x-envoy-upstream-service-time: 1
< server: envoy
<
{
"hostname": "podinfo-5bd5b49f6d-n847k", No compression applied, it has been disabled. parameter gzipset container args to have - --compression=gzip curl $ curl -v -H "Accept-Encoding: gzip,deflate" $URL | gzip -d
...
< HTTP/2 200
< content-type: application/json; charset=utf-8
< x-content-type-options: nosniff
< date: Tue, 29 Oct 2024 09:44:05 GMT
< x-envoy-upstream-service-time: 1
< content-encoding: gzip
< vary: Accept-Encoding
< server: envoy
<
{
"hostname": "podinfo-5bd5b49f6d-n847k", parameter brotliset container args to have - --compression=brotli curl $ curl -v -H "Accept-Encoding: br,deflate" $URL | brotli -d
...
< HTTP/2 200
< content-type: application/json; charset=utf-8
< x-content-type-options: nosniff
< date: Tue, 29 Oct 2024 09:46:35 GMT
< x-envoy-upstream-service-time: 2
< content-encoding: br
< vary: Accept-Encoding
< server: envoy
<
{
"hostname": "podinfo-5bd5b49f6d-n847k", brotli encoding applied parameter zstdset container args with - --compression=zstd curl $ curl -v -H "Accept-Encoding: zstd,deflate" $URL | zstd -d
...
< HTTP/2 200
< content-type: application/json; charset=utf-8
< x-content-type-options: nosniff
< date: Tue, 29 Oct 2024 09:49:23 GMT
< x-envoy-upstream-service-time: 1
< content-encoding: zstd
< vary: Accept-Encoding
< server: envoy
<
{
"hostname": "podinfo-5bd5b49f6d-n847k", zstd encoding applied config disabledRemove compression flag from container args and set config map to have: apiVersion: v1
data:
contour.yaml: |-
compression:
algorithm: disabled
... Restart contour pods. Do curl requesting gzip $ curl -v -H "Accept-Encoding: gzip,deflate" $URL
...
< HTTP/2 200
< content-type: application/json; charset=utf-8
< x-content-type-options: nosniff
< date: Tue, 29 Oct 2024 09:54:23 GMT
< content-length: 353
< x-envoy-upstream-service-time: 1
< server: envoy
<
{
"hostname": "podinfo-5bd5b49f6d-n847k",
"version": "6.0.0", compression is disabled. config gzipedit config apiVersion: v1
data:
contour.yaml: |-
compression:
algorithm: gzip
... Restart contour and curl: $ curl -v -H "Accept-Encoding: gzip,deflate" $URL | gzip -d
...
< HTTP/2 200
< content-type: application/json; charset=utf-8
< x-content-type-options: nosniff
< date: Tue, 29 Oct 2024 09:56:37 GMT
< x-envoy-upstream-service-time: 1
< content-encoding: gzip
< vary: Accept-Encoding
< server: envoy
<
{
"hostname": "podinfo-5bd5b49f6d-n847k", response encoded with gzip config brotliedit config to apiVersion: v1
data:
contour.yaml: |-
compression:
algorithm: brotli Restart contour and curl: $ curl -v -H "Accept-Encoding: br,deflate" $URL | brotli -d
...
< HTTP/2 200
< content-type: application/json; charset=utf-8
< x-content-type-options: nosniff
< date: Tue, 29 Oct 2024 09:59:48 GMT
< x-envoy-upstream-service-time: 1
< content-encoding: br
< vary: Accept-Encoding
< server: envoy
{
"hostname": "podinfo-5bd5b49f6d-n847k", config zstdedit config to apiVersion: v1
data:
contour.yaml: |-
compression:
algorithm: zstd curl: $ curl -v -H "Accept-Encoding: zstd,deflate" $URL | zstd -d
...
< HTTP/2 200
< content-type: application/json; charset=utf-8
< x-content-type-options: nosniff
< date: Tue, 29 Oct 2024 10:29:20 GMT
< x-envoy-upstream-service-time: 1
< content-encoding: zstd
< vary: Accept-Encoding
< server: envoy
<
{
"hostname": "podinfo-5bd5b49f6d-n847k", zstd compression applied. |
Hello @tsaarni, @davinci26, would you be able to review this? Thanks. |
@geomacy will take a look later today. |
For #6511
This PR adds,
Related #310, there had been mentions about disabling compression, the ticket we had raised shows the reason where disabling compression can bring cost benefits.