From 0ff49e5057f444b60036ffaf7e6a4bdaa0dbc399 Mon Sep 17 00:00:00 2001 From: Yusuke Kuoka Date: Mon, 4 Nov 2019 14:10:50 +0900 Subject: [PATCH 1/2] feat: Add H2C support `podinfo --h2c` allows upgrading a HTTP/1.1 connection to HTTP/2 Cleartext. This allows `podinfo` to be used in e.g. a H2C load-test like `echo "GET http://localhost:9898/status/200" | vegeta -h2c`, or a H2C connectivity test like done with `curl -v http2 http://localhost:9898/status/200`. I have manually verified this to work by running `curl -v --http2` on macOS and seeing the H2C upgrade happens onl when `-h2c` is provided to `podinfo`. Without `-h2c`: ``` $ curl -v --http2 localhost:9898/status/200 * Trying ::1... * TCP_NODELAY set * Connected to localhost (::1) port 9898 (#0) > GET /status/200 HTTP/1.1 > Host: localhost:9898 > User-Agent: curl/7.54.0 > Accept: */* > Connection: Upgrade, HTTP2-Settings > Upgrade: h2c > HTTP2-Settings: AAMAAABkAARAAAAAAAIAAAAA > < HTTP/1.1 200 OK < Content-Type: application/json; charset=utf-8 < X-Content-Type-Options: nosniff < Date: Mon, 04 Nov 2019 04:58:01 GMT < Content-Length: 19 < { "status": 200 * Connection #0 to host localhost left intact } ``` With `-h2c`: ``` $ curl -v --http2 localhost:9898/status/200 * Trying ::1... * TCP_NODELAY set * Connected to localhost (::1) port 9898 (#0) > GET /status/200 HTTP/1.1 > Host: localhost:9898 > User-Agent: curl/7.54.0 > Accept: */* > Connection: Upgrade, HTTP2-Settings > Upgrade: h2c > HTTP2-Settings: AAMAAABkAARAAAAAAAIAAAAA > < HTTP/1.1 101 Switching Protocols < Connection: Upgrade < Upgrade: h2c * Received 101 * Using HTTP2, server supports multi-use * Connection state changed (HTTP/2 confirmed) * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0 * Connection state changed (MAX_CONCURRENT_STREAMS updated)! < HTTP/2 200 < content-type: application/json; charset=utf-8 < x-content-type-options: nosniff < content-length: 19 < date: Mon, 04 Nov 2019 04:58:28 GMT < { "status": 200 * Connection #0 to host localhost left intact } ` --- cmd/podinfo/main.go | 1 + go.mod | 2 +- pkg/api/server.go | 13 ++++++++++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/cmd/podinfo/main.go b/cmd/podinfo/main.go index 2f1aeff..a53db35 100644 --- a/cmd/podinfo/main.go +++ b/cmd/podinfo/main.go @@ -39,6 +39,7 @@ func main() { fs.String("ui-logo", "", "UI logo") fs.String("ui-color", "cyan", "UI color") fs.String("ui-message", fmt.Sprintf("greetings from podinfo v%v", version.VERSION), "UI message") + fs.Bool("h2c", false, "Allow upgrading to H2C") fs.Bool("random-delay", false, "between 0 and 5 seconds random delay") fs.Bool("random-error", false, "1/3 chances of a random response error") fs.Int("stress-cpu", 0, "Number of CPU cores with 100 load") diff --git a/go.mod b/go.mod index 0ce6c67..e22818e 100644 --- a/go.mod +++ b/go.mod @@ -47,6 +47,6 @@ require ( go.uber.org/atomic v1.3.2 // indirect go.uber.org/multierr v1.1.0 // indirect go.uber.org/zap v1.9.1 - golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 // indirect + golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 google.golang.org/grpc v1.23.0 ) diff --git a/pkg/api/server.go b/pkg/api/server.go index df71f6a..b5aa67d 100644 --- a/pkg/api/server.go +++ b/pkg/api/server.go @@ -4,6 +4,9 @@ import ( "context" "fmt" "github.com/swaggo/swag" + "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" + "net/http" _ "net/http/pprof" "os" @@ -59,6 +62,7 @@ type Config struct { Port string `mapstructure:"port"` PortMetrics int `mapstructure:"port-metrics"` Hostname string `mapstructure:"hostname"` + H2C bool `mapstructure:"h2c"` RandomDelay bool `mapstructure:"random-delay"` RandomError bool `mapstructure:"random-error"` JWTSecret string `mapstructure:"jwt-secret"` @@ -141,12 +145,19 @@ func (s *Server) ListenAndServe(stopCh <-chan struct{}) { s.registerHandlers() s.registerMiddlewares() + var handler http.Handler + if s.config.H2C { + handler = h2c.NewHandler(s.router, &http2.Server{}) + } else { + handler = s.router + } + srv := &http.Server{ Addr: ":" + s.config.Port, WriteTimeout: s.config.HttpServerTimeout, ReadTimeout: s.config.HttpServerTimeout, IdleTimeout: 2 * s.config.HttpServerTimeout, - Handler: s.router, + Handler: handler, } //s.printRoutes() From a8260081d93a64dd8dd15a3329a03fe44bb63dca Mon Sep 17 00:00:00 2001 From: Yusuke Kuoka Date: Mon, 4 Nov 2019 14:17:10 +0900 Subject: [PATCH 2/2] Add `h2c.enabled` to chart for toggling H2C upgrading support --- charts/podinfo/templates/deployment.yaml | 3 +++ charts/podinfo/values.yaml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/charts/podinfo/templates/deployment.yaml b/charts/podinfo/templates/deployment.yaml index dbe4a48..d8160e3 100644 --- a/charts/podinfo/templates/deployment.yaml +++ b/charts/podinfo/templates/deployment.yaml @@ -54,6 +54,9 @@ spec: - --level={{ .Values.logLevel }} - --random-delay={{ .Values.faults.delay }} - --random-error={{ .Values.faults.error }} + {{- if .Values.h2c.enabled }} + - --h2c + {{- end }} env: {{- if .Values.ui.message }} - name: PODINFO_UI_MESSAGE diff --git a/charts/podinfo/values.yaml b/charts/podinfo/values.yaml index 918bcb1..b358c98 100644 --- a/charts/podinfo/values.yaml +++ b/charts/podinfo/values.yaml @@ -14,6 +14,9 @@ faults: delay: false error: false +h2c: + enabled: false + image: repository: stefanprodan/podinfo tag: 3.1.3