Compare commits

...

15 Commits
5.0.3 ... 5.1.1

Author SHA1 Message Date
Stefan Prodan
9f4d31a8c4 Merge pull request #111 from stefanprodan/release-v5.1.1
Release v5.1.1
2020-12-09 11:11:53 +02:00
Stefan Prodan
95eafd32f9 Release v5.1.1
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-12-09 10:25:36 +02:00
Stefan Prodan
86dbbf7254 Merge pull request #109 from ut8ia/patch-1
Issue : silence on config file missing error
2020-12-08 18:05:26 +02:00
Stefan Prodan
b13ec2ddb4 Merge pull request #110 from stefanprodan/release-v5.1.0
Release v5.1.0
2020-12-08 17:43:37 +02:00
Stefan Prodan
0f7a876dae Release v5.1.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-12-08 17:36:23 +02:00
Eugene Anufriev
837ff33ee0 Issue : silence on config file missing error
Any information in case when config file not exist or path\filename configured incorrectly.
It is not clear now.
Propose: handle such situation and inform about that.
2020-12-02 17:46:56 +02:00
Stefan Prodan
4735f54368 Merge pull request #108 from dmccaffery/feat/secure-port-chart
feat(charts): add tls support to helm chart
2020-11-20 15:43:54 +02:00
Deavon M. McCaffery
35c9128bca fix(charts): fix default tls port in deployment 2020-11-19 15:41:06 +00:00
Deavon M. McCaffery
411bce81c0 build: update e2e tests to validate secure-port
* pull out script blocks into `hack` path
* update e2e workflow to use scripts in `hack`
* install cert manager and self-signed cluster issuer in e2e
* deploy podinfo with secure port and certificate enabled
* add `hack/e2e.sh` script, which can be used to execute the github
  workflow locally
2020-11-19 03:04:36 +00:00
Deavon M. McCaffery
1ac286c3b0 feat(charts): add tls support to helm chart
* add tls variable block to configure service and pod with secure-port
* add ability to create cert-manager certificate
* add support for host ports (both http and https)
* add helm test for tls port
* add example values for secure-port deployment
  - this assumes certificate manager is deployed to the cluster
2020-11-19 02:46:25 +00:00
Stefan Prodan
b496853d32 Merge pull request #106 from dmccaffery/feat/secure-port
feat(podinfo): add secure port for end-to-end tls
2020-11-18 15:16:19 +02:00
Deavon M. McCaffery
9ca49aa442 build: replace add-path with environment files 2020-11-18 12:44:58 +00:00
Deavon M. McCaffery
bc809cd763 docs(deploy): add script to test podinfo using kind 2020-11-17 23:04:55 +00:00
Deavon M. McCaffery
046ac8a4a5 docs(deploy): add kube manifests for secure-port example 2020-11-17 23:04:35 +00:00
Deavon M. McCaffery
c38f357872 feat(podinfo): add secure port for end-to-end tls
* add `secure-port` argument to podinfo
* add `cert-path` argument to podinfo
* add http server for secure port
* normalise http/https server start
2020-11-17 23:01:41 +00:00
38 changed files with 802 additions and 58 deletions

View File

@@ -20,5 +20,6 @@ main() {
}
main
echo "::add-path::$BIN_DIR"
echo "::add-path::$RUNNER_WORKSPACE/$(basename $GITHUB_REPOSITORY)/bin"
echo "$BIN_DIR" >> $GITHUB_PATH
echo "$RUNNER_WORKSPACE/$(basename $GITHUB_REPOSITORY)/bin" >> $GITHUB_PATH

View File

@@ -18,11 +18,10 @@ jobs:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Kubernetes
uses: engineerd/setup-kind@v0.4.0
uses: engineerd/setup-kind@v0.5.0
- name: Build container image
run: |
GIT_COMMIT=$(git rev-list -1 HEAD) && \
docker build -t test/podinfo:latest --build-arg "REVISION=${GIT_COMMIT}" .
./hack/build.sh
kind load docker-image test/podinfo:latest
- name: Setup Helm
uses: ./.github/actions/helm
@@ -30,20 +29,11 @@ jobs:
helm-version: ${{ matrix.helm-version }}
- name: Install Tiller
if: ${{ startsWith(matrix.helm-version, '2') }}
run: |
kubectl --namespace kube-system create sa tiller
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
helm init --service-account tiller --upgrade --wait
run: ./hack/tiller.sh
- name: Deploy
run: |
helm upgrade -i podinfo ./charts/podinfo \
--set image.repository=test/podinfo \
--set image.tag=latest \
--namespace=default
run: ./hack/deploy.sh
- name: Run integration tests
run: |
kubectl rollout status deployment/podinfo --timeout=1m
helm test podinfo
run: ./hack/test.sh
- name: Debug failure
if: failure()
run: |

