mirror of
https://github.com/stefanprodan/podinfo.git
synced 2026-04-07 03:26:54 +00:00
Compare commits
311 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79279ccb31 | ||
|
|
7e1ef7457e | ||
|
|
af4919172a | ||
|
|
532e8f85b5 | ||
|
|
7c90501b8b | ||
|
|
5f1fb66f6f | ||
|
|
be80733cea | ||
|
|
8572a390f7 | ||
|
|
b2a41c64de | ||
|
|
11cf36d838 | ||
|
|
5d440e41da | ||
|
|
170b912d25 | ||
|
|
38a7952407 | ||
|
|
de90d92697 | ||
|
|
22ee79fcb8 | ||
|
|
03ffc8bc34 | ||
|
|
c4f2a6c5e6 | ||
|
|
ab9f7410c2 | ||
|
|
2c85a72737 | ||
|
|
3970a3a323 | ||
|
|
61d6ed42f5 | ||
|
|
bb11285c6f | ||
|
|
132f4e7192 | ||
|
|
6c596bf19b | ||
|
|
ea292aa958 | ||
|
|
33fa856b63 | ||
|
|
6065c5aa79 | ||
|
|
0771a597e6 | ||
|
|
693ffa9d28 | ||
|
|
1c39c04ac9 | ||
|
|
a27ef20cb7 | ||
|
|
5e2089eafb | ||
|
|
68fd4e245a | ||
|
|
b718809f3b | ||
|
|
26379a5589 | ||
|
|
8d37bcfa32 | ||
|
|
f168e1909b | ||
|
|
627d5c4bb6 | ||
|
|
29f3e7f430 | ||
|
|
8a7d5689e5 | ||
|
|
70ab46cd6e | ||
|
|
d8effad747 | ||
|
|
dc97765557 | ||
|
|
685371108d | ||
|
|
b6f1555176 | ||
|
|
deadf87be8 | ||
|
|
1d75661e45 | ||
|
|
6a78560d28 | ||
|
|
9c4df129c6 | ||
|
|
21c8dfbb69 | ||
|
|
8c93f05fa9 | ||
|
|
ef98a040c8 | ||
|
|
bcd8e65416 | ||
|
|
79ab71bcf9 | ||
|
|
a67c482a87 | ||
|
|
7d89cbfd07 | ||
|
|
0b73f44190 | ||
|
|
5751990e1a | ||
|
|
6d1d8c1271 | ||
|
|
81a311281e | ||
|
|
71647cee9a | ||
|
|
2487019631 | ||
|
|
885a35eebf | ||
|
|
d36c523e67 | ||
|
|
43b05fb948 | ||
|
|
6856337c57 | ||
|
|
2b603bedcd | ||
|
|
e43ebfa5bf | ||
|
|
c914acb34d | ||
|
|
982713606e | ||
|
|
63c0d0afe5 | ||
|
|
4407939ea3 | ||
|
|
ee6df13f57 | ||
|
|
97f9aca039 | ||
|
|
f30e3f89ed | ||
|
|
f220644263 | ||
|
|
9e066ebc7b | ||
|
|
855f7724be | ||
|
|
33d1e950a9 | ||
|
|
ec57c11356 | ||
|
|
f0d7f0adca | ||
|
|
9f4d31a8c4 | ||
|
|
95eafd32f9 | ||
|
|
86dbbf7254 | ||
|
|
b13ec2ddb4 | ||
|
|
0f7a876dae | ||
|
|
837ff33ee0 | ||
|
|
4735f54368 | ||
|
|
35c9128bca | ||
|
|
411bce81c0 | ||
|
|
1ac286c3b0 | ||
|
|
b496853d32 | ||
|
|
9ca49aa442 | ||
|
|
bc809cd763 | ||
|
|
046ac8a4a5 | ||
|
|
c38f357872 | ||
|
|
95be17be1d | ||
|
|
5c30dfefc7 | ||
|
|
d1829ea9ec | ||
|
|
06f2276501 | ||
|
|
13f7ec7ba1 | ||
|
|
e9d5f7965f | ||
|
|
6596ed08de | ||
|
|
4c0dfaef0e | ||
|
|
36e5ceaee2 | ||
|
|
5281c2d9a8 | ||
|
|
7411da595c | ||
|
|
44f8ae96eb | ||
|
|
0cab9bf6b2 | ||
|
|
7111121165 | ||
|
|
9299a2d1f3 | ||
|
|
8d90770909 | ||
|
|
16a9f6f84c | ||
|
|
6f4447fb8b | ||
|
|
70e31587bb | ||
|
|
6dca3b2743 | ||
|
|
5cd072243d | ||
|
|
fbf20b8ac1 | ||
|
|
5833d41e85 | ||
|
|
a77b43479a | ||
|
|
3b884b02c9 | ||
|
|
1a56086320 | ||
|
|
692df9e5b7 | ||
|
|
103929b14a | ||
|
|
d3865f9247 | ||
|
|
3507958932 | ||
|
|
a8b8bad0e4 | ||
|
|
26a630c0b4 | ||
|
|
76c18c588f | ||
|
|
df5ece51ef | ||
|
|
f7d1c5639c | ||
|
|
20a136a73c | ||
|
|
f43f9b2eb6 | ||
|
|
9a46ed3182 | ||
|
|
82b7007c5d | ||
|
|
806f0dbe82 | ||
|
|
936018e5bb | ||
|
|
1b4131b5ad | ||
|
|
b98a9dcc1a | ||
|
|
8860e57362 | ||
|
|
f1ecea6b53 | ||
|
|
ebc6493990 | ||
|
|
a2f9216fe4 | ||
|
|
27436ed538 | ||
|
|
c103a50423 | ||
|
|
5ac16f0f98 | ||
|
|
b4138fdb4d | ||
|
|
a2e6fd0ef1 | ||
|
|
c2aaf7a962 | ||
|
|
a066ff5385 | ||
|
|
113360052b | ||
|
|
a24e3e539c | ||
|
|
ed8a14d4d9 | ||
|
|
d2798e1a24 | ||
|
|
369014455c | ||
|
|
db1b8a7acd | ||
|
|
cc9231ae10 | ||
|
|
03ba47a0be | ||
|
|
ab953493ee | ||
|
|
c04ee365e6 | ||
|
|
26e8935520 | ||
|
|
dd027359e6 | ||
|
|
cf26a9cefc | ||
|
|
026b40876c | ||
|
|
fd1814052a | ||
|
|
98c2853ec3 | ||
|
|
b2ca15b8af | ||
|
|
55e7178dad | ||
|
|
ea55d3facf | ||
|
|
a72aa7a184 | ||
|
|
b4248cae1e | ||
|
|
7d2bc4905a | ||
|
|
f75f6e9fbc | ||
|
|
713d1094a2 | ||
|
|
3197ad3e45 | ||
|
|
92f415d633 | ||
|
|
0352a3c822 | ||
|
|
5ba5808722 | ||
|
|
1d416a8513 | ||
|
|
95028a0fb0 | ||
|
|
b45cc75329 | ||
|
|
79bbf76ece | ||
|
|
a8c7300174 | ||
|
|
a60f28ac2f | ||
|
|
adba061f77 | ||
|
|
8f15e4e00a | ||
|
|
07db5a6583 | ||
|
|
3e6d61e77e | ||
|
|
c7c7d699c9 | ||
|
|
067751c67d | ||
|
|
73b658d711 | ||
|
|
e5516b38cb | ||
|
|
39130004d5 | ||
|
|
d4b615e3a2 | ||
|
|
98e133a7be | ||
|
|
7674b76dab | ||
|
|
8fa39d90be | ||
|
|
638bdc8e83 | ||
|
|
b565a67dec | ||
|
|
65d077291b | ||
|
|
e9d11c247e | ||
|
|
126ac55801 | ||
|
|
306aac3e65 | ||
|
|
55318b0c20 | ||
|
|
1865faf7ce | ||
|
|
9edd7abbe8 | ||
|
|
1c4acc0b33 | ||
|
|
6274f16b9b | ||
|
|
93e338a964 | ||
|
|
73b03b77fc | ||
|
|
0135757fbd | ||
|
|
ea1fe87d49 | ||
|
|
363a6a8fe6 | ||
|
|
8491738c8a | ||
|
|
361179fad9 | ||
|
|
13eb7c42cd | ||
|
|
e4ecd98b83 | ||
|
|
5e747d3e08 | ||
|
|
c6425ac1f8 | ||
|
|
7f5b8817ca | ||
|
|
fb999f828f | ||
|
|
ba12154f68 | ||
|
|
73e0ee798f | ||
|
|
2c7029cf35 | ||
|
|
50c35833dc | ||
|
|
7a8b7d6a5c | ||
|
|
2a36e84bf2 | ||
|
|
3802fb427a | ||
|
|
b4ea2afc19 | ||
|
|
6ba7ddc83f | ||
|
|
af6868a8de | ||
|
|
910e7139f9 | ||
|
|
fe65869b6b | ||
|
|
2a319d9d0d | ||
|
|
48402eff7e | ||
|
|
15600cc7d3 | ||
|
|
ed2a774e10 | ||
|
|
1d590c07cb | ||
|
|
948de81ed3 | ||
|
|
78658c0311 | ||
|
|
7b6f11780a | ||
|
|
d65044ff2e | ||
|
|
18c63ad7f7 | ||
|
|
a8260081d9 | ||
|
|
0ff49e5057 | ||
|
|
79cfe56484 | ||
|
|
7e36892e26 | ||
|
|
3d6d0bed69 | ||
|
|
b213e0af0a | ||
|
|
42ad3faf5a | ||
|
|
939fd5b24d | ||
|
|
36ec3ef378 | ||
|
|
287e005129 | ||
|
|
0b3e88d6de | ||
|
|
10139749da | ||
|
|
f891e0683b | ||
|
|
647b4cba04 | ||
|
|
c5df50c774 | ||
|
|
2b1d325343 | ||
|
|
319d57cb68 | ||
|
|
087da02dbb | ||
|
|
7d00f68180 | ||
|
|
87c9bb8ba2 | ||
|
|
5fb970b526 | ||
|
|
56b404bd84 | ||
|
|
a12d0a1ed7 | ||
|
|
51979787b0 | ||
|
|
8b37756118 | ||
|
|
1eb1da110b | ||
|
|
d1ed907f1e | ||
|
|
8e6eccecda | ||
|
|
f3db1adb27 | ||
|
|
7f3e11c1ce | ||
|
|
a7eb7e4995 | ||
|
|
43194bb342 | ||
|
|
c7d21968e7 | ||
|
|
214a19fb0f | ||
|
|
82ea2fa993 | ||
|
|
d84913c31e | ||
|
|
6bac5ffaa2 | ||
|
|
eacf909c4a | ||
|
|
f7c1669125 | ||
|
|
158d6e82da | ||
|
|
4d890382e5 | ||
|
|
83842e01f7 | ||
|
|
37b453fbbc | ||
|
|
53c6b472de | ||
|
|
c759f958c0 | ||
|
|
5d14183809 | ||
|
|
ab74d6ef0b | ||
|
|
fefcae34c1 | ||
|
|
ed81a06a82 | ||
|
|
633982b0e5 | ||
|
|
4154e01fdd | ||
|
|
02d7f06d35 | ||
|
|
555450868e | ||
|
|
94085d6dc6 | ||
|
|
630841d81b | ||
|
|
ea7f4fcdf7 | ||
|
|
e97c926611 | ||
|
|
2479134e78 | ||
|
|
b0bbd16a77 | ||
|
|
7564949695 | ||
|
|
d34da2ab91 | ||
|
|
182156d9b4 | ||
|
|
e0864b6e20 | ||
|
|
de2a9c464a | ||
|
|
fed04ad692 | ||
|
|
c907163073 | ||
|
|
67578338c9 | ||
|
|
0c27729000 |
@@ -1,52 +0,0 @@
|
||||
version: 2.1
|
||||
jobs:
|
||||
push-helm-charts:
|
||||
docker:
|
||||
- image: circleci/golang:1.12
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Install kubectl
|
||||
command: sudo curl -L https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl -o /usr/local/bin/kubectl && sudo chmod +x /usr/local/bin/kubectl
|
||||
- run:
|
||||
name: Install helm
|
||||
command: sudo curl -L https://storage.googleapis.com/kubernetes-helm/helm-v2.14.2-linux-amd64.tar.gz | tar xz && sudo mv linux-amd64/helm /bin/helm && sudo rm -rf linux-amd64
|
||||
- run:
|
||||
name: Initialize helm
|
||||
command: helm init --client-only --kubeconfig=$HOME/.kube/kubeconfig
|
||||
- run:
|
||||
name: Lint charts
|
||||
command: |
|
||||
helm lint ./charts/*
|
||||
- run:
|
||||
name: Package charts
|
||||
command: |
|
||||
mkdir $HOME/charts
|
||||
helm package ./charts/* --destination $HOME/charts
|
||||
- run:
|
||||
name: Publish charts
|
||||
command: |
|
||||
if echo "${CIRCLE_TAG}" | grep -Eq "[0-9]+(\.[0-9]+)*(-[a-z]+)?$"; then
|
||||
REPOSITORY="https://stefanprodan:${GITHUB_TOKEN}@github.com/stefanprodan/podinfo.git"
|
||||
git config user.email stefanprodan@users.noreply.github.com
|
||||
git config user.name stefanprodan
|
||||
git remote set-url origin ${REPOSITORY}
|
||||
git checkout gh-pages
|
||||
mv -f $HOME/charts/*.tgz .
|
||||
helm repo index . --url https://stefanprodan.github.io/podinfo
|
||||
git add .
|
||||
git commit -m "Publish Helm charts v${CIRCLE_TAG}"
|
||||
git push origin gh-pages
|
||||
else
|
||||
echo "Not a release! Skip charts publish"
|
||||
fi
|
||||
workflows:
|
||||
version: 2
|
||||
release:
|
||||
jobs:
|
||||
- push-helm-charts:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
ignore: /^chart.*/
|
||||
39
.cosign/README.md
Normal file
39
.cosign/README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Podinfo signed releases
|
||||
|
||||
Podinfo deployment manifests are published to GitHub Container Registry as OCI artifacts
|
||||
and are signed using [cosign](https://github.com/sigstore/cosign).
|
||||
|
||||
## Verify the artifacts with cosign
|
||||
|
||||
Install the [cosign](https://github.com/sigstore/cosign) CLI:
|
||||
|
||||
```sh
|
||||
brew install sigstore/tap/cosign
|
||||
```
|
||||
|
||||
Verify a podinfo release with cosign CLI:
|
||||
|
||||
```sh
|
||||
cosign verify -key https://raw.githubusercontent.com/stefanprodan/podinfo/master/cosign/cosign.pub \
|
||||
ghcr.io/stefanprodan/podinfo-deploy:latest
|
||||
```
|
||||
|
||||
## Download the artifacts with crane
|
||||
|
||||
Install the [crane](https://github.com/google/go-containerregistry/tree/main/cmd/crane) CLI:
|
||||
|
||||
```sh
|
||||
brew install crane
|
||||
```
|
||||
|
||||
Download the podinfo deployment manifests with crane CLI:
|
||||
|
||||
```console
|
||||
$ crane export ghcr.io/stefanprodan/podinfo-deploy:latest -| tar -xf -
|
||||
|
||||
$ ls -1
|
||||
deployment.yaml
|
||||
hpa.yaml
|
||||
kustomization.yaml
|
||||
service.yaml
|
||||
```
|
||||
4
.cosign/cosign.pub
Normal file
4
.cosign/cosign.pub
Normal file
@@ -0,0 +1,4 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEST+BqQ1XZhhVYx0YWQjdUJYIG5Lt
|
||||
iz2+UxRIqmKBqNmce2T+l45qyqOs99qfD7gLNGmkVZ4vtJ9bM7FxChFczg==
|
||||
-----END PUBLIC KEY-----
|
||||
33
.github/actions/helm/action.yml
vendored
Normal file
33
.github/actions/helm/action.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
name: Setup Helm CLI
|
||||
description: A GitHub Action for running Helm commands
|
||||
author: Stefan Prodan
|
||||
branding:
|
||||
color: blue
|
||||
icon: command
|
||||
inputs:
|
||||
version:
|
||||
description: "Helm version"
|
||||
required: true
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: "Download helm binary to tmp"
|
||||
shell: bash
|
||||
run: |
|
||||
VERSION=${{ inputs.version }}
|
||||
BIN_URL="https://get.helm.sh/helm-v${VERSION}-linux-amd64.tar.gz"
|
||||
curl -sL ${BIN_URL} -o /tmp/helm.tar.gz
|
||||
mkdir -p /tmp/helm
|
||||
tar -C /tmp/helm/ -zxvf /tmp/helm.tar.gz
|
||||
- name: "Add helm binary to /usr/local/bin"
|
||||
shell: bash
|
||||
run: |
|
||||
sudo cp /tmp/helm/linux-amd64/helm /usr/local/bin
|
||||
- name: "Cleanup tmp"
|
||||
shell: bash
|
||||
run: |
|
||||
rm -rf /tmp/helm/ /tmp/helm.tar.gz
|
||||
- name: "Verify correct installation of binary"
|
||||
shell: bash
|
||||
run: |
|
||||
helm version
|
||||
6
.github/actions/release-notes/Dockerfile
vendored
Normal file
6
.github/actions/release-notes/Dockerfile
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
FROM stefanprodan/alpine-base:latest
|
||||
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
9
.github/actions/release-notes/action.yml
vendored
Normal file
9
.github/actions/release-notes/action.yml
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
name: 'github-release-notes'
|
||||
description: 'A GitHub Action to run github-release-notes commands'
|
||||
author: 'Stefan Prodan'
|
||||
branding:
|
||||
icon: 'command'
|
||||
color: 'blue'
|
||||
runs:
|
||||
using: 'docker'
|
||||
image: 'Dockerfile'
|
||||
25
.github/actions/release-notes/entrypoint.sh
vendored
Normal file
25
.github/actions/release-notes/entrypoint.sh
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
|
||||
VERSION=0.2.0
|
||||
BIN_DIR="$GITHUB_WORKSPACE/bin"
|
||||
|
||||
main() {
|
||||
mkdir -p ${BIN_DIR}
|
||||
tmpDir=$(mktemp -d)
|
||||
|
||||
pushd $tmpDir >& /dev/null
|
||||
|
||||
curl -sSL https://github.com/buchanae/github-release-notes/releases/download/${VERSION}/github-release-notes-linux-amd64-${VERSION}.tar.gz | tar xz
|
||||
cp github-release-notes ${BIN_DIR}/github-release-notes
|
||||
|
||||
popd >& /dev/null
|
||||
rm -rf $tmpDir
|
||||
}
|
||||
|
||||
main
|
||||
|
||||
echo "$BIN_DIR" >> $GITHUB_PATH
|
||||
echo "$RUNNER_WORKSPACE/$(basename $GITHUB_REPOSITORY)/bin" >> $GITHUB_PATH
|
||||
51
.github/policy/kubernetes.rego
vendored
Normal file
51
.github/policy/kubernetes.rego
vendored
Normal 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
43
.github/policy/rules.rego
vendored
Normal 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])
|
||||
}
|
||||
28
.github/workflows/cve-scan.yml
vendored
Normal file
28
.github/workflows/cve-scan.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: cve-scan
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
|
||||
jobs:
|
||||
trivy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Build image
|
||||
id: build
|
||||
run: |
|
||||
IMAGE=test/podinfo:${GITHUB_SHA}
|
||||
docker build -t ${IMAGE} .
|
||||
echo "::set-output name=image::$IMAGE"
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
image-ref: ${{ steps.build.outputs.image }}
|
||||
format: table
|
||||
exit-code: "1"
|
||||
ignore-unfixed: true
|
||||
vuln-type: os,library
|
||||
severity: CRITICAL,HIGH
|
||||
38
.github/workflows/e2e.yml
vendored
Normal file
38
.github/workflows/e2e.yml
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
name: e2e
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
|
||||
jobs:
|
||||
kind-helm:
|
||||
strategy:
|
||||
matrix:
|
||||
helm-version:
|
||||
- 3.6.0
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup Kubernetes
|
||||
uses: engineerd/setup-kind@v0.5.0
|
||||
with:
|
||||
version: v0.11.1
|
||||
- name: Build container image
|
||||
run: |
|
||||
./test/build.sh
|
||||
kind load docker-image test/podinfo:latest
|
||||
- name: Setup Helm
|
||||
uses: ./.github/actions/helm
|
||||
with:
|
||||
version: ${{ matrix.helm-version }}
|
||||
- name: Deploy
|
||||
run: ./test/deploy.sh
|
||||
- name: Run integration tests
|
||||
run: ./test/test.sh
|
||||
- name: Debug failure
|
||||
if: failure()
|
||||
run: |
|
||||
kubectl logs -l app=podinfo || true
|
||||
113
.github/workflows/release.yml
vendored
Normal file
113
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
name: release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
permissions:
|
||||
contents: write # needed to write releases
|
||||
id-token: write # needed for keyless signing
|
||||
packages: write # needed for ghcr access
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: imjasonh/setup-crane@v0.1
|
||||
- uses: sigstore/cosign-installer@main
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
with:
|
||||
platforms: all
|
||||
- name: Setup Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.GHCR_TOKEN }}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Prepare
|
||||
id: prep
|
||||
run: |
|
||||
VERSION=sha-${GITHUB_SHA::8}
|
||||
if [[ $GITHUB_REF == refs/tags/* ]]; then
|
||||
VERSION=${GITHUB_REF/refs\/tags\//}
|
||||
fi
|
||||
echo ::set-output name=BUILD_DATE::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
|
||||
echo ::set-output name=VERSION::${VERSION}
|
||||
- name: Publish multi-arch image
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
push: true
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
context: .
|
||||
file: ./Dockerfile.xx
|
||||
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
||||
tags: |
|
||||
docker.io/stefanprodan/podinfo:${{ steps.prep.outputs.VERSION }}
|
||||
docker.io/stefanprodan/podinfo:latest
|
||||
ghcr.io/stefanprodan/podinfo:${{ steps.prep.outputs.VERSION }}
|
||||
labels: |
|
||||
org.opencontainers.image.title=${{ github.event.repository.name }}
|
||||
org.opencontainers.image.description=${{ github.event.repository.description }}
|
||||
org.opencontainers.image.source=${{ github.event.repository.html_url }}
|
||||
org.opencontainers.image.url=${{ github.event.repository.html_url }}
|
||||
org.opencontainers.image.revision=${{ github.sha }}
|
||||
org.opencontainers.image.version=${{ steps.prep.outputs.VERSION }}
|
||||
org.opencontainers.image.created=${{ steps.prep.outputs.BUILD_DATE }}
|
||||
- name: Sign images
|
||||
env:
|
||||
COSIGN_EXPERIMENTAL: 1
|
||||
run: |
|
||||
cosign sign docker.io/stefanprodan/podinfo:${{ steps.prep.outputs.VERSION }}
|
||||
cosign sign docker.io/stefanprodan/podinfo:latest
|
||||
cosign sign ghcr.io/stefanprodan/podinfo:${{ steps.prep.outputs.VERSION }}
|
||||
- name: Publish base image
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
push: true
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
context: .
|
||||
platforms: linux/amd64
|
||||
file: ./Dockerfile.base
|
||||
tags: docker.io/stefanprodan/podinfo-base:latest
|
||||
- name: Publish helm chart
|
||||
uses: stefanprodan/helm-gh-pages@master
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Publish config artifact
|
||||
run: |
|
||||
cd kustomize
|
||||
tar -cf config.tar * --numeric-owner --owner=0 --group=0
|
||||
crane append -f config.tar -t ghcr.io/stefanprodan/podinfo-deploy:${{ steps.prep.outputs.VERSION }}
|
||||
crane tag ghcr.io/stefanprodan/podinfo-deploy:${{ steps.prep.outputs.VERSION }} latest
|
||||
rm config.tar
|
||||
- name: Sign config artifact
|
||||
run: |
|
||||
echo "$COSIGN_KEY" > /tmp/cosign.key
|
||||
cosign sign -key /tmp/cosign.key ghcr.io/stefanprodan/podinfo-deploy:${{ steps.prep.outputs.VERSION }}
|
||||
cosign sign -key /tmp/cosign.key ghcr.io/stefanprodan/podinfo-deploy:latest
|
||||
env:
|
||||
COSIGN_PASSWORD: ${{secrets.COSIGN_PASSWORD}}
|
||||
COSIGN_KEY: ${{secrets.COSIGN_KEY}}
|
||||
- uses: ./.github/actions/release-notes
|
||||
- name: Generate release notes
|
||||
run: |
|
||||
echo 'CHANGELOG' > /tmp/release.txt
|
||||
github-release-notes -org stefanprodan -repo podinfo -since-latest-release >> /tmp/release.txt
|
||||
- name: Publish release
|
||||
uses: goreleaser/goreleaser-action@v1
|
||||
with:
|
||||
version: latest
|
||||
args: release --release-notes=/tmp/release.txt
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
47
.github/workflows/test.yml
vendored
Normal file
47
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
name: test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Restore Go cache
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-go-
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.17.x
|
||||
- name: Run unit tests
|
||||
run: make test
|
||||
- name: Check if working tree is dirty
|
||||
run: |
|
||||
if [[ $(git diff --stat) != '' ]]; then
|
||||
echo 'run make test and commit changes'
|
||||
exit 1
|
||||
fi
|
||||
- name: Validate Helm chart
|
||||
uses: stefanprodan/kube-tools@v1
|
||||
with:
|
||||
kubectl: 1.19.11
|
||||
helm: 2.17.0
|
||||
helmv3: 3.6.0
|
||||
command: |
|
||||
helmv3 template ./charts/podinfo | kubeval --strict --kubernetes-version 1.19.11 --schema-location https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master
|
||||
- name: Validate kustomization
|
||||
uses: stefanprodan/kube-tools@v1
|
||||
with:
|
||||
kubectl: 1.19.11
|
||||
command: |
|
||||
kustomize build ./kustomize | kubeval --strict --kubernetes-version 1.19.11 --schema-location https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master
|
||||
kustomize build ./kustomize | conftest test -p .github/policy -
|
||||
32
.travis.yml
32
.travis.yml
@@ -1,32 +0,0 @@
|
||||
sudo: required
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.12.x
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- docker-ce
|
||||
|
||||
script:
|
||||
- make build-container
|
||||
|
||||
after_success:
|
||||
- if [ -z "$TRAVIS_TAG" ]; then
|
||||
echo "Not a release, skipping container push";
|
||||
else
|
||||
echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin;
|
||||
echo $QUAY_PASS | docker login -u $QUAY_USER --password-stdin quay.io;
|
||||
make push-container;
|
||||
fi
|
||||
|
||||
deploy:
|
||||
- provider: script
|
||||
skip_cleanup: true
|
||||
script: curl -sL http://git.io/goreleaser | bash
|
||||
on:
|
||||
tags: true
|
||||
30
Dockerfile
30
Dockerfile
@@ -1,4 +1,6 @@
|
||||
FROM golang:1.12 as builder
|
||||
FROM golang:1.17-alpine as builder
|
||||
|
||||
ARG REVISION
|
||||
|
||||
RUN mkdir -p /podinfo/
|
||||
|
||||
@@ -6,26 +8,28 @@ WORKDIR /podinfo
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN GOPROXY=https://proxy.golang.org go mod download
|
||||
RUN go mod download
|
||||
|
||||
RUN go test -v -race ./...
|
||||
|
||||
RUN GIT_COMMIT=$(git rev-list -1 HEAD) && \
|
||||
CGO_ENABLED=0 GOOS=linux go build -ldflags "-s -w \
|
||||
-X github.com/stefanprodan/podinfo/pkg/version.REVISION=${GIT_COMMIT}" \
|
||||
RUN CGO_ENABLED=0 go build -ldflags "-s -w \
|
||||
-X github.com/stefanprodan/podinfo/pkg/version.REVISION=${REVISION}" \
|
||||
-a -o bin/podinfo cmd/podinfo/*
|
||||
|
||||
RUN GIT_COMMIT=$(git rev-list -1 HEAD) && \
|
||||
CGO_ENABLED=0 GOOS=linux go build -ldflags "-s -w \
|
||||
-X github.com/stefanprodan/podinfo/pkg/version.REVISION=${GIT_COMMIT}" \
|
||||
RUN CGO_ENABLED=0 go build -ldflags "-s -w \
|
||||
-X github.com/stefanprodan/podinfo/pkg/version.REVISION=${REVISION}" \
|
||||
-a -o bin/podcli cmd/podcli/*
|
||||
|
||||
FROM alpine:3.10
|
||||
FROM alpine:3.15
|
||||
|
||||
ARG BUILD_DATE
|
||||
ARG VERSION
|
||||
ARG REVISION
|
||||
|
||||
LABEL maintainer="stefanprodan"
|
||||
|
||||
RUN addgroup -S app \
|
||||
&& adduser -S -g app app \
|
||||
&& adduser -S -G app app \
|
||||
&& apk --no-cache add \
|
||||
curl openssl netcat-openbsd
|
||||
ca-certificates curl netcat-openbsd
|
||||
|
||||
WORKDIR /home/app
|
||||
|
||||
|
||||
10
Dockerfile.base
Normal file
10
Dockerfile.base
Normal file
@@ -0,0 +1,10 @@
|
||||
FROM golang:1.17
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
# copy modules manifests
|
||||
COPY go.mod go.mod
|
||||
COPY go.sum go.sum
|
||||
|
||||
# cache modules
|
||||
RUN go mod download
|
||||
53
Dockerfile.xx
Normal file
53
Dockerfile.xx
Normal file
@@ -0,0 +1,53 @@
|
||||
ARG GO_VERSION=1.17
|
||||
ARG XX_VERSION=1.1.0
|
||||
|
||||
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
|
||||
|
||||
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine as builder
|
||||
|
||||
# Copy the build utilities.
|
||||
COPY --from=xx / /
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
ARG REVISION
|
||||
|
||||
RUN mkdir -p /podinfo/
|
||||
|
||||
WORKDIR /podinfo
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN go mod download
|
||||
|
||||
ENV CGO_ENABLED=0
|
||||
RUN xx-go build -ldflags "-s -w \
|
||||
-X github.com/stefanprodan/podinfo/pkg/version.REVISION=${REVISION}" \
|
||||
-a -o bin/podinfo cmd/podinfo/*
|
||||
|
||||
RUN xx-go build -ldflags "-s -w \
|
||||
-X github.com/stefanprodan/podinfo/pkg/version.REVISION=${REVISION}" \
|
||||
-a -o bin/podcli cmd/podcli/*
|
||||
|
||||
FROM alpine:3.15
|
||||
|
||||
ARG BUILD_DATE
|
||||
ARG VERSION
|
||||
ARG REVISION
|
||||
|
||||
LABEL maintainer="stefanprodan"
|
||||
|
||||
RUN addgroup -S app \
|
||||
&& adduser -S -G app app \
|
||||
&& apk --no-cache add \
|
||||
ca-certificates curl netcat-openbsd
|
||||
|
||||
WORKDIR /home/app
|
||||
|
||||
COPY --from=builder /podinfo/bin/podinfo .
|
||||
COPY --from=builder /podinfo/bin/podcli /usr/local/bin/podcli
|
||||
COPY ./ui ./ui
|
||||
RUN chown -R app:app ./
|
||||
|
||||
USER app
|
||||
|
||||
CMD ["./podinfo"]
|
||||
214
LICENSE
214
LICENSE
@@ -1,21 +1,201 @@
|
||||
MIT License
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
Copyright (c) 2018 Stefan Prodan
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
1. Definitions.
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2018 Stefan Prodan. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
64
Makefile
64
Makefile
@@ -6,18 +6,29 @@ TAG?=latest
|
||||
NAME:=podinfo
|
||||
DOCKER_REPOSITORY:=stefanprodan
|
||||
DOCKER_IMAGE_NAME:=$(DOCKER_REPOSITORY)/$(NAME)
|
||||
GITCOMMIT:=$(shell git describe --dirty --always)
|
||||
GIT_COMMIT:=$(shell git describe --dirty --always)
|
||||
VERSION:=$(shell grep 'VERSION' pkg/version/version.go | awk '{ print $$4 }' | tr -d '"')
|
||||
EXTRA_RUN_ARGS?=
|
||||
|
||||
run:
|
||||
GO111MODULE=on go run cmd/podinfo/*
|
||||
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://raw.githubusercontent.com/stefanprodan/podinfo/gh-pages/cuddle_clap.gif $(EXTRA_RUN_ARGS)
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
GO111MODULE=on go test -v -race ./...
|
||||
go test ./... -coverprofile cover.out
|
||||
|
||||
build:
|
||||
GO111MODULE=on GIT_COMMIT=$$(git rev-list -1 HEAD) && GO111MODULE=on CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/stefanprodan/podinfo/pkg/version.REVISION=$${GIT_COMMIT}" -a -o ./bin/podinfo ./cmd/podinfo/*
|
||||
GO111MODULE=on GIT_COMMIT=$$(git rev-list -1 HEAD) && GO111MODULE=on CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/stefanprodan/podinfo/pkg/version.REVISION=$${GIT_COMMIT}" -a -o ./bin/podcli ./cmd/podcli/*
|
||||
GIT_COMMIT=$$(git rev-list -1 HEAD) && CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/stefanprodan/podinfo/pkg/version.REVISION=$(GIT_COMMIT)" -a -o ./bin/podinfo ./cmd/podinfo/*
|
||||
GIT_COMMIT=$$(git rev-list -1 HEAD) && CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/stefanprodan/podinfo/pkg/version.REVISION=$(GIT_COMMIT)" -a -o ./bin/podcli ./cmd/podcli/*
|
||||
|
||||
tidy:
|
||||
rm -f go.sum; go mod tidy -compat=1.17
|
||||
|
||||
fmt:
|
||||
gofmt -l -s -w ./
|
||||
goimports -l -w ./
|
||||
|
||||
build-charts:
|
||||
helm lint charts/*
|
||||
@@ -26,21 +37,54 @@ build-charts:
|
||||
build-container:
|
||||
docker build -t $(DOCKER_IMAGE_NAME):$(VERSION) .
|
||||
|
||||
build-xx:
|
||||
docker buildx build \
|
||||
--platform=linux/amd64 \
|
||||
-t $(DOCKER_IMAGE_NAME):$(VERSION) \
|
||||
--load \
|
||||
-f Dockerfile.xx .
|
||||
|
||||
build-base:
|
||||
docker build -f Dockerfile.base -t $(DOCKER_REPOSITORY)/podinfo-base:latest .
|
||||
|
||||
push-base: build-base
|
||||
docker push $(DOCKER_REPOSITORY)/podinfo-base:latest
|
||||
|
||||
test-container:
|
||||
@docker rm -f podinfo || true
|
||||
@docker run -dp 9898:9898 --name=podinfo $(DOCKER_IMAGE_NAME):$(VERSION)
|
||||
@docker ps
|
||||
@TOKEN=$$(curl -sd 'test' localhost:9898/token | jq -r .token) && \
|
||||
curl -sH "Authorization: Bearer $${TOKEN}" localhost:9898/token/validate | grep test
|
||||
|
||||
push-container:
|
||||
docker tag $(DOCKER_IMAGE_NAME):$(VERSION) $(DOCKER_IMAGE_NAME):latest
|
||||
docker push $(DOCKER_IMAGE_NAME):$(VERSION)
|
||||
docker push $(DOCKER_IMAGE_NAME):latest
|
||||
docker tag $(DOCKER_IMAGE_NAME):$(VERSION) quay.io/$(DOCKER_IMAGE_NAME):$(VERSION)
|
||||
docker tag $(DOCKER_IMAGE_NAME):$(VERSION) quay.io/$(DOCKER_IMAGE_NAME):latest
|
||||
docker push quay.io/$(DOCKER_IMAGE_NAME):$(VERSION)
|
||||
docker push quay.io/$(DOCKER_IMAGE_NAME):latest
|
||||
|
||||
version-set:
|
||||
@next="$(TAG)" && \
|
||||
current="$(VERSION)" && \
|
||||
sed -i '' "s/$$current/$$next/g" pkg/version/version.go && \
|
||||
sed -i '' "s/tag: $$current/tag: $$next/g" charts/podinfo/values.yaml && \
|
||||
sed -i '' "s/appVersion: $$current/appVersion: $$next/g" charts/podinfo/Chart.yaml && \
|
||||
sed -i '' "s/version: $$current/version: $$next/g" charts/podinfo/Chart.yaml && \
|
||||
sed -i '' "s/podinfo:$$current/podinfo:$$next/g" kustomize/deployment.yaml && \
|
||||
/usr/bin/sed -i '' "s/$$current/$$next/g" pkg/version/version.go && \
|
||||
/usr/bin/sed -i '' "s/tag: $$current/tag: $$next/g" charts/podinfo/values.yaml && \
|
||||
/usr/bin/sed -i '' "s/tag: $$current/tag: $$next/g" charts/podinfo/values-prod.yaml && \
|
||||
/usr/bin/sed -i '' "s/appVersion: $$current/appVersion: $$next/g" charts/podinfo/Chart.yaml && \
|
||||
/usr/bin/sed -i '' "s/version: $$current/version: $$next/g" charts/podinfo/Chart.yaml && \
|
||||
/usr/bin/sed -i '' "s/podinfo:$$current/podinfo:$$next/g" kustomize/deployment.yaml && \
|
||||
/usr/bin/sed -i '' "s/podinfo:$$current/podinfo:$$next/g" deploy/webapp/frontend/deployment.yaml && \
|
||||
/usr/bin/sed -i '' "s/podinfo:$$current/podinfo:$$next/g" deploy/webapp/backend/deployment.yaml && \
|
||||
/usr/bin/sed -i '' "s/podinfo:$$current/podinfo:$$next/g" deploy/bases/frontend/deployment.yaml && \
|
||||
/usr/bin/sed -i '' "s/podinfo:$$current/podinfo:$$next/g" deploy/bases/backend/deployment.yaml && \
|
||||
echo "Version $$next set in code, deployment, chart and kustomize"
|
||||
|
||||
release:
|
||||
git tag $(VERSION)
|
||||
git push origin $(VERSION)
|
||||
|
||||
swagger:
|
||||
go get github.com/swaggo/swag/cmd/swag
|
||||
cd pkg/api && $$(go env GOPATH)/bin/swag init -g server.go
|
||||
|
||||
135
README.md
135
README.md
@@ -1,22 +1,31 @@
|
||||
# podinfo
|
||||
|
||||
[](https://travis-ci.org/stefanprodan/podinfo)
|
||||
[](https://github.com/stefanprodan/podinfo/blob/master/.github/workflows/e2e.yml)
|
||||
[](https://github.com/stefanprodan/podinfo/blob/master/.github/workflows/test.yml)
|
||||
[](https://github.com/stefanprodan/podinfo/blob/master/.github/workflows/cve-scan.yml)
|
||||
[](https://goreportcard.com/report/github.com/stefanprodan/podinfo)
|
||||
[](https://hub.docker.com/r/stefanprodan/podinfo)
|
||||
|
||||
Podinfo is a tiny web application made with Go
|
||||
that showcases best practices of running microservices in Kubernetes.
|
||||
Podinfo is a tiny web application made with Go that showcases best practices of running microservices in Kubernetes.
|
||||
Podinfo is used by CNCF projects like [Flux](https://github.com/fluxcd/flux2) and [Flagger](https://github.com/fluxcd/flagger)
|
||||
for end-to-end testing and workshops.
|
||||
|
||||
Specifications:
|
||||
|
||||
* Health checks (readiness and liveness)
|
||||
* Graceful shutdown on interrupt signals
|
||||
* File watcher for secrets and configmaps
|
||||
* Instrumented with Prometheus
|
||||
* Tracing with Istio and Jaeger
|
||||
* Instrumented with Prometheus and Open Telemetry
|
||||
* Structured logging with zap
|
||||
* 12-factor app with viper
|
||||
* Fault injection (random errors and latency)
|
||||
* Helm chart
|
||||
* Swagger docs
|
||||
* Helm and Kustomize installers
|
||||
* End-to-End testing with Kubernetes Kind and Helm
|
||||
* Kustomize testing with GitHub Actions and Open Policy Agent
|
||||
* Multi-arch container image with Docker buildx and Github Actions
|
||||
* Container image signing with Sigstore cosign
|
||||
* CVE scanning with Trivy
|
||||
|
||||
Web API:
|
||||
|
||||
@@ -36,34 +45,54 @@ Web API:
|
||||
* `POST /token` issues a JWT token valid for one minute `JWT=$(curl -sd 'anon' podinfo:9898/token | jq -r .token)`
|
||||
* `GET /token/validate` validates the JWT token `curl -H "Authorization: Bearer $JWT" podinfo:9898/token/validate`
|
||||
* `GET /configs` returns a JSON with configmaps and/or secrets mounted in the `config` volume
|
||||
* `POST/PUT /cache/{key}` saves the posted content to Redis
|
||||
* `GET /cache/{key}` returns the content from Redis if the key exists
|
||||
* `DELETE /cache/{key}` deletes the key from Redis if exists
|
||||
* `POST /store` writes the posted content to disk at /data/hash and returns the SHA1 hash of the content
|
||||
* `GET /store/{hash}` returns the content of the file /data/hash if exists
|
||||
* `GET /ws/echo` echos content via websockets `podcli ws ws://localhost:9898/ws/echo`
|
||||
* `GET /chunked/{seconds}` uses `transfer-encoding` type `chunked` to give a partial response and then waits for the specified period
|
||||
* `GET /swagger.json` returns the API Swagger docs, used for Linkerd service profiling and Gloo routes discovery
|
||||
|
||||
gRPC API:
|
||||
|
||||
* `/grpc.health.v1.Health/Check` health checking
|
||||
|
||||
Web UI:
|
||||
|
||||

|
||||
|
||||
To access the Swagger UI open `<podinfo-host>/swagger/index.html` in a browser.
|
||||
|
||||
### Guides
|
||||
|
||||
* [GitOps Progressive Deliver with Flagger, Helm v3 and Linkerd](https://helm.workshop.flagger.dev/intro/)
|
||||
* [GitOps Progressive Deliver on EKS with Flagger and AppMesh](https://eks.handson.flagger.dev/prerequisites/)
|
||||
* [Automated canary deployments with Flagger and Istio](https://medium.com/google-cloud/automated-canary-deployments-with-flagger-and-istio-ac747827f9d1)
|
||||
* [Kubernetes autoscaling with Istio metrics](https://medium.com/google-cloud/kubernetes-autoscaling-with-istio-metrics-76442253a45a)
|
||||
* [Autoscaling EKS on Fargate with custom metrics](https://aws.amazon.com/blogs/containers/autoscaling-eks-on-fargate-with-custom-metrics/)
|
||||
* [Managing Helm releases the GitOps way](https://medium.com/google-cloud/managing-helm-releases-the-gitops-way-207a6ac6ff0e)
|
||||
* [Expose Kubernetes services over HTTPS with Ngrok](https://stefanprodan.com/2018/expose-kubernetes-services-over-http-with-ngrok/)
|
||||
* [Securing EKS Ingress With Contour And Let’s Encrypt The GitOps Way](https://aws.amazon.com/blogs/containers/securing-eks-ingress-contour-lets-encrypt-gitops/)
|
||||
|
||||
### Install
|
||||
|
||||
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
|
||||
|
||||
helm upgrade --install --wait backend \
|
||||
--namespace test \
|
||||
--set hpa.enabled=true \
|
||||
sp/podinfo
|
||||
--set redis.enabled=true \
|
||||
podinfo/podinfo
|
||||
```
|
||||
|
||||
Kustomize:
|
||||
@@ -71,3 +100,87 @@ Kustomize:
|
||||
```bash
|
||||
kubectl apply -k github.com/stefanprodan/podinfo//kustomize
|
||||
```
|
||||
|
||||
Docker:
|
||||
|
||||
```bash
|
||||
docker run -dp 9898:9898 stefanprodan/podinfo
|
||||
```
|
||||
|
||||
### Continuous Delivery
|
||||
|
||||
In order to install podinfo on a Kubernetes cluster and keep it up to date with the latest
|
||||
release in an automated manner, you can use [Flux](https://fluxcd.io).
|
||||
|
||||
Install the Flux CLI on MacOS and Linux using Homebrew:
|
||||
|
||||
```sh
|
||||
brew install fluxcd/tap/flux
|
||||
```
|
||||
|
||||
Install the Flux controllers needed for Helm operations:
|
||||
|
||||
```sh
|
||||
flux install \
|
||||
--namespace=flux-system \
|
||||
--network-policy=false \
|
||||
--components=source-controller,helm-controller
|
||||
```
|
||||
|
||||
Add podinfo's Helm repository to your cluster and
|
||||
configure Flux to check for new chart releases every ten minutes:
|
||||
|
||||
```sh
|
||||
flux create source helm podinfo \
|
||||
--namespace=default \
|
||||
--url=https://stefanprodan.github.io/podinfo \
|
||||
--interval=10m
|
||||
```
|
||||
|
||||
Create a `podinfo-values.yaml` file locally:
|
||||
|
||||
```sh
|
||||
cat > podinfo-values.yaml <<EOL
|
||||
replicaCount: 2
|
||||
resources:
|
||||
limits:
|
||||
memory: 256Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 64Mi
|
||||
EOL
|
||||
```
|
||||
|
||||
Create a Helm release for deploying podinfo in the default namespace:
|
||||
|
||||
```sh
|
||||
flux create helmrelease podinfo \
|
||||
--namespace=default \
|
||||
--source=HelmRepository/podinfo \
|
||||
--release-name=podinfo \
|
||||
--chart=podinfo \
|
||||
--chart-version=">5.0.0" \
|
||||
--values=podinfo-values.yaml
|
||||
```
|
||||
|
||||
Based on the above definition, Flux will upgrade the release automatically
|
||||
when a new version of podinfo is released. If the upgrade fails, Flux
|
||||
can [rollback](https://toolkit.fluxcd.io/components/helm/helmreleases/#configuring-failure-remediation)
|
||||
to the previous working version.
|
||||
|
||||
You can check what version is currently deployed with:
|
||||
|
||||
```sh
|
||||
flux get helmreleases -n default
|
||||
```
|
||||
|
||||
To delete podinfo's Helm repository and release from your cluster run:
|
||||
|
||||
```sh
|
||||
flux -n default delete source helm podinfo
|
||||
flux -n default delete helmrelease podinfo
|
||||
```
|
||||
|
||||
If you wish to manage the lifecycle of your applications in a **GitOps** manner, check out
|
||||
this [workflow example](https://github.com/fluxcd/flux2-kustomize-helm-example)
|
||||
for multi-env deployments with Flux, Kustomize and Helm.
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
.bzr/
|
||||
.bzrignore
|
||||
.hg/
|
||||
.hgignore
|
||||
.svn/
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
@@ -1,5 +0,0 @@
|
||||
apiVersion: v1
|
||||
appVersion: "1.0"
|
||||
description: A Ngrok Helm chart for Kubernetes
|
||||
name: ngrok
|
||||
version: 0.2.0
|
||||
@@ -1,64 +0,0 @@
|
||||
# Ngrok
|
||||
|
||||
Expose Kubernetes service with [Ngrok](https://ngrok.com).
|
||||
|
||||
## Installing the Chart
|
||||
|
||||
To install the chart with the release name `my-release`:
|
||||
|
||||
```console
|
||||
$ helm install sp/ngrok --name my-release \
|
||||
--set token=NGROK-TOKEN \
|
||||
--set expose.service=podinfo:9898
|
||||
```
|
||||
|
||||
The command deploys Ngrok on the Kubernetes cluster in the default namespace.
|
||||
The [configuration](#configuration) section lists the parameters that can be configured during installation.
|
||||
|
||||
## Uninstalling the Chart
|
||||
|
||||
To uninstall/delete the `my-release` deployment:
|
||||
|
||||
```console
|
||||
$ helm delete --purge my-release
|
||||
```
|
||||
|
||||
The command removes all the Kubernetes components associated with the chart and deletes the release.
|
||||
|
||||
## Configuration
|
||||
|
||||
The following tables lists the configurable parameters of the Grafana chart and their default values.
|
||||
|
||||
Parameter | Description | Default
|
||||
--- | --- | ---
|
||||
`image.repository` | Image repository | `stefanprodan/ngrok`
|
||||
`image.pullPolicy` | Image pull policy | `IfNotPresent`
|
||||
`image.tag` | Image tag | `latest`
|
||||
`replicaCount` | desired number of pods | `1`
|
||||
`tolerations` | List of node taints to tolerate | `[]`
|
||||
`affinity` | node/pod affinities | `node`
|
||||
`nodeSelector` | node labels for pod assignment | `{}`
|
||||
`service.type` | type of service | `ClusterIP`
|
||||
`token` | Ngrok auth token | `none`
|
||||
`expose.service` | Service address to be exposed as in `service-name:port` | `none`
|
||||
`subdomain` | Ngrok subdomain | `none`
|
||||
|
||||
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
|
||||
|
||||
```console
|
||||
$ helm upgrade --install --wait tunel \
|
||||
--set token=NGROK-TOKEN \
|
||||
--set service.type=NodePort \
|
||||
--set expose.service=podinfo:9898 \
|
||||
sp/ngrok
|
||||
```
|
||||
|
||||
Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart. For example,
|
||||
|
||||
```console
|
||||
$ helm install sp/grafana --name my-release -f values.yaml
|
||||
```
|
||||
|
||||
> **Tip**: You can use the default [values.yaml](values.yaml)
|
||||
```
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
1. Get the application URL by running these commands:
|
||||
{{- if contains "NodePort" .Values.service.type }}
|
||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "ngrok.fullname" . }})
|
||||
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||
echo http://$NODE_IP:$NODE_PORT
|
||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||
You can watch the status of by running 'kubectl get svc -w {{ template "ngrok.fullname" . }}'
|
||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "ngrok.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
|
||||
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "ngrok.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
||||
echo "Visit http://127.0.0.1:8080 to use your application"
|
||||
kubectl port-forward $POD_NAME 8080:80
|
||||
{{- end }}
|
||||
@@ -1,32 +0,0 @@
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "ngrok.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "ngrok.fullname" -}}
|
||||
{{- if .Values.fullnameOverride -}}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||
{{- if contains $name .Release.Name -}}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "ngrok.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
@@ -1,12 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ template "ngrok.fullname" . }}
|
||||
data:
|
||||
ngrok.yml: |-
|
||||
web_addr: 0.0.0.0:4040
|
||||
update: false
|
||||
log: stdout
|
||||
{{- if .Values.token }}
|
||||
authtoken: {{ .Values.token }}
|
||||
{{- end }}
|
||||
@@ -1,65 +0,0 @@
|
||||
apiVersion: apps/v1beta2
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ template "ngrok.fullname" . }}
|
||||
labels:
|
||||
app: {{ template "ngrok.name" . }}
|
||||
chart: {{ template "ngrok.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
spec:
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ template "ngrok.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ template "ngrok.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
annotations:
|
||||
prometheus.io/scrape: 'false'
|
||||
spec:
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
command:
|
||||
- ./ngrok
|
||||
- http
|
||||
{{- if .Values.subdomain }}
|
||||
- --subdomain={{ .Values.subdomain }}
|
||||
{{- end }}
|
||||
- {{ .Values.expose.service }}
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /home/ngrok/.ngrok2
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 4040
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /api/tunnels
|
||||
port: http
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 30
|
||||
resources:
|
||||
{{ toYaml .Values.resources | indent 12 }}
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{ toYaml . | indent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.affinity }}
|
||||
affinity:
|
||||
{{ toYaml . | indent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{ toYaml . | indent 8 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: {{ template "ngrok.fullname" . }}
|
||||
@@ -1,19 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ template "ngrok.fullname" . }}
|
||||
labels:
|
||||
app: {{ template "ngrok.name" . }}
|
||||
chart: {{ template "ngrok.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.service.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: {{ template "ngrok.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
@@ -1,27 +0,0 @@
|
||||
# Default values for ngrok.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
replicaCount: 1
|
||||
|
||||
image:
|
||||
repository: stefanprodan/ngrok
|
||||
tag: latest
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 4040
|
||||
|
||||
expose:
|
||||
service: ga-podinfo:9898
|
||||
|
||||
token: 4i3rDinhLqMHtvez71N9S_38rkS7onwv77VFNZTaUR6
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
||||
|
||||
subdomain:
|
||||
@@ -1,6 +1,6 @@
|
||||
apiVersion: v1
|
||||
version: 2.0.0
|
||||
appVersion: 2.0.0
|
||||
version: 6.1.0
|
||||
appVersion: 6.1.0
|
||||
name: podinfo
|
||||
engine: gotpl
|
||||
description: Podinfo Helm chart for Kubernetes
|
||||
@@ -10,3 +10,4 @@ maintainers:
|
||||
name: stefanprodan
|
||||
sources:
|
||||
- https://github.com/stefanprodan/podinfo
|
||||
kubeVersion: ">=1.19.0-0"
|
||||
|
||||
201
charts/podinfo/LICENSE
Normal file
201
charts/podinfo/LICENSE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2018 Stefan Prodan. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -1,15 +1,20 @@
|
||||
# Podinfo
|
||||
|
||||
Podinfo is a tiny web application made with Go
|
||||
Podinfo is a tiny web application made with Go
|
||||
that showcases best practices of running microservices in Kubernetes.
|
||||
|
||||
Podinfo is used by CNCF projects like [Flux](https://github.com/fluxcd/flux2)
|
||||
and [Flagger](https://github.com/fluxcd/flagger)
|
||||
for end-to-end testing and workshops.
|
||||
|
||||
## Installing the Chart
|
||||
|
||||
To install the chart with the release name `my-release`:
|
||||
|
||||
```console
|
||||
$ helm repo add sp https://stefanprodan.github.io/k8s-podinfo
|
||||
$ helm upgrade my-release --install sp/podinfo
|
||||
$ helm repo add podinfo https://stefanprodan.github.io/podinfo
|
||||
|
||||
$ helm upgrade -i my-release podinfo/podinfo
|
||||
```
|
||||
|
||||
The command deploys podinfo on the Kubernetes cluster in the default namespace.
|
||||
@@ -20,7 +25,7 @@ The [configuration](#configuration) section lists the parameters that can be con
|
||||
To uninstall/delete the `my-release` deployment:
|
||||
|
||||
```console
|
||||
$ helm delete --purge my-release
|
||||
$ helm delete my-release
|
||||
```
|
||||
|
||||
The command removes all the Kubernetes components associated with the chart and deletes the release.
|
||||
@@ -29,53 +34,90 @@ The command removes all the Kubernetes components associated with the chart and
|
||||
|
||||
The following tables lists the configurable parameters of the podinfo chart and their default values.
|
||||
|
||||
Parameter | Description | Default
|
||||
Parameter | Default | Description
|
||||
--- | --- | ---
|
||||
`affinity` | node/pod affinities | None
|
||||
`color` | UI color | blue
|
||||
`backend` | echo backend URL | None
|
||||
`faults.delay` | random HTTP response delays between 0 and 5 seconds | `false`
|
||||
`faults.error` | 1/3 chances of a random HTTP response error | `false`
|
||||
`hpa.enabled` | enables HPA | `false`
|
||||
`hpa.cpu` | target CPU usage per pod | None
|
||||
`hpa.memory` | target memory usage per pod | None
|
||||
`hpa.requests` | target requests per second per pod | None
|
||||
`hpa.maxReplicas` | maximum pod replicas | `10`
|
||||
`ingress.hosts` | ingress accepted hostnames | None
|
||||
`ingress.tls` | ingress TLS configuration | None:
|
||||
`image.pullPolicy` | image pull policy | `IfNotPresent`
|
||||
`image.repository` | image repository | `stefanprodan/podinfo`
|
||||
`image.tag` | image tag | `0.0.1`
|
||||
`ingress.enabled` | enables ingress | `false`
|
||||
`ingress.annotations` | ingress annotations | None
|
||||
`ingress.hosts` | ingress accepted hostnames | None
|
||||
`ingress.tls` | ingress TLS configuration | None
|
||||
`message` | UI greetings message | None
|
||||
`nodeSelector` | node labels for pod assignment | `{}`
|
||||
`replicaCount` | desired number of pods | `2`
|
||||
`resources.requests/cpu` | pod CPU request | `1m`
|
||||
`resources.requests/memory` | pod memory request | `16Mi`
|
||||
`resources.limits/cpu` | pod CPU limit | None
|
||||
`resources.limits/memory` | pod memory limit | None
|
||||
`service.externalPort` | external port for the service | `9898`
|
||||
`service.internalPort` | internal port for the service | `9898`
|
||||
`service.nodePort` | node port for the service | `31198`
|
||||
`service.type` | type of service | `ClusterIP`
|
||||
`tolerations` | list of node taints to tolerate | `[]`
|
||||
`replicaCount` | `1` | Desired number of pods
|
||||
`logLevel` | `info` | Log level: `debug`, `info`, `warn`, `error`
|
||||
`backend` | `None` | Echo backend URL
|
||||
`backends` | `[]` | Array of echo backend URLs
|
||||
`cache` | `None` | Redis address in the format `<host>:<port>`
|
||||
`redis.enabled` | `false` | Create Redis deployment for caching purposes
|
||||
`ui.color` | `#34577c` | UI color
|
||||
`ui.message` | `None` | UI greetings message
|
||||
`ui.logo` | `None` | UI logo
|
||||
`faults.delay` | `false` | Random HTTP response delays between 0 and 5 seconds
|
||||
`faults.error` | `false` | 1/3 chances of a random HTTP response error
|
||||
`faults.unhealthy` | `false` | When set, the healthy state is never reached
|
||||
`faults.unready` | `false` | When set, the ready state is never reached
|
||||
`faults.testFail` | `false` | When set, a helm test is included which always fails
|
||||
`faults.testTimeout` | `false` | When set, a helm test is included which always times out
|
||||
`image.repository` | `stefanprodan/podinfo` | Image repository
|
||||
`image.tag` | `<VERSION>` | Image tag
|
||||
`image.pullPolicy` | `IfNotPresent` | Image pull policy
|
||||
`service.enabled` | `true` | Create a Kubernetes Service, should be disabled when using [Flagger](https://flagger.app)
|
||||
`service.type` | `ClusterIP` | Type of the Kubernetes Service
|
||||
`service.metricsPort` | `9797` | Prometheus metrics endpoint port
|
||||
`service.httpPort` | `9898` | Container HTTP port
|
||||
`service.externalPort` | `9898` | ClusterIP HTTP port
|
||||
`service.grpcPort` | `9999` | ClusterIP gPRC port
|
||||
`service.grpcService` | `podinfo` | gPRC service name
|
||||
`service.nodePort` | `31198` | NodePort for the HTTP endpoint
|
||||
`h2c.enabled` | `false` | Allow upgrading to h2c (non-TLS version of HTTP/2)
|
||||
`hpa.enabled` | `false` | Enables the Kubernetes HPA
|
||||
`hpa.maxReplicas` | `10` | Maximum amount of pods
|
||||
`hpa.cpu` | `None` | Target CPU usage per pod
|
||||
`hpa.memory` | `None` | Target memory usage per pod
|
||||
`hpa.requests` | `None` | Target HTTP requests per second per pod
|
||||
`serviceAccount.enabled` | `false` | Whether a service account should be created
|
||||
`serviceAccount.name` | `None` | The name of the service account to use, if not set and create is true, a name is generated using the fullname template
|
||||
`securityContext` | `{}` | The security context to be set on the podinfo container
|
||||
`linkerd.profile.enabled` | `false` | Create Linkerd service profile
|
||||
`serviceMonitor.enabled` | `false` | Whether a Prometheus Operator service monitor should be created
|
||||
`serviceMonitor.interval` | `15s` | Prometheus scraping interval
|
||||
`serviceMonitor.additionalLabels` | `{}` | Add additional labels to the service monitor |
|
||||
`ingress.enabled` | `false` | Enables Ingress
|
||||
`ingress.className ` | `""` | Use ingressClassName
|
||||
`ingress.annotations` | `{}` | Ingress annotations
|
||||
`ingress.hosts` | `[]` | Ingress accepted hosts
|
||||
`ingress.tls` | `[]` | Ingress TLS configuration
|
||||
`resources.requests.cpu` | `1m` | Pod CPU request
|
||||
`resources.requests.memory` | `16Mi` | Pod memory request
|
||||
`resources.limits.cpu` | `None` | Pod CPU limit
|
||||
`resources.limits.memory` | `None` | Pod memory limit
|
||||
`nodeSelector` | `{}` | Node labels for pod assignment
|
||||
`tolerations` | `[]` | List of node taints to tolerate
|
||||
`affinity` | `None` | Node/pod affinities
|
||||
`podAnnotations` | `{}` | Pod annotations
|
||||
|
||||
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
|
||||
|
||||
```console
|
||||
$ helm install stable/podinfo --name my-release \
|
||||
--set=image.tag=0.0.2,service.type=NodePort
|
||||
$ helm install my-release podinfo/podinfo \
|
||||
--set=serviceMonitor.enabled=true,serviceMonitor.interval=5s
|
||||
```
|
||||
|
||||
To add custom annotations you need to escape the annotation key string:
|
||||
|
||||
```console
|
||||
$ helm upgrade -i my-release podinfo/podinfo \
|
||||
--set podAnnotations."appmesh\.k8s\.aws\/preview"=enabled
|
||||
```
|
||||
|
||||
Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart. For example,
|
||||
|
||||
```console
|
||||
$ helm install stable/podinfo --name my-release -f values.yaml
|
||||
$ helm install my-release podinfo/podinfo -f values.yaml
|
||||
```
|
||||
|
||||
> **Tip**: You can use the default [values.yaml](values.yaml)
|
||||
```
|
||||
|
||||
## Upgrading the chart
|
||||
|
||||
### To =< 5.0.0
|
||||
|
||||
Version 5.0.0 is a major update.
|
||||
|
||||
* The chart now follows the new Kubernetes label recommendations:
|
||||
<https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/>
|
||||
|
||||
The simplest way to update is to do a force upgrade, which recreates the resources by doing a delete and an install.
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
1. Get the application URL by running these commands:
|
||||
{{- if .Values.ingress.enabled }}
|
||||
{{- range .Values.ingress.hosts }}
|
||||
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }}
|
||||
{{- range $host := .Values.ingress.hosts }}
|
||||
{{- range .paths }}
|
||||
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- else if contains "NodePort" .Values.service.type }}
|
||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "podinfo.fullname" . }})
|
||||
@@ -11,9 +13,8 @@
|
||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||
You can watch the status of by running 'kubectl get svc -w {{ template "podinfo.fullname" . }}'
|
||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "podinfo.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
|
||||
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
||||
echo http://$SERVICE_IP:{{ .Values.service.externalPort }}
|
||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "podinfo.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
||||
echo "Visit http://127.0.0.1:8080 to use your application"
|
||||
kubectl port-forward $POD_NAME 8080:{{ .Values.service.externalPort }}
|
||||
kubectl -n {{ .Release.Namespace }} port-forward deploy/{{ template "podinfo.fullname" . }} 8080:{{ .Values.service.externalPort }}
|
||||
{{- end }}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "podinfo.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
@@ -12,21 +11,59 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "podinfo.fullname" -}}
|
||||
{{- if .Values.fullnameOverride -}}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||
{{- if contains $name .Release.Name -}}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- if .Values.fullnameOverride }}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "podinfo.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "podinfo.labels" -}}
|
||||
helm.sh/chart: {{ include "podinfo.chart" . }}
|
||||
{{ include "podinfo.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "podinfo.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "podinfo.fullname" . }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "podinfo.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.enabled }}
|
||||
{{- default (include "podinfo.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else }}
|
||||
{{- 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 }}
|
||||
16
charts/podinfo/templates/certificate.yaml
Normal file
16
charts/podinfo/templates/certificate.yaml
Normal 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 }}
|
||||
@@ -3,45 +3,102 @@ kind: Deployment
|
||||
metadata:
|
||||
name: {{ template "podinfo.fullname" . }}
|
||||
labels:
|
||||
app: {{ template "podinfo.name" . }}
|
||||
chart: {{ template "podinfo.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
{{- include "podinfo.labels" . | nindent 4 }}
|
||||
spec:
|
||||
{{- if not .Values.hpa.enabled }}
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
{{- end }}
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxUnavailable: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ template "podinfo.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
{{- include "podinfo.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ template "podinfo.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
{{- include "podinfo.selectorLabels" . | nindent 8 }}
|
||||
annotations:
|
||||
prometheus.io/scrape: 'true'
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/port: "{{ .Values.service.httpPort }}"
|
||||
{{- range $key, $value := .Values.podAnnotations }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
spec:
|
||||
terminationGracePeriodSeconds: 30
|
||||
{{- if .Values.serviceAccount.enabled }}
|
||||
serviceAccountName: {{ template "podinfo.serviceAccountName" . }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
{{- if .Values.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
{{- else if (or .Values.service.hostPort .Values.tls.hostPort) }}
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
add:
|
||||
- NET_BIND_SERVICE
|
||||
{{- end }}
|
||||
command:
|
||||
- ./podinfo
|
||||
- --port={{ .Values.service.containerPort }}
|
||||
- --port={{ .Values.service.httpPort | default 9898 }}
|
||||
{{- if .Values.host }}
|
||||
- --host={{ .Values.host }}
|
||||
{{- end }}
|
||||
{{- 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 }}
|
||||
{{- if .Values.service.grpcPort }}
|
||||
- --grpc-port={{ .Values.service.grpcPort }}
|
||||
{{- end }}
|
||||
{{- if .Values.service.grpcService }}
|
||||
- --grpc-service-name={{ .Values.service.grpcService }}
|
||||
{{- end }}
|
||||
{{- range .Values.backends }}
|
||||
- --backend-url={{ . }}
|
||||
{{- end }}
|
||||
{{- if .Values.cache }}
|
||||
- --cache-server={{ .Values.cache }}
|
||||
{{- else if .Values.redis.enabled }}
|
||||
- --cache-server={{ template "podinfo.fullname" . }}-redis:6379
|
||||
{{- end }}
|
||||
- --level={{ .Values.logLevel }}
|
||||
- --random-delay={{ .Values.faults.delay }}
|
||||
- --random-error={{ .Values.faults.error }}
|
||||
{{- if .Values.faults.unhealthy }}
|
||||
- --unhealthy
|
||||
{{- end }}
|
||||
{{- if .Values.faults.unready }}
|
||||
- --unready
|
||||
{{- end }}
|
||||
{{- if .Values.h2c.enabled }}
|
||||
- --h2c
|
||||
{{- end }}
|
||||
env:
|
||||
- name: PODINFO_UI_COLOR
|
||||
value: {{ .Values.color }}
|
||||
{{- if .Values.message }}
|
||||
{{- if .Values.ui.message }}
|
||||
- name: PODINFO_UI_MESSAGE
|
||||
value: {{ .Values.message }}
|
||||
value: {{ quote .Values.ui.message }}
|
||||
{{- end }}
|
||||
{{- if .Values.ui.logo }}
|
||||
- name: PODINFO_UI_LOGO
|
||||
value: {{ .Values.ui.logo }}
|
||||
{{- end }}
|
||||
{{- if .Values.ui.color }}
|
||||
- name: PODINFO_UI_COLOR
|
||||
value: {{ quote .Values.ui.color }}
|
||||
{{- end }}
|
||||
{{- if .Values.backend }}
|
||||
- name: PODINFO_BACKEND_URL
|
||||
@@ -49,16 +106,37 @@ spec:
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {{ .Values.service.containerPort }}
|
||||
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 }}
|
||||
protocol: TCP
|
||||
{{- end }}
|
||||
{{- if .Values.service.grpcPort }}
|
||||
- name: grpc
|
||||
containerPort: {{ .Values.service.grpcPort }}
|
||||
protocol: TCP
|
||||
{{- end }}
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- podcli
|
||||
- check
|
||||
- http
|
||||
- localhost:{{ .Values.service.containerPort }}/healthz
|
||||
initialDelaySeconds: 5
|
||||
- localhost:{{ .Values.service.httpPort | default 9898 }}/healthz
|
||||
initialDelaySeconds: 1
|
||||
timeoutSeconds: 5
|
||||
readinessProbe:
|
||||
exec:
|
||||
@@ -66,12 +144,17 @@ spec:
|
||||
- podcli
|
||||
- check
|
||||
- http
|
||||
- localhost:{{ .Values.service.containerPort }}/readyz
|
||||
initialDelaySeconds: 5
|
||||
- localhost:{{ .Values.service.httpPort | default 9898 }}/readyz
|
||||
initialDelaySeconds: 1
|
||||
timeoutSeconds: 5
|
||||
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 }}
|
||||
@@ -89,3 +172,8 @@ spec:
|
||||
volumes:
|
||||
- name: data
|
||||
emptyDir: {}
|
||||
{{- if .Values.tls.enabled }}
|
||||
- name: tls
|
||||
secret:
|
||||
secretName: {{ template "podinfo.tlsSecretName" . }}
|
||||
{{- end }}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
{{- if .Values.hpa.enabled -}}
|
||||
apiVersion: autoscaling/v2beta1
|
||||
apiVersion: autoscaling/v2beta2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: {{ template "podinfo.fullname" . }}
|
||||
labels:
|
||||
{{- include "podinfo.labels" . | nindent 4 }}
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1beta2
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{ template "podinfo.fullname" . }}
|
||||
minReplicas: {{ .Values.replicaCount }}
|
||||
@@ -15,18 +17,25 @@ spec:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
targetAverageUtilization: {{ .Values.hpa.cpu }}
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: {{ .Values.hpa.cpu }}
|
||||
{{- end }}
|
||||
{{- if .Values.hpa.memory }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
targetAverageValue: {{ .Values.hpa.memory }}
|
||||
target:
|
||||
type: AverageValue
|
||||
averageValue: {{ .Values.hpa.memory }}
|
||||
{{- end }}
|
||||
{{- if .Values.hpa.requests }}
|
||||
- type: Pod
|
||||
pods:
|
||||
metricName: http_requests
|
||||
targetAverageValue: {{ .Values.hpa.requests }}
|
||||
- type: Pods
|
||||
pods:
|
||||
metric:
|
||||
name: http_requests
|
||||
target:
|
||||
type: AverageValue
|
||||
averageValue: {{ .Values.hpa.requests }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
@@ -1,39 +1,41 @@
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
{{- $fullName := include "podinfo.fullname" . -}}
|
||||
{{- $servicePort := .Values.service.port -}}
|
||||
{{- $ingressPath := .Values.ingress.path -}}
|
||||
apiVersion: extensions/v1beta1
|
||||
{{- $svcPort := .Values.service.externalPort -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
labels:
|
||||
app: {{ template "podinfo.name" . }}
|
||||
chart: {{ template "podinfo.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
{{- include "podinfo.labels" . | nindent 4 }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
annotations:
|
||||
{{ toYaml . | indent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if .Values.ingress.tls }}
|
||||
tls:
|
||||
{{- range .Values.ingress.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
ingressClassName: {{ .Values.ingress.className }}
|
||||
{{- if .Values.ingress.tls }}
|
||||
tls:
|
||||
{{- range .Values.ingress.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- host: {{ . }}
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- host: {{ .host | quote }}
|
||||
http:
|
||||
paths:
|
||||
- path: {{ $ingressPath }}
|
||||
{{- range .paths }}
|
||||
- path: {{ .path }}
|
||||
pathType: {{ .pathType }}
|
||||
backend:
|
||||
serviceName: {{ $fullName }}
|
||||
servicePort: http
|
||||
{{- end }}
|
||||
service:
|
||||
name: {{ $fullName }}
|
||||
port:
|
||||
number: {{ $svcPort }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
98
charts/podinfo/templates/linkerd.yaml
Normal file
98
charts/podinfo/templates/linkerd.yaml
Normal file
@@ -0,0 +1,98 @@
|
||||
{{- if .Values.linkerd.profile.enabled -}}
|
||||
apiVersion: linkerd.io/v1alpha2
|
||||
kind: ServiceProfile
|
||||
metadata:
|
||||
name: {{ template "podinfo.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local
|
||||
labels:
|
||||
{{- include "podinfo.labels" . | nindent 4 }}
|
||||
spec:
|
||||
routes:
|
||||
- condition:
|
||||
method: GET
|
||||
pathRegex: /
|
||||
name: GET /
|
||||
- condition:
|
||||
method: POST
|
||||
pathRegex: /api/echo
|
||||
name: POST /api/echo
|
||||
- condition:
|
||||
method: GET
|
||||
pathRegex: /api/info
|
||||
name: GET /api/info
|
||||
- condition:
|
||||
method: GET
|
||||
pathRegex: /chunked/[^/]*
|
||||
name: GET /chunked/{seconds}
|
||||
- condition:
|
||||
method: GET
|
||||
pathRegex: /delay/[^/]*
|
||||
name: GET /delay/{seconds}
|
||||
- condition:
|
||||
method: GET
|
||||
pathRegex: /env
|
||||
name: GET /env
|
||||
- condition:
|
||||
method: GET
|
||||
pathRegex: /headers
|
||||
name: GET /headers
|
||||
- condition:
|
||||
method: GET
|
||||
pathRegex: /healthz
|
||||
name: GET /healthz
|
||||
- condition:
|
||||
method: GET
|
||||
pathRegex: /metrics
|
||||
name: GET /metrics
|
||||
- condition:
|
||||
method: GET
|
||||
pathRegex: /panic
|
||||
name: GET /panic
|
||||
- condition:
|
||||
method: GET
|
||||
pathRegex: /readyz
|
||||
name: GET /readyz
|
||||
- condition:
|
||||
method: POST
|
||||
pathRegex: /readyz/disable
|
||||
name: POST /readyz/disable
|
||||
- condition:
|
||||
method: POST
|
||||
pathRegex: /readyz/enable
|
||||
name: POST /readyz/enable
|
||||
- condition:
|
||||
method: GET
|
||||
pathRegex: /status/[^/]*
|
||||
name: GET /status/{code}
|
||||
- condition:
|
||||
method: POST
|
||||
pathRegex: /cache
|
||||
name: POST /cache
|
||||
- condition:
|
||||
method: GET
|
||||
pathRegex: /cache/[^/]*
|
||||
name: GET /cache/{hash}
|
||||
- condition:
|
||||
method: POST
|
||||
pathRegex: /store
|
||||
name: POST /store
|
||||
- condition:
|
||||
method: GET
|
||||
pathRegex: /store/[^/]*
|
||||
name: GET /store/{hash}
|
||||
- condition:
|
||||
method: POST
|
||||
pathRegex: /token
|
||||
name: POST /token
|
||||
- condition:
|
||||
method: POST
|
||||
pathRegex: /token/validate
|
||||
name: POST /token/validate
|
||||
- condition:
|
||||
method: GET
|
||||
pathRegex: /version
|
||||
name: GET /version
|
||||
- condition:
|
||||
method: POST
|
||||
pathRegex: /ws/echo
|
||||
name: POST /ws/echo
|
||||
{{- end }}
|
||||
12
charts/podinfo/templates/redis/config.yaml
Normal file
12
charts/podinfo/templates/redis/config.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
{{- if .Values.redis.enabled -}}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ template "podinfo.fullname" . }}-redis
|
||||
data:
|
||||
redis.conf: |
|
||||
maxmemory 64mb
|
||||
maxmemory-policy allkeys-lru
|
||||
save ""
|
||||
appendonly no
|
||||
{{- end }}
|
||||
68
charts/podinfo/templates/redis/deployment.yaml
Normal file
68
charts/podinfo/templates/redis/deployment.yaml
Normal file
@@ -0,0 +1,68 @@
|
||||
{{- if .Values.redis.enabled -}}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ template "podinfo.fullname" . }}-redis
|
||||
labels:
|
||||
app: {{ template "podinfo.fullname" . }}-redis
|
||||
spec:
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ template "podinfo.fullname" . }}-redis
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ template "podinfo.fullname" . }}-redis
|
||||
annotations:
|
||||
checksum/config: {{ include (print $.Template.BasePath "/redis/config.yaml") . | sha256sum | quote }}
|
||||
spec:
|
||||
{{- if .Values.serviceAccount.enabled }}
|
||||
serviceAccountName: {{ template "podinfo.serviceAccountName" . }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: redis
|
||||
image: "{{ .Values.redis.repository }}:{{ .Values.redis.tag }}"
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- redis-server
|
||||
- "/redis-master/redis.conf"
|
||||
ports:
|
||||
- name: redis
|
||||
containerPort: 6379
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: redis
|
||||
initialDelaySeconds: 5
|
||||
timeoutSeconds: 5
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- redis-cli
|
||||
- ping
|
||||
initialDelaySeconds: 5
|
||||
timeoutSeconds: 5
|
||||
resources:
|
||||
limits:
|
||||
cpu: 1000m
|
||||
memory: 128Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 32Mi
|
||||
volumeMounts:
|
||||
- mountPath: /var/lib/redis
|
||||
name: data
|
||||
- mountPath: /redis-master
|
||||
name: config
|
||||
volumes:
|
||||
- name: data
|
||||
emptyDir: {}
|
||||
- name: config
|
||||
configMap:
|
||||
name: {{ template "podinfo.fullname" . }}-redis
|
||||
items:
|
||||
- key: redis.conf
|
||||
path: redis.conf
|
||||
{{- end }}
|
||||
17
charts/podinfo/templates/redis/service.yaml
Normal file
17
charts/podinfo/templates/redis/service.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
{{- if .Values.redis.enabled -}}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ template "podinfo.fullname" . }}-redis
|
||||
labels:
|
||||
app: {{ template "podinfo.fullname" . }}-redis
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: {{ template "podinfo.fullname" . }}-redis
|
||||
ports:
|
||||
- name: redis
|
||||
port: 6379
|
||||
protocol: TCP
|
||||
targetPort: redis
|
||||
{{- end }}
|
||||
@@ -1,12 +1,14 @@
|
||||
{{- if .Values.service.enabled -}}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ template "podinfo.fullname" . }}
|
||||
labels:
|
||||
app: {{ template "podinfo.name" . }}
|
||||
chart: {{ template "podinfo.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
{{- include "podinfo.labels" . | nindent 4 }}
|
||||
{{- with .Values.service.annotations }}
|
||||
annotations:
|
||||
{{ toYaml . | indent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
ports:
|
||||
@@ -17,6 +19,18 @@ 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
|
||||
protocol: TCP
|
||||
name: grpc
|
||||
{{- end }}
|
||||
selector:
|
||||
app: {{ template "podinfo.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
{{- include "podinfo.selectorLabels" . | nindent 4 }}
|
||||
{{- end }}
|
||||
|
||||
8
charts/podinfo/templates/serviceaccount.yaml
Normal file
8
charts/podinfo/templates/serviceaccount.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
{{- if .Values.serviceAccount.enabled -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ template "podinfo.serviceAccountName" . }}
|
||||
labels:
|
||||
{{- include "podinfo.labels" . | nindent 4 }}
|
||||
{{- end -}}
|
||||
22
charts/podinfo/templates/servicemonitor.yaml
Normal file
22
charts/podinfo/templates/servicemonitor.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
{{- if .Values.serviceMonitor.enabled -}}
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: ServiceMonitor
|
||||
metadata:
|
||||
name: {{ template "podinfo.fullname" . }}
|
||||
labels:
|
||||
{{- include "podinfo.labels" . | nindent 4 }}
|
||||
{{- with .Values.serviceMonitor.additionalLabels }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
endpoints:
|
||||
- path: /metrics
|
||||
port: http
|
||||
interval: {{ .Values.serviceMonitor.interval }}
|
||||
namespaceSelector:
|
||||
matchNames:
|
||||
- {{ .Release.Namespace }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "podinfo.selectorLabels" . | nindent 6 }}
|
||||
{{- end }}
|
||||
29
charts/podinfo/templates/tests/cache.yaml
Normal file
29
charts/podinfo/templates/tests/cache.yaml
Normal file
@@ -0,0 +1,29 @@
|
||||
{{- if .Values.cache }}
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: {{ template "podinfo.fullname" . }}-cache-test-{{ randAlphaNum 5 | lower }}
|
||||
labels:
|
||||
{{- include "podinfo.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
"helm.sh/hook": test
|
||||
"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 -sd 'data' ${PODINFO_SVC}/cache/test &&
|
||||
curl -s ${PODINFO_SVC}/cache/test | grep data &&
|
||||
curl -s -XDELETE ${PODINFO_SVC}/cache/test
|
||||
env:
|
||||
- name: PODINFO_SVC
|
||||
value: "{{ template "podinfo.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.service.externalPort }}"
|
||||
restartPolicy: Never
|
||||
{{- end }}
|
||||
21
charts/podinfo/templates/tests/fail.yaml
Normal file
21
charts/podinfo/templates/tests/fail.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
{{- if .Values.faults.testFail }}
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: {{ template "podinfo.fullname" . }}-fault-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: fault
|
||||
image: alpine:3.11
|
||||
command: ['/bin/sh']
|
||||
args: ['-c', 'exit 1']
|
||||
restartPolicy: Never
|
||||
{{- end }}
|
||||
19
charts/podinfo/templates/tests/grpc.yaml
Normal file
19
charts/podinfo/templates/tests/grpc.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: {{ template "podinfo.fullname" . }}-grpc-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: grpc-health-probe
|
||||
image: stefanprodan/grpc_health_probe:v0.3.0
|
||||
command: ['grpc_health_probe']
|
||||
args: ['-addr={{ template "podinfo.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.service.grpcPort }}']
|
||||
restartPolicy: Never
|
||||
26
charts/podinfo/templates/tests/jwt.yaml
Normal file
26
charts/podinfo/templates/tests/jwt.yaml
Normal file
@@ -0,0 +1,26 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: {{ template "podinfo.fullname" . }}-jwt-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: tools
|
||||
image: giantswarm/tiny-tools
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
TOKEN=$(curl -sd 'test' ${PODINFO_SVC}/token | jq -r .token) &&
|
||||
curl -sH "Authorization: Bearer ${TOKEN}" ${PODINFO_SVC}/token/validate | grep test
|
||||
env:
|
||||
- name: PODINFO_SVC
|
||||
value: "{{ template "podinfo.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.service.externalPort }}"
|
||||
restartPolicy: Never
|
||||
@@ -3,16 +3,23 @@ kind: Pod
|
||||
metadata:
|
||||
name: {{ template "podinfo.fullname" . }}-service-test-{{ randAlphaNum 5 | lower }}
|
||||
labels:
|
||||
heritage: {{ .Release.Service }}
|
||||
release: {{ .Release.Name }}
|
||||
chart: {{ .Chart.Name }}-{{ .Chart.Version }}
|
||||
app: {{ template "podinfo.name" . }}
|
||||
{{- 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: radial/busyboxplus:curl
|
||||
command: ['curl']
|
||||
args: ['{{ template "podinfo.fullname" . }}:{{ .Values.service.externalPort }}']
|
||||
image: curlimages/curl:7.69.0
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
curl -s ${PODINFO_SVC}/api/info | grep version
|
||||
env:
|
||||
- name: PODINFO_SVC
|
||||
value: "{{ template "podinfo.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.service.externalPort }}"
|
||||
restartPolicy: Never
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: {{ template "podinfo.fullname" . }}-storage-test-{{ randAlphaNum 5 | lower }}
|
||||
labels:
|
||||
heritage: {{ .Release.Service }}
|
||||
release: {{ .Release.Name }}
|
||||
chart: {{ .Chart.Name }}-{{ .Chart.Version }}
|
||||
app: {{ template "podinfo.name" . }}
|
||||
annotations:
|
||||
"helm.sh/hook": test-success
|
||||
spec:
|
||||
containers:
|
||||
- name: tools
|
||||
image: giantswarm/tiny-tools
|
||||
command: ["/bin/sh", "/scripts/ping.sh"]
|
||||
env:
|
||||
- name: PODINFO_SVC
|
||||
value: {{ template "podinfo.fullname" . }}:{{ .Values.service.externalPort }}
|
||||
volumeMounts:
|
||||
- name: scripts
|
||||
mountPath: /scripts
|
||||
restartPolicy: Never
|
||||
volumes:
|
||||
- name: scripts
|
||||
configMap:
|
||||
name: {{ template "podinfo.fullname" . }}-storage-cfg
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ template "podinfo.fullname" . }}-storage-cfg
|
||||
labels:
|
||||
heritage: {{ .Release.Service }}
|
||||
release: {{ .Release.Name }}
|
||||
chart: {{ .Chart.Name }}-{{ .Chart.Version }}
|
||||
app: {{ template "podinfo.name" . }}
|
||||
data:
|
||||
ping.sh: |
|
||||
#!/bin/sh
|
||||
curl -sS ${PODINFO_SVC}/store/$(curl -sSd 'test' ${PODINFO_SVC}/store | jq -r .hash) |grep test
|
||||
21
charts/podinfo/templates/tests/timeout.yaml
Normal file
21
charts/podinfo/templates/tests/timeout.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
{{- if .Values.faults.testTimeout }}
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: {{ template "podinfo.fullname" . }}-fault-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: fault
|
||||
image: alpine:3.11
|
||||
command: ['/bin/sh']
|
||||
args: ['-c', 'while sleep 3600; do :; done']
|
||||
restartPolicy: Never
|
||||
{{- end }}
|
||||
27
charts/podinfo/templates/tests/tls.yaml
Normal file
27
charts/podinfo/templates/tests/tls.yaml
Normal 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 }}
|
||||
137
charts/podinfo/values-prod.yaml
Normal file
137
charts/podinfo/values-prod.yaml
Normal file
@@ -0,0 +1,137 @@
|
||||
# Production values for podinfo.
|
||||
# Includes Redis deployment and memory limits.
|
||||
|
||||
replicaCount: 1
|
||||
logLevel: info
|
||||
backend: #http://backend-podinfo:9898/echo
|
||||
backends: []
|
||||
|
||||
image:
|
||||
repository: ghcr.io/stefanprodan/podinfo
|
||||
tag: 6.1.0
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
ui:
|
||||
color: "#34577c"
|
||||
message: ""
|
||||
logo: ""
|
||||
|
||||
# failure conditions
|
||||
faults:
|
||||
delay: false
|
||||
error: false
|
||||
unhealthy: false
|
||||
unready: false
|
||||
testFail: false
|
||||
testTimeout: false
|
||||
|
||||
# Kubernetes Service settings
|
||||
service:
|
||||
enabled: true
|
||||
annotations: {}
|
||||
type: ClusterIP
|
||||
metricsPort: 9797
|
||||
httpPort: 9898
|
||||
externalPort: 9898
|
||||
grpcPort: 9999
|
||||
grpcService: podinfo
|
||||
nodePort: 31198
|
||||
|
||||
# enable h2c protocol (non-TLS version of HTTP/2)
|
||||
h2c:
|
||||
enabled: false
|
||||
|
||||
# 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 (cert-manager required)
|
||||
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:
|
||||
enabled: true
|
||||
maxReplicas: 5
|
||||
# average total CPU usage per pod (1-100)
|
||||
cpu: 99
|
||||
# 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: true
|
||||
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:
|
||||
|
||||
# set container security context
|
||||
securityContext: {}
|
||||
|
||||
ingress:
|
||||
enabled: false
|
||||
className: ""
|
||||
annotations: {}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
hosts:
|
||||
- host: podinfo.local
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
tls: []
|
||||
# - secretName: chart-example-tls
|
||||
# hosts:
|
||||
# - chart-example.local
|
||||
|
||||
linkerd:
|
||||
profile:
|
||||
enabled: false
|
||||
|
||||
# create Prometheus Operator monitor
|
||||
serviceMonitor:
|
||||
enabled: false
|
||||
interval: 15s
|
||||
additionalLabels: {}
|
||||
|
||||
resources:
|
||||
limits:
|
||||
memory: 256Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 64Mi
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
||||
|
||||
podAnnotations: {}
|
||||
@@ -2,24 +2,73 @@
|
||||
|
||||
replicaCount: 1
|
||||
logLevel: info
|
||||
color: blue
|
||||
host: #0.0.0.0
|
||||
backend: #http://backend-podinfo:9898/echo
|
||||
message: #UI greetings
|
||||
backends: []
|
||||
|
||||
image:
|
||||
repository: ghcr.io/stefanprodan/podinfo
|
||||
tag: 6.1.0
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
ui:
|
||||
color: "#34577c"
|
||||
message: ""
|
||||
logo: ""
|
||||
|
||||
# failure conditions
|
||||
faults:
|
||||
delay: false
|
||||
error: false
|
||||
unhealthy: false
|
||||
unready: false
|
||||
testFail: false
|
||||
testTimeout: false
|
||||
|
||||
image:
|
||||
repository: quay.io/stefanprodan/podinfo
|
||||
tag: 2.0.0
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
# Kubernetes Service settings
|
||||
service:
|
||||
enabled: true
|
||||
annotations: {}
|
||||
type: ClusterIP
|
||||
metricsPort: 9797
|
||||
httpPort: 9898
|
||||
externalPort: 9898
|
||||
containerPort: 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 h2c protocol (non-TLS version of HTTP/2)
|
||||
h2c:
|
||||
enabled: false
|
||||
|
||||
# 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 (cert-manager required)
|
||||
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:
|
||||
@@ -32,19 +81,50 @@ hpa:
|
||||
# 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:
|
||||
|
||||
# set container security context
|
||||
securityContext: {}
|
||||
|
||||
ingress:
|
||||
enabled: false
|
||||
className: ""
|
||||
annotations: {}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
path: /
|
||||
hosts:
|
||||
- podinfo.local
|
||||
- host: podinfo.local
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
tls: []
|
||||
# - secretName: chart-example-tls
|
||||
# hosts:
|
||||
# - chart-example.local
|
||||
|
||||
linkerd:
|
||||
profile:
|
||||
enabled: false
|
||||
|
||||
# create Prometheus Operator monitor
|
||||
serviceMonitor:
|
||||
enabled: false
|
||||
interval: 15s
|
||||
additionalLabels: {}
|
||||
|
||||
resources:
|
||||
limits:
|
||||
requests:
|
||||
@@ -57,3 +137,4 @@ tolerations: []
|
||||
|
||||
affinity: {}
|
||||
|
||||
podAnnotations: {}
|
||||
|
||||
@@ -14,14 +14,19 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/health/grpc_health_v1"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
var (
|
||||
retryCount int
|
||||
retryDelay time.Duration
|
||||
method string
|
||||
body string
|
||||
timeout time.Duration
|
||||
retryCount int
|
||||
retryDelay time.Duration
|
||||
method string
|
||||
body string
|
||||
timeout time.Duration
|
||||
grpcServiceName string
|
||||
)
|
||||
|
||||
var checkCmd = &cobra.Command{
|
||||
@@ -51,6 +56,13 @@ var checkCertCmd = &cobra.Command{
|
||||
RunE: runCheckCert,
|
||||
}
|
||||
|
||||
var checkgRPCCmd = &cobra.Command{
|
||||
Use: `grpc [address]`,
|
||||
Short: "gRPC health check",
|
||||
Example: ` check grpc localhost:8080 --service=podinfo --retry=1 --delay=2s --timeout=2s`,
|
||||
RunE: runCheckgPRC,
|
||||
}
|
||||
|
||||
func init() {
|
||||
checkUrlCmd.Flags().StringVar(&method, "method", "GET", "HTTP method")
|
||||
checkUrlCmd.Flags().StringVar(&body, "body", "", "HTTP POST/PUT content")
|
||||
@@ -64,6 +76,12 @@ func init() {
|
||||
checkTcpCmd.Flags().DurationVar(&timeout, "timeout", 5*time.Second, "timeout")
|
||||
checkCmd.AddCommand(checkTcpCmd)
|
||||
|
||||
checkgRPCCmd.Flags().IntVar(&retryCount, "retry", 0, "times to retry the TCP check")
|
||||
checkgRPCCmd.Flags().DurationVar(&retryDelay, "delay", 1*time.Second, "wait duration between retries")
|
||||
checkgRPCCmd.Flags().DurationVar(&timeout, "timeout", 5*time.Second, "timeout")
|
||||
checkgRPCCmd.Flags().StringVar(&grpcServiceName, "service", "", "gRPC service name")
|
||||
checkCmd.AddCommand(checkgRPCCmd)
|
||||
|
||||
checkCmd.AddCommand(checkCertCmd)
|
||||
|
||||
rootCmd.AddCommand(checkCmd)
|
||||
@@ -243,3 +261,53 @@ func fmtContentLength(b int64) string {
|
||||
}
|
||||
return fmt.Sprintf("%.1f %cB", float64(b)/float64(div), "kMGTPE"[exp])
|
||||
}
|
||||
|
||||
func runCheckgPRC(cmd *cobra.Command, args []string) error {
|
||||
if retryCount < 0 {
|
||||
return fmt.Errorf("--retry is required")
|
||||
}
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("address is required! example: check grpc localhost:8080")
|
||||
}
|
||||
address := args[0]
|
||||
|
||||
for n := 0; n <= retryCount; n++ {
|
||||
if n != 1 {
|
||||
time.Sleep(retryDelay)
|
||||
}
|
||||
|
||||
conn, err := grpc.Dial(address, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
logger.Info("check failed",
|
||||
zap.String("address", address),
|
||||
zap.Error(err))
|
||||
continue
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
resp, err := grpc_health_v1.NewHealthClient(conn).Check(ctx, &grpc_health_v1.HealthCheckRequest{
|
||||
Service: grpcServiceName,
|
||||
})
|
||||
cancel()
|
||||
|
||||
if err != nil {
|
||||
if stat, ok := status.FromError(err); ok && stat.Code() == codes.Unimplemented {
|
||||
logger.Info("gPRC health protocol not implemented")
|
||||
os.Exit(1)
|
||||
} else {
|
||||
logger.Info("check failed",
|
||||
zap.String("address", address),
|
||||
zap.Error(err))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
conn.Close()
|
||||
logger.Info("check succeed",
|
||||
zap.String("status", resp.GetStatus().String()))
|
||||
os.Exit(0)
|
||||
|
||||
}
|
||||
|
||||
os.Exit(1)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,365 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/go-getter"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
codeProjectName string
|
||||
codeGitUser string
|
||||
codeVersion string
|
||||
codeProjectPath string
|
||||
)
|
||||
|
||||
var codeCmd = &cobra.Command{
|
||||
Use: `code`,
|
||||
Short: "Code commands",
|
||||
}
|
||||
|
||||
var codeInitCmd = &cobra.Command{
|
||||
Use: `init [name]`,
|
||||
Short: "initialize podinfo code repo",
|
||||
Example: ` code init demo-app --version=v1.2.0 --git-user=stefanprodan`,
|
||||
RunE: runCodeInit,
|
||||
}
|
||||
|
||||
func init() {
|
||||
codeInitCmd.Flags().StringVar(&codeGitUser, "git-user", "", "GitHub user or org")
|
||||
codeInitCmd.Flags().StringVar(&codeVersion, "version", "master", "podinfo repo tag or branch name")
|
||||
codeInitCmd.Flags().StringVar(&codeProjectPath, "path", ".", "destination repo")
|
||||
|
||||
codeCmd.AddCommand(codeInitCmd)
|
||||
|
||||
rootCmd.AddCommand(codeCmd)
|
||||
}
|
||||
|
||||
func runCodeInit(cmd *cobra.Command, args []string) error {
|
||||
|
||||
if len(codeGitUser) < 0 {
|
||||
return fmt.Errorf("--git-user is required")
|
||||
}
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("project name is required")
|
||||
}
|
||||
|
||||
codeProjectName = args[0]
|
||||
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatalf("Error getting pwd: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
tmpPath := "/tmp/k8s-podinfo"
|
||||
versionName := fmt.Sprintf("k8s-podinfo-%s", codeVersion)
|
||||
|
||||
downloadURL := fmt.Sprintf("https://github.com/stefanprodan/podinfo/archive/%s.zip", codeVersion)
|
||||
client := &getter.Client{
|
||||
Src: downloadURL,
|
||||
Dst: tmpPath,
|
||||
Pwd: pwd,
|
||||
Mode: getter.ClientModeAny,
|
||||
}
|
||||
|
||||
fmt.Printf("Downloading %s\n", downloadURL)
|
||||
|
||||
if err := client.Get(); err != nil {
|
||||
log.Fatalf("Error downloading: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
pkgFrom := "github.com/stefanprodan/podinfo"
|
||||
pkgTo := fmt.Sprintf("github.com/%s/%s", codeGitUser, codeProjectName)
|
||||
|
||||
if err := replaceImports(tmpPath, pkgFrom, pkgTo); err != nil {
|
||||
log.Fatalf("Error parsing imports: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
dirs := []string{"pkg", "cmd", "ui", "vendor", ".github"}
|
||||
for _, dir := range dirs {
|
||||
|
||||
err = os.MkdirAll(path.Join(codeProjectPath, dir), os.ModePerm)
|
||||
if err != nil {
|
||||
log.Fatalf("Error: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := copyDir(path.Join(tmpPath, versionName, dir), path.Join(codeProjectPath, dir)); err != nil {
|
||||
log.Fatalf("Error: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
files := []string{"Gopkg.toml", "Gopkg.lock"}
|
||||
for _, file := range files {
|
||||
if err := copyFile(path.Join(tmpPath, versionName, file), path.Join(codeProjectPath, file)); err != nil {
|
||||
log.Fatalf("Error: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fileContent, err := ioutil.ReadFile(path.Join(codeProjectPath, file))
|
||||
if err != nil {
|
||||
log.Fatalf("Error: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
newContent := strings.Replace(string(fileContent), pkgFrom, pkgTo, -1)
|
||||
err = ioutil.WriteFile(path.Join(codeProjectPath, file), []byte(newContent), os.ModePerm)
|
||||
if err != nil {
|
||||
log.Fatalf("Error: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
projFrom := "stefanprodan/podinfo"
|
||||
projTo := fmt.Sprintf("%s/%s", codeGitUser, codeProjectName)
|
||||
|
||||
makeFiles := []string{"Makefile.gh", "Dockerfile.gh"}
|
||||
for _, file := range makeFiles {
|
||||
fileContent, err := ioutil.ReadFile(path.Join(tmpPath, versionName, file))
|
||||
if err != nil {
|
||||
log.Fatalf("Error: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
destFile := strings.Replace(file, ".gh", "", -1)
|
||||
newContent := strings.Replace(string(fileContent), projFrom, projTo, -1)
|
||||
err = ioutil.WriteFile(path.Join(codeProjectPath, destFile), []byte(newContent), os.ModePerm)
|
||||
if err != nil {
|
||||
log.Fatalf("Error: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
workflows := []string{".github/main.workflow"}
|
||||
for _, file := range workflows {
|
||||
fileContent, err := ioutil.ReadFile(path.Join(codeProjectPath, file))
|
||||
if err != nil {
|
||||
log.Fatalf("Error: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
newContent := strings.Replace(string(fileContent), "Dockerfile.gh", "Dockerfile", -1)
|
||||
err = ioutil.WriteFile(path.Join(codeProjectPath, file), []byte(newContent), os.ModePerm)
|
||||
if err != nil {
|
||||
log.Fatalf("Error: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
dockerFiles := []string{"Dockerfile.ci"}
|
||||
for _, file := range dockerFiles {
|
||||
fileContent, err := ioutil.ReadFile(path.Join(tmpPath, versionName, file))
|
||||
if err != nil {
|
||||
log.Fatalf("Error: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
newContent := strings.Replace(string(fileContent), projFrom, projTo, -1)
|
||||
err = ioutil.WriteFile(path.Join(codeProjectPath, file), []byte(newContent), os.ModePerm)
|
||||
if err != nil {
|
||||
log.Fatalf("Error: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
travisFiles := []string{"travis.lite.yml"}
|
||||
for _, file := range travisFiles {
|
||||
fileContent, err := ioutil.ReadFile(path.Join(tmpPath, versionName, file))
|
||||
if err != nil {
|
||||
log.Fatalf("Error: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
destFile := strings.Replace(file, "travis.lite.yml", ".travis.yml", -1)
|
||||
newContent := strings.Replace(string(fileContent), projFrom, projTo, -1)
|
||||
err = ioutil.WriteFile(path.Join(codeProjectPath, destFile), []byte(newContent), os.ModePerm)
|
||||
if err != nil {
|
||||
log.Fatalf("Error: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
err = gitPush()
|
||||
if err != nil {
|
||||
log.Fatalf("git push error: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Println("Initialization finished")
|
||||
return nil
|
||||
}
|
||||
|
||||
func gitPush() error {
|
||||
cmdPush := fmt.Sprintf("git add . && git commit -m \"sync %s\" && git push", codeVersion)
|
||||
cmd := exec.Command("sh", "-c", cmdPush)
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(string(output))
|
||||
return nil
|
||||
}
|
||||
|
||||
func replaceImports(projectPath string, pkgFrom string, pkgTo string) error {
|
||||
regexImport, err := regexp.Compile(`(?s)(import(.*?)\)|import.*$)`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
regexImportedPackage, err := regexp.Compile(`"(.*?)"`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
found := []string{}
|
||||
|
||||
err = filepath.Walk(projectPath, func(path string, info os.FileInfo, err error) error {
|
||||
if filepath.Ext(path) == ".go" {
|
||||
bts, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
content := string(bts)
|
||||
matches := regexImport.FindAllString(content, -1)
|
||||
isExists := false
|
||||
|
||||
isReplaceable:
|
||||
for _, each := range matches {
|
||||
for _, eachLine := range strings.Split(each, "\n") {
|
||||
matchesInline := regexImportedPackage.FindAllString(eachLine, -1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, eachSubline := range matchesInline {
|
||||
if strings.Contains(eachSubline, pkgFrom) {
|
||||
isExists = true
|
||||
break isReplaceable
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if isExists {
|
||||
content = strings.Replace(content, `"`+pkgFrom+`"`, `"`+pkgTo+`"`, -1)
|
||||
content = strings.Replace(content, `"`+pkgFrom+`/`, `"`+pkgTo+`/`, -1)
|
||||
found = append(found, path)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(path, []byte(content), info.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("ERROR", err.Error())
|
||||
}
|
||||
|
||||
if len(found) == 0 {
|
||||
fmt.Println("Nothing replaced")
|
||||
} else {
|
||||
fmt.Printf("Go imports total %d file replaced\n", len(found))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyDir(src string, dst string) error {
|
||||
si, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !si.IsDir() {
|
||||
return fmt.Errorf("source is not a directory")
|
||||
}
|
||||
|
||||
err = os.MkdirAll(dst, si.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
entries, err := ioutil.ReadDir(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
srcPath := filepath.Join(src, entry.Name())
|
||||
dstPath := filepath.Join(dst, entry.Name())
|
||||
|
||||
if entry.IsDir() {
|
||||
err = copyDir(srcPath, dstPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Skip symlinks.
|
||||
if entry.Mode()&os.ModeSymlink != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
err = copyFile(srcPath, dstPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyFile(src, dst string) (err error) {
|
||||
in, err := os.Open(src)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer in.Close()
|
||||
|
||||
out, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if e := out.Close(); e != nil {
|
||||
err = e
|
||||
}
|
||||
}()
|
||||
|
||||
_, err = io.Copy(out, in)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = out.Sync()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
si, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = os.Chmod(dst, si.Mode())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -2,11 +2,12 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"go.uber.org/zap"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/stefanprodan/podinfo/pkg/version"
|
||||
)
|
||||
|
||||
@@ -2,41 +2,58 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stefanprodan/podinfo/pkg/api"
|
||||
"github.com/stefanprodan/podinfo/pkg/signals"
|
||||
"github.com/stefanprodan/podinfo/pkg/version"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
|
||||
"github.com/stefanprodan/podinfo/pkg/api"
|
||||
"github.com/stefanprodan/podinfo/pkg/grpc"
|
||||
"github.com/stefanprodan/podinfo/pkg/signals"
|
||||
"github.com/stefanprodan/podinfo/pkg/version"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// flags definition
|
||||
fs := pflag.NewFlagSet("default", pflag.ContinueOnError)
|
||||
fs.Int("port", 9898, "port")
|
||||
fs.String("host", "", "Host to bind service to")
|
||||
fs.Int("port", 9898, "HTTP port to bind service to")
|
||||
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")
|
||||
fs.String("level", "info", "log level debug, info, warn, error, flat or panic")
|
||||
fs.String("backend-url", "", "backend service URL")
|
||||
fs.StringSlice("backend-url", []string{}, "backend service URL")
|
||||
fs.Duration("http-client-timeout", 2*time.Minute, "client timeout duration")
|
||||
fs.Duration("http-server-timeout", 30*time.Second, "server read and write timeout duration")
|
||||
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-color", "blue", "UI color")
|
||||
fs.String("ui-logo", "", "UI logo")
|
||||
fs.String("ui-color", "#34577c", "UI color")
|
||||
fs.String("ui-message", fmt.Sprintf("greetings from podinfo v%v", version.VERSION), "UI message")
|
||||
fs.Bool("random-delay", false, "between 0 and 5 seconds random delay")
|
||||
fs.Bool("h2c", false, "allow upgrading to H2C")
|
||||
fs.Bool("random-delay", false, "between 0 and 5 seconds random delay by default")
|
||||
fs.String("random-delay-unit", "s", "either s(seconds) or ms(milliseconds")
|
||||
fs.Int("random-delay-min", 0, "min for random delay: 0 by default")
|
||||
fs.Int("random-delay-max", 5, "max for random delay: 5 by default")
|
||||
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")
|
||||
fs.Bool("unhealthy", false, "when set, healthy state is never reached")
|
||||
fs.Bool("unready", false, "when set, ready state is never reached")
|
||||
fs.Int("stress-cpu", 0, "number of CPU cores with 100 load")
|
||||
fs.Int("stress-memory", 0, "MB of data to load into memory")
|
||||
fs.String("cache-server", "", "Redis address in the format <host>:<port>")
|
||||
fs.String("otel-service-name", "", "service name for reporting to open telemetry address, when not set tracing is disabled")
|
||||
|
||||
versionFlag := fs.BoolP("version", "v", false, "get version number")
|
||||
|
||||
@@ -59,6 +76,7 @@ func main() {
|
||||
viper.RegisterAlias("backendUrl", "backend-url")
|
||||
hostname, _ := os.Hostname()
|
||||
viper.SetDefault("jwt-secret", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9")
|
||||
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)
|
||||
@@ -67,11 +85,11 @@ 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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +108,38 @@ 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`")
|
||||
}
|
||||
|
||||
switch delayUnit := viper.GetString("random-delay-unit"); delayUnit {
|
||||
case
|
||||
"s",
|
||||
"ms":
|
||||
break
|
||||
default:
|
||||
logger.Panic("`random-delay-unit` accepted values are: s|ms")
|
||||
}
|
||||
|
||||
// load gRPC server config
|
||||
var grpcCfg grpc.Config
|
||||
if err := viper.Unmarshal(&grpcCfg); err != nil {
|
||||
logger.Panic("config unmarshal failed", zap.Error(err))
|
||||
}
|
||||
|
||||
// start gRPC server
|
||||
if grpcCfg.Port > 0 {
|
||||
grpcSrv, _ := grpc.NewServer(&grpcCfg, logger)
|
||||
go grpcSrv.ListenAndServe()
|
||||
}
|
||||
|
||||
// load HTTP server config
|
||||
var srvCfg api.Config
|
||||
if err := viper.Unmarshal(&srvCfg); err != nil {
|
||||
|
||||
45
deploy/README.md
Normal file
45
deploy/README.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Deploy demo webapp
|
||||
|
||||
Demo webapp manifests:
|
||||
|
||||
- [common](webapp/common)
|
||||
- [frontend](webapp/frontend)
|
||||
- [backend](webapp/backend)
|
||||
|
||||
Deploy the demo in `webapp` namespace:
|
||||
|
||||
```bash
|
||||
kubectl apply -f ./webapp/common
|
||||
kubectl apply -f ./webapp/backend
|
||||
kubectl apply -f ./webapp/frontend
|
||||
```
|
||||
|
||||
Deploy the demo in the `dev` namespace:
|
||||
|
||||
```bash
|
||||
kustomize build ./overlays/dev | kubectl apply -f-
|
||||
```
|
||||
|
||||
Deploy the demo in the `staging` namespace:
|
||||
|
||||
```bash
|
||||
kustomize build ./overlays/staging | kubectl apply -f-
|
||||
```
|
||||
|
||||
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
|
||||
```
|
||||
73
deploy/bases/backend/deployment.yaml
Normal file
73
deploy/bases/backend/deployment.yaml
Normal file
@@ -0,0 +1,73 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: backend
|
||||
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:
|
||||
containers:
|
||||
- name: backend
|
||||
image: ghcr.io/stefanprodan/podinfo:6.1.0
|
||||
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
|
||||
- --cache-server=cache:6379
|
||||
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
|
||||
18
deploy/bases/backend/hpa.yaml
Normal file
18
deploy/bases/backend/hpa.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
apiVersion: autoscaling/v2beta2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: backend
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: backend
|
||||
minReplicas: 1
|
||||
maxReplicas: 2
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 99
|
||||
7
deploy/bases/backend/kustomization.yaml
Normal file
7
deploy/bases/backend/kustomization.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- service.yaml
|
||||
- deployment.yaml
|
||||
- hpa.yaml
|
||||
|
||||
17
deploy/bases/backend/service.yaml
Normal file
17
deploy/bases/backend/service.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: backend
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: backend
|
||||
ports:
|
||||
- name: http
|
||||
port: 9898
|
||||
protocol: TCP
|
||||
targetPort: http
|
||||
- port: 9999
|
||||
targetPort: grpc
|
||||
protocol: TCP
|
||||
name: grpc
|
||||
57
deploy/bases/cache/deployment.yaml
vendored
Normal file
57
deploy/bases/cache/deployment.yaml
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: cache
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: cache
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: cache
|
||||
spec:
|
||||
containers:
|
||||
- name: redis
|
||||
image: redis:6.0.1
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- redis-server
|
||||
- "/redis-master/redis.conf"
|
||||
ports:
|
||||
- name: redis
|
||||
containerPort: 6379
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: redis
|
||||
initialDelaySeconds: 5
|
||||
timeoutSeconds: 5
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- redis-cli
|
||||
- ping
|
||||
initialDelaySeconds: 5
|
||||
timeoutSeconds: 5
|
||||
resources:
|
||||
limits:
|
||||
cpu: 1000m
|
||||
memory: 128Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 32Mi
|
||||
volumeMounts:
|
||||
- mountPath: /var/lib/redis
|
||||
name: data
|
||||
- mountPath: /redis-master
|
||||
name: config
|
||||
volumes:
|
||||
- name: data
|
||||
emptyDir: {}
|
||||
- name: config
|
||||
configMap:
|
||||
name: redis-config
|
||||
items:
|
||||
- key: redis.conf
|
||||
path: redis.conf
|
||||
9
deploy/bases/cache/kustomization.yaml
vendored
Normal file
9
deploy/bases/cache/kustomization.yaml
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- service.yaml
|
||||
- deployment.yaml
|
||||
configMapGenerator:
|
||||
- name: redis-config
|
||||
files:
|
||||
- redis.conf
|
||||
4
deploy/bases/cache/redis.conf
vendored
Normal file
4
deploy/bases/cache/redis.conf
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
maxmemory 64mb
|
||||
maxmemory-policy allkeys-lru
|
||||
save ""
|
||||
appendonly no
|
||||
13
deploy/bases/cache/service.yaml
vendored
Normal file
13
deploy/bases/cache/service.yaml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: cache
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: cache
|
||||
ports:
|
||||
- name: redis
|
||||
port: 6379
|
||||
protocol: TCP
|
||||
targetPort: redis
|
||||
72
deploy/bases/frontend/deployment.yaml
Normal file
72
deploy/bases/frontend/deployment.yaml
Normal file
@@ -0,0 +1,72 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: frontend
|
||||
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:
|
||||
containers:
|
||||
- name: frontend
|
||||
image: ghcr.io/stefanprodan/podinfo:6.1.0
|
||||
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
|
||||
- --level=info
|
||||
- --backend-url=http://backend:9898/echo
|
||||
- --cache-server=cache:6379
|
||||
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
|
||||
18
deploy/bases/frontend/hpa.yaml
Normal file
18
deploy/bases/frontend/hpa.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
apiVersion: autoscaling/v2beta2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: frontend
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: frontend
|
||||
minReplicas: 1
|
||||
maxReplicas: 4
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 99
|
||||
7
deploy/bases/frontend/kustomization.yaml
Normal file
7
deploy/bases/frontend/kustomization.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- service.yaml
|
||||
- deployment.yaml
|
||||
- hpa.yaml
|
||||
|
||||
13
deploy/bases/frontend/service.yaml
Normal file
13
deploy/bases/frontend/service.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: frontend
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: frontend
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
protocol: TCP
|
||||
targetPort: http
|
||||
48
deploy/kind.sh
Executable file
48
deploy/kind.sh
Executable file
@@ -0,0 +1,48 @@
|
||||
#! /usr/bin/env sh
|
||||
|
||||
mkdir -p bin
|
||||
cat > ./bin/kind.yaml <<EOF
|
||||
apiVersion: kind.x-k8s.io/v1alpha4
|
||||
kind: Cluster
|
||||
nodes:
|
||||
- role: control-plane
|
||||
extraPortMappings:
|
||||
- containerPort: 80
|
||||
hostPort: 80
|
||||
protocol: TCP
|
||||
- containerPort: 443
|
||||
hostPort: 443
|
||||
protocol: TCP
|
||||
EOF
|
||||
|
||||
# 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
|
||||
10
deploy/overlays/dev/kustomization.yaml
Normal file
10
deploy/overlays/dev/kustomization.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: dev
|
||||
resources:
|
||||
- ../../bases/backend
|
||||
- ../../bases/frontend
|
||||
- ../../bases/cache
|
||||
- namespace.yaml
|
||||
transformers:
|
||||
- labels.yaml
|
||||
10
deploy/overlays/dev/labels.yaml
Normal file
10
deploy/overlays/dev/labels.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: builtin
|
||||
kind: LabelTransformer
|
||||
metadata:
|
||||
name: labels
|
||||
labels:
|
||||
env: dev
|
||||
instance: webapp
|
||||
fieldSpecs:
|
||||
- path: metadata/labels
|
||||
create: true
|
||||
4
deploy/overlays/dev/namespace.yaml
Normal file
4
deploy/overlays/dev/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: dev
|
||||
10
deploy/overlays/production/kustomization.yaml
Normal file
10
deploy/overlays/production/kustomization.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: production
|
||||
resources:
|
||||
- ../../bases/backend
|
||||
- ../../bases/frontend
|
||||
- ../../bases/cache
|
||||
- namespace.yaml
|
||||
transformers:
|
||||
- labels.yaml
|
||||
10
deploy/overlays/production/labels.yaml
Normal file
10
deploy/overlays/production/labels.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: builtin
|
||||
kind: LabelTransformer
|
||||
metadata:
|
||||
name: labels
|
||||
labels:
|
||||
env: production
|
||||
instance: webapp
|
||||
fieldSpecs:
|
||||
- path: metadata/labels
|
||||
create: true
|
||||
4
deploy/overlays/production/namespace.yaml
Normal file
4
deploy/overlays/production/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: production
|
||||
10
deploy/overlays/staging/kustomization.yaml
Normal file
10
deploy/overlays/staging/kustomization.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: staging
|
||||
resources:
|
||||
- ../../bases/backend
|
||||
- ../../bases/frontend
|
||||
- ../../bases/cache
|
||||
- namespace.yaml
|
||||
transformers:
|
||||
- labels.yaml
|
||||
10
deploy/overlays/staging/labels.yaml
Normal file
10
deploy/overlays/staging/labels.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: builtin
|
||||
kind: LabelTransformer
|
||||
metadata:
|
||||
name: labels
|
||||
labels:
|
||||
env: staging
|
||||
instance: webapp
|
||||
fieldSpecs:
|
||||
- path: metadata/labels
|
||||
create: true
|
||||
4
deploy/overlays/staging/namespace.yaml
Normal file
4
deploy/overlays/staging/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: staging
|
||||
74
deploy/secure/backend/deployment.yaml
Normal file
74
deploy/secure/backend/deployment.yaml
Normal 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
|
||||
19
deploy/secure/backend/hpa.yaml
Normal file
19
deploy/secure/backend/hpa.yaml
Normal 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
|
||||
18
deploy/secure/backend/service.yaml
Normal file
18
deploy/secure/backend/service.yaml
Normal 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
|
||||
6
deploy/secure/common/cluster-issuer.yaml
Normal file
6
deploy/secure/common/cluster-issuer.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: ClusterIssuer
|
||||
metadata:
|
||||
name: self-signed
|
||||
spec:
|
||||
selfSigned: {}
|
||||
4
deploy/secure/common/namespace.yaml
Normal file
4
deploy/secure/common/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: secure
|
||||
29
deploy/secure/common/reconciler-rbac.yaml
Normal file
29
deploy/secure/common/reconciler-rbac.yaml
Normal 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
|
||||
5
deploy/secure/common/service-account.yaml
Normal file
5
deploy/secure/common/service-account.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: secure
|
||||
namespace: secure
|
||||
15
deploy/secure/frontend/certificate.yaml
Normal file
15
deploy/secure/frontend/certificate.yaml
Normal 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
|
||||
95
deploy/secure/frontend/deployment.yaml
Normal file
95
deploy/secure/frontend/deployment.yaml
Normal 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
|
||||
19
deploy/secure/frontend/hpa.yaml
Normal file
19
deploy/secure/frontend/hpa.yaml
Normal 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
|
||||
18
deploy/secure/frontend/service.yaml
Normal file
18
deploy/secure/frontend/service.yaml
Normal 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
|
||||
74
deploy/webapp/backend/deployment.yaml
Normal file
74
deploy/webapp/backend/deployment.yaml
Normal file
@@ -0,0 +1,74 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: backend
|
||||
namespace: webapp
|
||||
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: webapp
|
||||
containers:
|
||||
- name: backend
|
||||
image: ghcr.io/stefanprodan/podinfo:6.1.0
|
||||
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
|
||||
19
deploy/webapp/backend/hpa.yaml
Normal file
19
deploy/webapp/backend/hpa.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
apiVersion: autoscaling/v2beta2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: backend
|
||||
namespace: webapp
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: backend
|
||||
minReplicas: 1
|
||||
maxReplicas: 2
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 99
|
||||
18
deploy/webapp/backend/service.yaml
Normal file
18
deploy/webapp/backend/service.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: backend
|
||||
namespace: webapp
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: backend
|
||||
ports:
|
||||
- name: http
|
||||
port: 9898
|
||||
protocol: TCP
|
||||
targetPort: http
|
||||
- port: 9999
|
||||
targetPort: grpc
|
||||
protocol: TCP
|
||||
name: grpc
|
||||
4
deploy/webapp/common/namespace.yaml
Normal file
4
deploy/webapp/common/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: webapp
|
||||
29
deploy/webapp/common/reconciler-rbac.yaml
Normal file
29
deploy/webapp/common/reconciler-rbac.yaml
Normal file
@@ -0,0 +1,29 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: reconciler
|
||||
namespace: webapp
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: reconciler
|
||||
namespace: webapp
|
||||
rules:
|
||||
- apiGroups: ['*']
|
||||
resources: ['*']
|
||||
verbs: ['*']
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: reconciler
|
||||
namespace: webapp
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: reconciler
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: reconciler
|
||||
namespace: webapp
|
||||
5
deploy/webapp/common/service-account.yaml
Normal file
5
deploy/webapp/common/service-account.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: webapp
|
||||
namespace: webapp
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user