Compare commits

..

6 Commits
3.1.3 ... 3.1.4

Author SHA1 Message Date
stefanprodan
d65044ff2e Release v3.1.4 2019-11-04 09:22:36 +02:00
Stefan Prodan
18c63ad7f7 Merge pull request #42 from mumoshu/h2c
feat: Add H2C support
2019-11-04 09:16:12 +02:00
Yusuke Kuoka
a8260081d9 Add h2c.enabled to chart for toggling H2C upgrading support 2019-11-04 14:17:10 +09:00
Yusuke Kuoka
0ff49e5057 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
}
`
2019-11-04 14:10:50 +09:00
Stefan Prodan
79cfe56484 Merge pull request #41 from stefanprodan/gh-actions
Add GitHub workflow for manifests validation
2019-10-23 17:35:53 +03:00
stefanprodan
7e36892e26 Add GitHub workflow for manifests validation
- validate kustomize build with kubeval strict mode
- deny containers with latest image tag
- deny deployments and services without app label selector
- warn if deployments have no prometheus pod annotations
2019-10-23 17:10:21 +03:00
12 changed files with 141 additions and 10 deletions

51
.github/policy/kubernetes.rego vendored Normal file
View File

@@ -0,0 +1,51 @@
package kubernetes
name = input.metadata.name
kind = input.kind
is_service {
input.kind = "Service"
}
is_deployment {
input.kind = "Deployment"
}
is_pod {
input.kind = "Pod"
}
split_image(image) = [image, "latest"] {
not contains(image, ":")
}
split_image(image) = [image_name, tag] {
[image_name, tag] = split(image, ":")
}
pod_containers(pod) = all_containers {
keys = {"containers", "initContainers"}
all_containers = [c | keys[k]; c = pod.spec[k][_]]
}
containers[container] {
pods[pod]
all_containers = pod_containers(pod)
container = all_containers[_]
}
containers[container] {
all_containers = pod_containers(input)
container = all_containers[_]
}
pods[pod] {
is_deployment
pod = input.spec.template
}
pods[pod] {
is_pod
pod = input
}

43
.github/policy/rules.rego vendored Normal file
View File

@@ -0,0 +1,43 @@
package main
import data.kubernetes
name = input.metadata.name
# Deny containers with latest image tag
deny[msg] {
kubernetes.containers[container]
[image_name, "latest"] = kubernetes.split_image(container.image)
msg = sprintf("%s in the %s %s has an image %s, using the latest tag", [container.name, kubernetes.kind, kubernetes.name, image_name])
}
# Deny services without app label selector
service_labels {
input.spec.selector["app"]
}
deny[msg] {
kubernetes.is_service
not service_labels
msg = sprintf("Service %s should set app label selector", [name])
}
# Deny deployments without app label selector
match_labels {
input.spec.selector.matchLabels["app"]
}
deny[msg] {
kubernetes.is_deployment
not match_labels
msg = sprintf("Service %s should set app label selector", [name])
}
# Warn if deployments have no prometheus pod annotations
annotations {
input.spec.template.metadata.annotations["prometheus.io/scrape"]
input.spec.template.metadata.annotations["prometheus.io/port"]
}
warn[msg] {
kubernetes.is_deployment
not annotations
msg = sprintf("Deployment %s should set prometheus.io/scrape and prometheus.io/port pod annotations", [name])
}

17
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
on: [push, pull_request]
name: kustomize
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: kubeval
uses: stefanprodan/kube-tools@v1
with:
command: |
kustomize build ./kustomize | kubeval --strict
- name: conftest
uses: stefanprodan/kube-tools@v1
with:
command: |
kustomize build ./kustomize | conftest test -p .github/policy -

View File

@@ -1,6 +1,7 @@
# podinfo
[![CircleCI](https://circleci.com/gh/stefanprodan/podinfo.svg?style=svg)](https://circleci.com/gh/stefanprodan/podinfo)
[![conftest](https://github.com/stefanprodan/podinfo/workflows/test/badge.svg)](https://github.com/stefanprodan/podinfo/blob/master/.github/workflows/test.yml)
[![Go Report Card](https://goreportcard.com/badge/github.com/stefanprodan/podinfo)](https://goreportcard.com/report/github.com/stefanprodan/podinfo)
[![Docker Pulls](https://img.shields.io/docker/pulls/stefanprodan/podinfo)](https://hub.docker.com/r/stefanprodan/podinfo)
@@ -20,6 +21,7 @@ Specifications:
* Swagger docs
* Helm and Kustomize installers
* End-to-End testing with Kubernetes Kind and Helm
* Kustomize testing with GitHub Actions and Open Policy Agent
Web API:
@@ -67,20 +69,20 @@ To access the Swagger UI open `<podinfo-host>/swagger/index.html` in a browser.
Helm:
```bash
helm repo add sp https://stefanprodan.github.io/podinfo
helm repo add podinfo https://stefanprodan.github.io/podinfo
helm upgrade --install --wait frontend \
--namespace test \
--set replicaCount=2 \
--set backend=http://backend-podinfo:9898/echo \
sp/podinfo
podinfo/podinfo
helm test frontend --cleanup
helm upgrade --install --wait backend \
--namespace test \
--set hpa.enabled=true \
sp/podinfo
podinfo/podinfo
```
Kustomize:

View File

@@ -1,6 +1,6 @@
apiVersion: v1
version: 3.1.3
appVersion: 3.1.3
version: 3.1.4
appVersion: 3.1.4
name: podinfo
engine: gotpl
description: Podinfo Helm chart for Kubernetes

View File

@@ -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

View File

@@ -14,9 +14,12 @@ faults:
delay: false
error: false
h2c:
enabled: false
image:
repository: stefanprodan/podinfo
tag: 3.1.3
tag: 3.1.4
pullPolicy: IfNotPresent
service:

View File

@@ -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")

2
go.mod
View File

@@ -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
)

View File

@@ -25,7 +25,7 @@ spec:
spec:
containers:
- name: podinfod
image: stefanprodan/podinfo:3.1.3
image: stefanprodan/podinfo:3.1.4
imagePullPolicy: IfNotPresent
ports:
- name: http

View File

@@ -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()

View File

@@ -1,4 +1,4 @@
package version
var VERSION = "3.1.3"
var VERSION = "3.1.4"
var REVISION = "unknown"