View File

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

View File

@@ -59,3 +59,11 @@ Create the name of the service account to use
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
{{/*
Create the name of the tls secret for secure port
*/}}
{{- define "podinfo.tlsSecretName" -}}
{{- $fullname := include "podinfo.fullname" . -}}
{{- default (printf "%s-tls" $fullname) .Values.tls.secretName }}
{{- end }}

View File

@@ -0,0 +1,16 @@
{{- if .Values.certificate.create -}}
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: {{ template "podinfo.fullname" . }}
labels:
{{- include "podinfo.labels" . | nindent 4 }}
spec:
dnsNames:
{{- range .Values.certificate.dnsNames }}
- {{ . | quote }}
{{- end }}
secretName: {{ template "podinfo.tlsSecretName" . }}
issuerRef:
{{- .Values.certificate.issuerRef | toYaml | trimSuffix "\n" | nindent 4 }}
{{- end }}

View File

@@ -34,9 +34,24 @@ spec:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
{{- if (or .Values.service.hostPort .Values.tls.hostPort) }}
securityContext:
allowPrivilegeEscalation: true
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
{{- end }}
command:
- ./podinfo
- --port={{ .Values.service.httpPort | default 9898 }}
{{- if .Values.tls.enabled }}
- --secure-port={{ .Values.tls.port }}
{{- end }}
{{- if .Values.tls.certPath }}
- --cert-path={{ .Values.tls.certPath }}
{{- end }}
{{- if .Values.service.metricsPort }}
- --port-metrics={{ .Values.service.metricsPort }}
{{- end }}
@@ -87,6 +102,17 @@ spec:
- name: http
containerPort: {{ .Values.service.httpPort | default 9898 }}
protocol: TCP
{{- if .Values.service.hostPort }}
hostPort: {{ .Values.service.hostPort }}
{{- end }}
{{- if .Values.tls.enabled }}
- name: https
containerPort: {{ .Values.tls.port | default 9899 }}
protocol: TCP
{{- if .Values.tls.hostPort }}
hostPort: {{ .Values.tls.hostPort }}
{{- end }}
{{- end }}
{{- if .Values.service.metricsPort }}
- name: http-metrics
containerPort: {{ .Values.service.metricsPort }}
@@ -118,6 +144,11 @@ spec:
volumeMounts:
- name: data
mountPath: /data
{{- if .Values.tls.enabled }}
- name: tls
mountPath: {{ .Values.tls.certPath | default "/data/cert" }}
readOnly: true
{{- end }}
resources:
{{ toYaml .Values.resources | indent 12 }}
{{- with .Values.nodeSelector }}
@@ -135,3 +166,8 @@ spec:
volumes:
- name: data
emptyDir: {}
{{- if .Values.tls.enabled }}
- name: tls
secret:
secretName: {{ template "podinfo.tlsSecretName" . }}
{{- end }}

View File

@@ -15,6 +15,12 @@ spec:
{{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }}
nodePort: {{ .Values.service.nodePort }}
{{- end }}
{{- if .Values.tls.enabled }}
- port: {{ .Values.tls.port | default 9899 }}
targetPort: https
protocol: TCP
name: https
{{- end }}
{{- if .Values.service.grpcPort }}
- port: {{ .Values.service.grpcPort }}
targetPort: grpc

View File

@@ -0,0 +1,27 @@
{{- if .Values.tls.enabled -}}
apiVersion: v1
kind: Pod
metadata:
name: {{ template "podinfo.fullname" . }}-tls-test-{{ randAlphaNum 5 | lower }}
labels:
{{- include "podinfo.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test-success
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
sidecar.istio.io/inject: "false"
linkerd.io/inject: disabled
appmesh.k8s.aws/sidecarInjectorWebhook: disabled
spec:
containers:
- name: curl
image: curlimages/curl:7.69.0
command:
- sh
- -c
- |
curl -sk ${PODINFO_SVC}/api/info | grep version
env:
- name: PODINFO_SVC
value: "https://{{ template "podinfo.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.tls.port }}"
restartPolicy: Never
{{- end }}

