Compare commits

...

9 Commits
3.1.3 ... 3.1.5

Author SHA1 Message Date
stefanprodan
948de81ed3 Update manifests to v3.1.5 2019-12-26 15:45:17 +02:00
stefanprodan
78658c0311 Release v3.1.5 cuddle edition 2019-11-07 00:31:49 +02:00
stefanprodan
7b6f11780a Rename GitHub workflow for kustomize testing 2019-11-04 09:59:11 +02:00
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
15 changed files with 160 additions and 23 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: test
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

@@ -12,7 +12,7 @@ VERSION:=$(shell grep 'VERSION' pkg/version/version.go | awk '{ print $$4 }' | t
run:
GO111MODULE=on go run -ldflags "-s -w -X github.com/stefanprodan/podinfo/pkg/version.REVISION=$(GIT_COMMIT)" cmd/podinfo/* \
--level=debug --grpc-port=9999 --backend-url=https://httpbin.org/status/401 --backend-url=https://httpbin.org/status/500 \
--ui-logo=https://media.giphy.com/media/l0ExbNdlJFGRphMR2/giphy.gif
--ui-logo=https://raw.githubusercontent.com/stefanprodan/podinfo/gh-pages/cuddle_clap.gif --ui-color=#34577c
test:
GO111MODULE=on go test -v -race ./...

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:
@@ -51,7 +53,7 @@ gRPC API:
Web UI:
![podinfo-ui](https://raw.githubusercontent.com/stefanprodan/podinfo/gh-pages/screens/podinfo-ui.png)
![podinfo-ui](https://raw.githubusercontent.com/stefanprodan/podinfo/gh-pages/screens/podinfo-ui-v3.png)
To access the Swagger UI open `<podinfo-host>/swagger/index.html` in a browser.
@@ -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.5
appVersion: 3.1.5
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

@@ -5,7 +5,7 @@ metadata:
name: {{ template "podinfo.fullname" . }}
spec:
scaleTargetRef:
apiVersion: apps/v1beta2
apiVersion: apps/v1
kind: Deployment
name: {{ template "podinfo.fullname" . }}
minReplicas: {{ .Values.replicaCount }}

View File

@@ -6,7 +6,7 @@ backend: #http://backend-podinfo:9898/echo
backends: []
ui:
color: "cyan"
color: "#34577c"
message: ""
logo: ""
@@ -14,9 +14,12 @@ faults:
delay: false
error: false
h2c:
enabled: false
image:
repository: stefanprodan/podinfo
tag: 3.1.3
tag: 3.1.5
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")
@@ -65,7 +66,7 @@ func main() {
viper.RegisterAlias("backendUrl", "backend-url")
hostname, _ := os.Hostname()
viper.SetDefault("jwt-secret", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9")
viper.SetDefault("ui-logo", "https://d33wubrfki0l68.cloudfront.net/33a12d8be0bc50be4738443101616e968c7afb8f/cba76/images/scalable.png")
viper.SetDefault("ui-logo", "https://raw.githubusercontent.com/stefanprodan/podinfo/gh-pages/cuddle_clap.gif")
viper.Set("hostname", hostname)
viper.Set("version", version.VERSION)
viper.Set("revision", version.REVISION)

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.5
imagePullPolicy: IfNotPresent
ports:
- name: http
@@ -48,7 +48,7 @@ spec:
- --random-error=false
env:
- name: PODINFO_UI_COLOR
value: cyan
value: "#34577c"
livenessProbe:
exec:
command:

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.5"
var REVISION = "unknown"

View File

@@ -10,8 +10,11 @@
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
<style>
[v-cloak] {
display: none;
}
display: none;
}
.v-application .v-parallax {
height: 100vh !important;
}
</style>
</head>
<body>
@@ -19,14 +22,14 @@
<v-app dark>
<v-content>
<section>
<v-parallax id="parallax-hero" src="https://upload.wikimedia.org/wikipedia/commons/c/ca/1x1.png" :class="info.color">
<v-parallax id="parallax-hero" :style="cuddleStyle" src="https://upload.wikimedia.org/wikipedia/commons/c/ca/1x1.png">
<v-layout
column
align-center
justify-center
class="white--text"
>
<img :src="info.logo" alt="kubernetes" height="200">
<img :src="info.logo" height="350">
<h1 class="white--text mb-2 display-1 text-xs-center">${ info.message }</h1>
<div class="subheading mb-3 text-xs-center">Served by <b>${ info.hostname }</b></div>
<v-btn
@@ -86,11 +89,11 @@
tlColor1: 'grey',
tlName2: '',
tlColor2: 'grey',
cuddleStyle: {
backgroundColor: '#34577c'
},
}
},
mounted: function() {
document.getElementById('parallax-hero').style.height = '100vh'
},
created: function() {
this.getInfo();
this.timer = setInterval(this.getInfo, 3000)
@@ -109,6 +112,9 @@
}
self.info = data
self.info.color = data.color
self.cuddleStyle = {
backgroundColor: data.color
}
self.info.logo = data.logo
document.title = data.hostname
let verColor = (parseInt(data.version.split('.').reverse()[0], 10) % 2 === 0)