View File

@@ -23,7 +23,7 @@ h2c:
image:
repository: ghcr.io/stefanprodan/podinfo
tag: 5.0.3
tag: 5.1.1
pullPolicy: IfNotPresent
service:

View File

@@ -0,0 +1,127 @@
# Default values for podinfo.
replicaCount: 1
logLevel: info
backend: #http://backend-podinfo:9898/echo
backends: []
ui:
color: "#34577c"
message: ""
logo: ""
faults:
delay: false
error: false
unhealthy: false
unready: false
testFail: false
testTimeout: false
h2c:
enabled: false
image:
repository: ghcr.io/stefanprodan/podinfo
tag: 5.0.3
pullPolicy: IfNotPresent
service:
enabled: true
type: ClusterIP
metricsPort: 9797
httpPort: 9898
externalPort: 9898
grpcPort: 9999
grpcService: podinfo
nodePort: 31198
# the port used to bind the http port to the host
# NOTE: requires privileged container with NET_BIND_SERVICE capability -- this is useful for testing
# in local clusters such as kind without port forwarding
hostPort:
# enable tls on the podinfo service
tls:
enabled: true
# the name of the secret used to mount the certificate key pair
secretName:
# the path where the certificate key pair will be mounted
certPath: /data/cert
# the port used to host the tls endpoint on the service
port: 9899
# the port used to bind the tls port to the host
# NOTE: requires privileged container with NET_BIND_SERVICE capability -- this is useful for testing
# in local clusters such as kind without port forwarding
hostPort:
# create a certificate manager certificate
certificate:
create: true
# the issuer used to issue the certificate
issuerRef:
kind: ClusterIssuer
name: self-signed
# the hostname / subject alternative names for the certificate
dnsNames:
- podinfo
# metrics-server add-on required
hpa:
enabled: false
maxReplicas: 10
# average total CPU usage per pod (1-100)
cpu:
# average memory usage per pod (100Mi-1Gi)
memory:
# average http requests per second per pod (k8s-prometheus-adapter)
requests:
# Redis address in the format <host>:<port>
cache: ""
# Redis deployment
redis:
enabled: false
repository: redis
tag: 6.0.8
serviceAccount:
# Specifies whether a service account should be created
enabled: false
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name:
linkerd:
profile:
enabled: false
serviceMonitor:
enabled: false
interval: 15s
ingress:
enabled: false
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
path: /*
hosts: []
# - podinfo.local
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
resources:
limits:
requests:
cpu: 1m
memory: 16Mi
nodeSelector: {}
tolerations: []
affinity: {}
podAnnotations: {}

View File

@@ -23,7 +23,7 @@ h2c:
image:
repository: ghcr.io/stefanprodan/podinfo
tag: 5.0.3
tag: 5.1.1
pullPolicy: IfNotPresent
service:
@@ -35,6 +35,35 @@ service:
grpcPort: 9999
grpcService: podinfo
nodePort: 31198
# the port used to bind the http port to the host
# NOTE: requires privileged container with NET_BIND_SERVICE capability -- this is useful for testing
# in local clusters such as kind without port forwarding
hostPort:
# enable tls on the podinfo service
tls:
enabled: false
# the name of the secret used to mount the certificate key pair
secretName:
# the path where the certificate key pair will be mounted
certPath: /data/cert
# the port used to host the tls endpoint on the service
port: 9899
# the port used to bind the tls port to the host
# NOTE: requires privileged container with NET_BIND_SERVICE capability -- this is useful for testing
# in local clusters such as kind without port forwarding
hostPort:
# create a certificate manager certificate
certificate:
create: false
# the issuer used to issue the certificate
issuerRef:
kind: ClusterIssuer
name: self-signed
# the hostname / subject alternative names for the certificate
dnsNames:
- podinfo
# metrics-server add-on required
hpa:

View File

@@ -24,6 +24,7 @@ func main() {
// flags definition
fs := pflag.NewFlagSet("default", pflag.ContinueOnError)
fs.Int("port", 9898, "HTTP port")
fs.Int("secure-port", 0, "HTTPS port")
fs.Int("port-metrics", 0, "metrics port")
fs.Int("grpc-port", 0, "gRPC port")
fs.String("grpc-service-name", "podinfo", "gPRC service name")
@@ -34,6 +35,7 @@ func main() {
fs.Duration("http-server-shutdown-timeout", 5*time.Second, "server graceful shutdown timeout duration")
fs.String("data-path", "/data", "data local path")
fs.String("config-path", "", "config dir path")
fs.String("cert-path", "/data/cert", "certificate path for HTTPS port")
fs.String("config", "config.yaml", "config file name")
fs.String("ui-path", "./ui", "UI local path")
fs.String("ui-logo", "", "UI logo")
@@ -81,12 +83,14 @@ func main() {
viper.AutomaticEnv()
// load config from file
if _, err := os.Stat(filepath.Join(viper.GetString("config-path"), viper.GetString("config"))); err == nil {
if _, fileErr := os.Stat(filepath.Join(viper.GetString("config-path"), viper.GetString("config"))); fileErr == nil {
viper.SetConfigName(strings.Split(viper.GetString("config"), ".")[0])
viper.AddConfigPath(viper.GetString("config-path"))
if err := viper.ReadInConfig(); err != nil {
fmt.Printf("Error reading config file, %v\n", err)
if readErr := viper.ReadInConfig(); readErr != nil {
fmt.Printf("Error reading config file, %v\n", readErr)
}
}else{
fmt.Printf("Error to open config file, %v\n",fileErr)
}
// configure logging
@@ -104,6 +108,12 @@ func main() {
viper.Set("port", strconv.Itoa(port))
}
// validate secure port
if _, err := strconv.Atoi(viper.GetString("secure-port")); err != nil {
securePort, _ := fs.GetInt("secure-port")
viper.Set("secure-port", strconv.Itoa(securePort))
}
// validate random delay options
if viper.GetInt("random-delay-max") < viper.GetInt("random-delay-min") {
logger.Panic("`--random-delay-max` should be greater than `--random-delay-min`")

View File

@@ -1,6 +1,7 @@
# Deploy demo webapp
# Deploy demo webapp
Demo webapp manifests:
- [common](webapp/common)
- [frontend](webapp/frontend)
- [backend](webapp/backend)
@@ -30,3 +31,15 @@ Deploy the demo in the `production` namespace:
```bash
kustomize build ./overlays/production | kubectl apply -f-
```
## Testing Locally Using Kind
> NOTE: You can install [kind from here](https://kind.sigs.k8s.io/docs/user/quick-start/#installation)
The following will create a new cluster called "podinfo" and configure host ports on 80 and 443. You can access the
endpoints on localhost. The example also deploys cert-manager within the cluster along with a self-signed cluster issuer
used to generate the certificate to validate the secure port.
```sh
./kind.sh
```

View File

@@ -23,7 +23,7 @@ spec:
spec:
containers:
- name: backend
image: ghcr.io/stefanprodan/podinfo:5.0.3
image: ghcr.io/stefanprodan/podinfo:5.1.1
imagePullPolicy: IfNotPresent
ports:
- name: http

View File

@@ -23,7 +23,7 @@ spec:
spec:
containers:
- name: frontend
image: ghcr.io/stefanprodan/podinfo:5.0.3
image: ghcr.io/stefanprodan/podinfo:5.1.1
imagePullPolicy: IfNotPresent
ports:
- name: http

33
deploy/kind.sh Executable file
View File

@@ -0,0 +1,33 @@
#! /usr/bin/env sh
# create the kind cluster
kind create cluster --config=kind.yaml
# add certificate manager
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.0.4/cert-manager.yaml
# wait for cert manager
kubectl rollout status --namespace cert-manager deployment/cert-manager --timeout=2m
kubectl rollout status --namespace cert-manager deployment/cert-manager-webhook --timeout=2m
kubectl rollout status --namespace cert-manager deployment/cert-manager-cainjector --timeout=2m
# # apply the secure webapp
kubectl apply -f ./secure/common
kubectl apply -f ./secure/backend
kubectl apply -f ./secure/frontend
# # wait for the podinfo frontend to come up
kubectl rollout status --namespace secure deployment/frontend --timeout=1m
# curl the endpoints (responds with info due to header regexp on route handler)
echo
echo "http enpdoint:"
echo "curl http://localhost"
echo
curl http://localhost
echo
echo "https (secure) enpdoint:"
echo "curl --insecure https://localhost"
echo
curl --insecure https://localhost

11
deploy/kind.yaml Normal file
View File

@@ -0,0 +1,11 @@
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP

View File

@@ -0,0 +1,74 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace: secure
spec:
minReadySeconds: 3
revisionHistoryLimit: 5
progressDeadlineSeconds: 60
strategy:
rollingUpdate:
maxUnavailable: 0
type: RollingUpdate
selector:
matchLabels:
app: backend
template:
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9797"
labels:
app: backend
spec:
serviceAccountName: secure
containers:
- name: backend
image: ghcr.io/stefanprodan/podinfo:5.0.3
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 9898
protocol: TCP
- name: http-metrics
containerPort: 9797
protocol: TCP
- name: grpc
containerPort: 9999
protocol: TCP
command:
- ./podinfo
- --port=9898
- --port-metrics=9797
- --grpc-port=9999
- --grpc-service-name=backend
- --level=info
env:
- name: PODINFO_UI_COLOR
value: "#34577c"
livenessProbe:
exec:
command:
- podcli
- check
- http
- localhost:9898/healthz
initialDelaySeconds: 5
timeoutSeconds: 5
readinessProbe:
exec:
command:
- podcli
- check
- http
- localhost:9898/readyz
initialDelaySeconds: 5
timeoutSeconds: 5
resources:
limits:
cpu: 2000m
memory: 512Mi
requests:
cpu: 100m
memory: 32Mi

View File

@@ -0,0 +1,19 @@
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: backend
namespace: secure
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: backend
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 99

View File

@@ -0,0 +1,18 @@
apiVersion: v1
kind: Service
metadata:
name: backend
namespace: secure
spec:
type: ClusterIP
selector:
app: backend
ports:
- name: http
port: 9898
protocol: TCP
targetPort: http
- port: 9999
targetPort: grpc
protocol: TCP
name: grpc

View File

@@ -0,0 +1,6 @@
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: self-signed
spec:
selfSigned: {}

View File

@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: secure

View File

@@ -0,0 +1,29 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: reconciler
namespace: secure
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: reconciler
namespace: secure
rules:
- apiGroups: ['*']
resources: ['*']
verbs: ['*']
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: reconciler
namespace: secure
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: reconciler
subjects:
- kind: ServiceAccount
name: reconciler
namespace: secure

View File

@@ -0,0 +1,5 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: secure
namespace: secure

View File

@@ -0,0 +1,15 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: podinfo-frontend
namespace: secure
spec:
dnsNames:
- frontend
- frontend.secure
- frontend.secure.cluster.local
- localhost
secretName: podinfo-frontend-tls
issuerRef:
name: self-signed
kind: ClusterIssuer

View File

@@ -0,0 +1,95 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: secure
spec:
minReadySeconds: 3
revisionHistoryLimit: 5
progressDeadlineSeconds: 60
strategy:
rollingUpdate:
maxUnavailable: 0
type: RollingUpdate
selector:
matchLabels:
app: frontend
template:
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9797"
labels:
app: frontend
spec:
serviceAccountName: secure
volumes:
- name: tls
secret:
secretName: podinfo-frontend-tls
containers:
- name: frontend
image: deavon/podinfo:secure-port
imagePullPolicy: IfNotPresent
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
allowPrivilegeEscalation: true
ports:
- name: http
containerPort: 9898
protocol: TCP
hostPort: 80
- name: https
containerPort: 9899
protocol: TCP
hostPort: 443
- name: http-metrics
containerPort: 9797
protocol: TCP
- name: grpc
containerPort: 9999
protocol: TCP
volumeMounts:
- name: tls
mountPath: /data/cert
readOnly: true
command:
- ./podinfo
- --port=9898
- --secure-port=9899
- --port-metrics=9797
- --level=info
- --cert-path=/data/cert
- --backend-url=http://backend:9898/echo
env:
- name: PODINFO_UI_COLOR
value: "#34577c"
livenessProbe:
exec:
command:
- podcli
- check
- http
- localhost:9898/healthz
initialDelaySeconds: 5
timeoutSeconds: 5
readinessProbe:
exec:
command:
- podcli
- check
- http
- localhost:9898/readyz
initialDelaySeconds: 5
timeoutSeconds: 5
resources:
limits:
cpu: 1000m
memory: 128Mi
requests:
cpu: 100m
memory: 32Mi

View File

@@ -0,0 +1,19 @@
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: frontend
namespace: secure
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: frontend
minReplicas: 1
maxReplicas: 4
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 99

View File

@@ -0,0 +1,18 @@
apiVersion: v1
kind: Service
metadata:
name: frontend
namespace: secure
spec:
type: ClusterIP
selector:
app: frontend
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
- name: https
port: 443
protocol: TCP
targetPort: https

View File

@@ -25,7 +25,7 @@ spec:
serviceAccountName: webapp
containers:
- name: backend
image: ghcr.io/stefanprodan/podinfo:5.0.3
image: ghcr.io/stefanprodan/podinfo:5.1.1
imagePullPolicy: IfNotPresent
ports:
- name: http

View File

@@ -25,7 +25,7 @@ spec:
serviceAccountName: webapp
containers:
- name: frontend
image: ghcr.io/stefanprodan/podinfo:5.0.3
image: ghcr.io/stefanprodan/podinfo:5.1.1
imagePullPolicy: IfNotPresent
ports:
- name: http

7
hack/build.sh Executable file
View File

@@ -0,0 +1,7 @@
#! /usr/bin/env sh
set -e
# build the docker file
GIT_COMMIT=$(git rev-list -1 HEAD) && \
DOCKER_BUILDKIT=1 docker build --tag test/podinfo --build-arg "REVISION=${GIT_COMMIT}" .

32
hack/deploy.sh Executable file
View File

@@ -0,0 +1,32 @@
#! /usr/bin/env sh
# add jetstack repository
helm repo add jetstack https://charts.jetstack.io || true
# install cert-manager
helm upgrade --install cert-manager jetstack/cert-manager \
--set installCRDs=true \
--namespace default
# wait for cert manager
kubectl rollout status deployment/cert-manager --timeout=2m
kubectl rollout status deployment/cert-manager-webhook --timeout=2m
kubectl rollout status deployment/cert-manager-cainjector --timeout=2m
# install self-signed certificate
cat << 'EOF' | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: self-signed
spec:
selfSigned: {}
EOF
# install podinfo with tls enabled
helm upgrade --install podinfo ./charts/podinfo \
--set image.repository=test/podinfo \
--set image.tag=latest \
--set tls.enabled=true \
--set certificate.create=true \
--namespace=default

20
hack/e2e.sh Executable file
View File

@@ -0,0 +1,20 @@
#! /usr/bin/env sh
set -e
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)
# run the build
$SCRIPT_DIR/build.sh
# create the kind cluster
kind create cluster || true
# load the docker image
kind load docker-image test/podinfo:latest
# run the deploy
$SCRIPT_DIR/deploy.sh
# run the tests
$SCRIPT_DIR/test.sh

9
hack/test.sh Executable file
View File

@@ -0,0 +1,9 @@
#1 /usr/bin/env sh
set -e
# wait for podinfo
kubectl rollout status deployment/podinfo --timeout=3m
# test podinfo
helm test podinfo

7
hack/tiller.sh Executable file
View File

@@ -0,0 +1,7 @@
#! /usr/bin/env sh
set -e
kubectl --namespace kube-system create sa tiller
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
helm init --service-account tiller --upgrade --wait

View File

@@ -23,7 +23,7 @@ spec:
spec:
containers:
- name: podinfod
image: ghcr.io/stefanprodan/podinfo:5.0.3
image: ghcr.io/stefanprodan/podinfo:5.1.1
imagePullPolicy: IfNotPresent
ports:
- name: http

View File

@@ -6,6 +6,7 @@ import (
"net/http"
_ "net/http/pprof"
"os"
"path"
"strings"
"sync/atomic"
"time"
@@ -54,7 +55,9 @@ type Config struct {
UIPath string `mapstructure:"ui-path"`
DataPath string `mapstructure:"data-path"`
ConfigPath string `mapstructure:"config-path"`
CertPath string `mapstructure:"cert-path"`
Port string `mapstructure:"port"`
SecurePort string `mapstructure:"secure-port"`
PortMetrics int `mapstructure:"port-metrics"`
Hostname string `mapstructure:"hostname"`
H2C bool `mapstructure:"h2c"`
@@ -70,10 +73,11 @@ type Config struct {
}
type Server struct {
router *mux.Router
logger *zap.Logger
config *Config
pool *redis.Pool
router *mux.Router
logger *zap.Logger
config *Config
pool *redis.Pool
handler http.Handler
}
func NewServer(config *Config, logger *zap.Logger) (*Server, error) {
@@ -151,19 +155,10 @@ 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{})
s.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: handler,
s.handler = s.router
}
//s.printRoutes()
@@ -183,12 +178,11 @@ func (s *Server) ListenAndServe(stopCh <-chan struct{}) {
ticker := time.NewTicker(30 * time.Second)
s.startCachePool(ticker, stopCh)
// run server in background
go func() {
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
s.logger.Fatal("HTTP server crashed", zap.Error(err))
}
}()
// create the http server
srv := s.startServer()
// create the secure server
secureSrv := s.startSecureServer()
// signal Kubernetes the server is ready to receive traffic
if !s.config.Unhealthy {
@@ -212,7 +206,7 @@ func (s *Server) ListenAndServe(stopCh <-chan struct{}) {
_ = s.pool.Close()
}
s.logger.Info("Shutting down HTTP server", zap.Duration("timeout", s.config.HttpServerShutdownTimeout))
s.logger.Info("Shutting down HTTP/HTTPS server", zap.Duration("timeout", s.config.HttpServerShutdownTimeout))
// wait for Kubernetes readiness probe to remove this instance from the load balancer
// the readiness check interval must be lower than the timeout
@@ -220,12 +214,78 @@ func (s *Server) ListenAndServe(stopCh <-chan struct{}) {
time.Sleep(3 * time.Second)
}
// attempt graceful shutdown
if err := srv.Shutdown(ctx); err != nil {
s.logger.Warn("HTTP server graceful shutdown failed", zap.Error(err))
} else {
s.logger.Info("HTTP server stopped")
// determine if the http server was started
if srv != nil {
if err := srv.Shutdown(ctx); err != nil {
s.logger.Warn("HTTP server graceful shutdown failed", zap.Error(err))
}
}
// determine if the secure server was started
if secureSrv != nil {
if err := secureSrv.Shutdown(ctx); err != nil {
s.logger.Warn("HTTPS server graceful shutdown failed", zap.Error(err))
}
}
}
func (s *Server) startServer() *http.Server {
// determine if the port is specified
if s.config.Port == "0" {
// move on immediately
return nil
}
srv := &http.Server{
Addr: ":" + s.config.Port,
WriteTimeout: s.config.HttpServerTimeout,
ReadTimeout: s.config.HttpServerTimeout,
IdleTimeout: 2 * s.config.HttpServerTimeout,
Handler: s.handler,
}
// start the server in the background
go func() {
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
s.logger.Fatal("HTTP server crashed", zap.Error(err))
}
}()
// return the server and routine
return srv
}
func (s *Server) startSecureServer() *http.Server {
// determine if the port is specified
if s.config.SecurePort == "0" {
// move on immediately
return nil
}
srv := &http.Server{
Addr: ":" + s.config.SecurePort,
WriteTimeout: s.config.HttpServerTimeout,
ReadTimeout: s.config.HttpServerTimeout,
IdleTimeout: 2 * s.config.HttpServerTimeout,
Handler: s.handler,
}
cert := path.Join(s.config.CertPath, "tls.crt")
key := path.Join(s.config.CertPath, "tls.key")
// start the server in the background
go func() {
if err := srv.ListenAndServeTLS(cert, key); err != http.ErrServerClosed {
s.logger.Fatal("HTTPS server crashed", zap.Error(err))
}
}()
// return the server
return srv
}
func (s *Server) startMetricsServer() {

View File

@@ -1,4 +1,4 @@
package version
var VERSION = "5.0.3"
var VERSION = "5.1.1"
var REVISION = "unknown"