Compare commits

...

60 Commits

Author SHA1 Message Date
Weave Flux
82f2f9ecf9 Automated: default:deployment/podinfo
[ci skip]
2018-07-05 16:20:52 +00:00
Weave Flux
035f78edc1 Deautomated: default:deployment/podinfo
[ci skip]
2018-07-05 16:18:53 +00:00
Weave Flux
91c61d4fa5 Automated: default:deployment/podinfo
[ci skip]
2018-07-05 16:18:37 +00:00
Weave Flux
e673dae20d Release all latest to default:deployment/podinfo
[ci skip]
2018-07-05 16:04:30 +00:00
Weave Flux
adfff4a923 Release stefanprodan/podinfo:62fa684 to default:deployment/podinfo
[ci skip]
2018-07-05 16:01:53 +00:00
Weave Flux
4db9d5a1ed Release stefanprodan/podinfo:92114c0 to default:deployment/podinfo
[ci skip]
2018-07-05 16:01:21 +00:00
Ilya Dmitrichenko
92114c05c9 Change hash algorithm 2018-07-05 16:20:48 +01:00
Stefan Prodan
62fa684440 Release v4.0 2018-06-14 16:03:16 -07:00
Stefan Prodan
2aba7a3ed2 Update release automation list 2018-05-23 14:01:25 +03:00
Stefan Prodan
fda68019ea Merge pull request #5 from errordeveloper/master
Fix deploy guard logic
2018-05-21 13:06:28 +03:00
Ilya Dmitrichenko
39dde13700 Fix deploy guard logic, use multiple lines 2018-05-21 09:55:02 +01:00
Stefan Prodan
2485a10189 Merge pull request #3 from errordeveloper/master 2018-05-19 16:42:50 +03:00
Ilya Dmitrichenko
6c3569e131 Skip deploy on PR 2018-05-18 16:54:42 +01:00
Ilya Dmitrichenko
9b3a033845 Production deployment manifest for skaffold blog 2018-05-18 16:29:22 +01:00
Stefan Prodan
f02ebc267a Merge pull request #2 from errordeveloper/master
Add CircleCI
2018-05-17 14:55:31 +03:00
Ilya Dmitrichenko
01631a0a43 Add CircleCI 2018-05-17 12:51:52 +01:00
Stefan Prodan
a1e5cb77fd Merge pull request #1 from errordeveloper/master
Add Skaffold config files
2018-05-15 16:17:23 +03:00
Ilya Dmitrichenko
cdc6765b51 Add skaffold 2018-05-15 12:38:53 +01:00
Ilya Dmitrichenko
ff9cf93b14 Add .dockerignore 2018-05-11 14:53:17 +01:00
Stefan Prodan
5665149191 Set default port to 9898 2018-05-11 16:13:47 +03:00
Stefan Prodan
5a1f009200 Add Weave Flux Helm Operator diagram 2018-05-10 13:49:05 +03:00
Stefan Prodan
b6be95ee77 Bump podinfo Helm chart app version to v0.3 2018-05-10 11:56:47 +03:00
Stefan Prodan
ad22fdb933 Add canary deployments docs for Istio and Ambassador 2018-05-10 11:50:19 +03:00
Stefan Prodan
9b287dbf5c Add git poll interval option to Flux chart 2018-05-07 12:23:26 +03:00
Stefan Prodan
e81277f217 Release Flux chart 1.3.0 and Helm Operator v1alpha2 2018-05-07 11:16:00 +03:00
Stefan Prodan
e24c83525a Use http_request_duration_seconds for RED metrics 2018-05-07 11:03:02 +03:00
Stefan Prodan
65d03a557b Fix Quay push 2018-05-07 11:00:02 +03:00
Stefan Prodan
e93d0682fb bump version to 0.3.0 2018-05-02 23:08:43 +02:00
Stefan Prodan
a1bedc8c43 Update Weave Flux chart (Weave Cloud token option) 2018-04-25 15:01:19 +03:00
Stefan Prodan
07d3192afb Add Weave Cloud service token option 2018-04-25 15:00:27 +03:00
Stefan Prodan
ee10c878a0 Istio Canary GitOps mention the cluster config repo 2018-04-25 14:52:26 +03:00
Stefan Prodan
db9bf53e4f Istio Canary GitOps pipeline 2018-04-25 14:22:56 +03:00
Stefan Prodan
53d2609d8f Weave Scope Istio canary observability 2018-04-25 11:39:31 +03:00
Stefan Prodan
b34653912d Weave Cloud Istio canary observability 2018-04-25 11:17:43 +03:00
Stefan Prodan
1a2029f74d Use Weave Flux Helm Operator master-d5c374c 2018-04-24 00:09:51 +03:00
Stefan Prodan
68babf42e1 Add Weave Flux Helm Operator 2018-04-22 13:39:29 +03:00
Stefan Prodan
1330decdaa Add Weave Flux to podinfo Helm repo 2018-04-22 12:17:13 +03:00
Stefan Prodan
1682f79478 Add Weave Flux Git deploy setup docs 2018-04-22 12:16:49 +03:00
Stefan Prodan
93dee060dc Add Weave Flux OSS Helm chart 2018-04-21 21:34:06 +03:00
Stefan Prodan
797a4200dd Add Weave Cloud chart 2018-04-20 12:26:39 +03:00
Stefan Prodan
0c84164b65 Add Istio ingress to v1alpha3, remove v1alpha2 2018-04-20 01:03:16 +03:00
Stefan Prodan
b104769f20 Istio use Hey to generate load 2018-04-20 00:56:36 +03:00
Stefan Prodan
4acfdba296 Add ClusterIP service definition 2018-04-19 10:21:05 +03:00
Stefan Prodan
b5719fea3f Use test namespace 2018-04-17 14:58:40 +03:00
Stefan Prodan
00106faf8d Istio install steps 2018-04-17 14:13:08 +03:00
Stefan Prodan
88f417ee1c split Istio configs 2018-04-17 13:56:23 +03:00
Stefan Prodan
94441ef933 Istio - using same hosts has no effect 2018-04-17 11:47:44 +03:00
Stefan Prodan
b1871f827b Istio broken 2018-04-12 11:37:15 +01:00
Stefan Prodan
753799812a Fix istio.io/v1alpha3 definitions 2018-04-12 11:08:45 +01:00
Stefan Prodan
6aa5cbbaee Canary istio.io/v1alpha3 2018-04-12 10:15:13 +01:00
Stefan Prodan
4efde133e5 fix Travis Quay login 2018-04-12 10:14:51 +01:00
Stefan Prodan
60c0601128 try fix Travis Docker login 2018-04-11 18:05:02 +01:00
Stefan Prodan
d4882b4212 Istio canary deployments 2018-04-11 15:27:41 +01:00
Stefan Prodan
e4c765160a All namespace ops from K9 pod 2018-04-10 16:44:46 +01:00
Stefan Prodan
130e1dac8e Clone GCP Git repo on K9 IDE startup 2018-04-09 14:49:27 +01:00
Stefan Prodan
510864654f Add GCP Git support 2018-04-09 11:52:05 +01:00
Stefan Prodan
310643b0df Add Flux to the k9 setup 2018-04-08 01:24:17 +03:00
Stefan Prodan
6de537a315 Use Cloud9 golang image 2018-04-07 02:46:47 +03:00
Stefan Prodan
5d992a92bb Clone git repo at startup
- mount known_hosts from the ssh secret
2018-04-07 02:15:55 +03:00
Stefan Prodan
0aade8c049 Automate Git server repo seeding 2018-04-07 01:40:13 +03:00
74 changed files with 1751 additions and 74 deletions

38
.circleci/config.yml Normal file
View File

@@ -0,0 +1,38 @@
version: 2
jobs:
build:
docker:
- image: errordeveloper/skaffold:66cc263ef18f107adce245b8fc622a8ea46385f2
steps:
- checkout
- setup_remote_docker: {docker_layer_caching: true}
- run:
name: Run unit tests and build the image with Skaffold
command: skaffold build --profile=test
deploy:
docker:
- image: errordeveloper/skaffold:66cc263ef18f107adce245b8fc622a8ea46385f2
steps:
- checkout
- setup_remote_docker: {docker_layer_caching: true}
- run:
name: Build and push the image to the registry with Skaffold
command: |
if [[ -z "${CIRCLE_PULL_REQUEST}" ]] && [[ "${CIRCLE_PROJECT_USERNAME}" = "stefanprodan" ]] ; then
echo $REGISTRY_PASSWORD | docker login --username $REGISTRY_USERNAME --password-stdin
skaffold build --profile=production
else
echo "Do not push image"
fi
workflows:
version: 2
main:
jobs:
- build
- deploy:
requires: [build]
filters:
branches: {only: [master]}

9
.dockerignore Normal file
View File

@@ -0,0 +1,9 @@
docs
deploy
charts
cloudbuild.yaml
skaffold.yaml
.gitignore
.travis.yml
LICENSE
README.md

View File

@@ -32,12 +32,12 @@ after_success:
- if [ -z "$DOCKER_USER" ]; then
echo "PR build, skipping Docker Hub push";
else
docker login -u $DOCKER_USER -p $DOCKER_PASS;
echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin;
make docker-push;
fi
- if [ -z "$QUAY_USER" ]; then
echo "PR build, skipping Quay push";
else
docker login -u $QUAY_USER -p $QUAY_PASS quay.io;
echo $QUAY_PASS | docker login -u $QUAY_USER --password-stdin quay.io;
make quay-push;
fi

View File

@@ -71,7 +71,7 @@ docker-build: tar
.PHONY: docker-push
docker-push:
@echo Pushing: $(VERSION) to $(DOCKER_IMAGE_NAME)
for arch in $(LINUX_ARCH); do \
for arch in $(LINUX_ARCH); do \
docker push $(DOCKER_IMAGE_NAME):$(NAME)-$$arch ;\
done
manifest-tool push from-args --platforms $(PLATFORMS) --template $(DOCKER_IMAGE_NAME):podinfo-ARCH --target $(DOCKER_IMAGE_NAME):$(VERSION)
@@ -80,7 +80,7 @@ docker-push:
.PHONY: quay-push
quay-push:
@echo Pushing: $(VERSION) to quay.io/$(DOCKER_IMAGE_NAME):$(VERSION)
@cd build/docker/linux/amd64/ ; docker build -t quay.io/$(DOCKER_IMAGE_NAME):$(VERSION) . ; docker push quay.io/$(DOCKER_IMAGE_NAME):$(VERSION)
@docker build -t quay.io/$(DOCKER_IMAGE_NAME):$(VERSION) -f Dockerfile.ci . ; docker push quay.io/$(DOCKER_IMAGE_NAME):$(VERSION)
.PHONY: clean
clean:
@@ -110,4 +110,6 @@ charts:
mv charts/grafana-0.1.0.tgz docs/
cd charts/ && helm package ngrok/
mv charts/ngrok-0.1.0.tgz docs/
cd charts/ && helm package weave-flux/
mv charts/weave-flux-0.2.0.tgz docs/
helm repo index docs --url https://stefanprodan.github.io/k8s-podinfo --merge ./docs/index.yaml

View File

@@ -5,7 +5,7 @@ that showcases best practices of running microservices in Kubernetes.
Specifications:
* Multi-arch build and release automation (Make/TravisCI)
* Release automation (Make/TravisCI/CircleCI/Quay.io/Google Cloud Container Builder/Skaffold/Weave Flux)
* Multi-platform Docker image (amd64/arm/arm64/ppc64le/s390x)
* Health checks (readiness and liveness)
* Graceful shutdown on interrupt signals
@@ -39,5 +39,6 @@ Web API:
* [Horizontal Pod Auto-scaling](docs/2-autoscaling.md)
* [Monitoring and alerting with Prometheus](docs/3-monitoring.md)
* [StatefulSets with local persistent volumes](docs/4-statefulsets.md)
* [Canary Deployments and A/B Testing](docs/5-canary.md)
* [Expose Kubernetes services over HTTPS with Ngrok](docs/6-ngrok.md)
* [A/B Testing with Ambassador API Gateway](docs/5-canary.md)
* [Canary Deployments with Istio](docs/7-istio.md)

View File

@@ -1,5 +1,5 @@
apiVersion: v1
appVersion: "0.2.1"
appVersion: "0.4.0"
description: Podinfo Helm chart for Kubernetes
name: podinfo
version: 0.1.0

View File

@@ -5,7 +5,7 @@ backend: http://backend-podinfo:9898/echo
image:
repository: stefanprodan/podinfo
tag: 0.2.1
tag: 0.4.0
pullPolicy: IfNotPresent
service:

View File

@@ -0,0 +1,21 @@
# 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

View File

@@ -0,0 +1,13 @@
apiVersion: v1
appVersion: "1.0"
description: Weave Cloud is a add-on to Kubernetes which provides Continuous Delivery, along with hosted Prometheus Monitoring and a visual dashboard for exploring & debugging microservices
name: weave-cloud
version: 0.2.0
home: https://weave.works
maintainers:
- name: Ilya Dmitrichenko
email: ilya@weave.works
- name: Stefan Prodan
email: stefan@weave.works
engine: gotpl
icon: https://www.weave.works/assets/images/bltd108e8f850ae9e7c/weave-logo-512.png

View File

@@ -0,0 +1,53 @@
# Weave Cloud Agents
> ***NOTE: This chart is for Kubernetes version 1.6 and later.***
Weave Cloud is a add-on to Kubernetes which provides Continuous Delivery, along with hosted Prometheus Monitoring and a visual dashboard for exploring & debugging microservices.
This package contains the agents which connect your cluster to Weave Cloud.
_To learn more and sign up please visit [Weaveworks website](https://weave.works)._
You will need a service token which you can get from [cloud.weave.works](https://cloud.weave.works/).
## Installing the Chart
To install the chart:
```console
$ helm install --name weave-cloud --namespace weave --set token=<YOUR_WEAVE_CLOUD_SERVICE_TOKEN> stable/weave-cloud
```
To view the pods installed:
```console
$ kubectl get pods -n weave -l weave-cloud-component
```
To upgrade the chart:
```console
$ helm upgrade --reuse-values weave-cloud stable/weave-cloud
```
## Uninstalling the Chart
To uninstall/delete the `weave-cloud` chart:
```console
$ helm delete --purge weave-cloud
```
Delete the `weave` namespace:
```console
$ kubectl delete namespace weave
```
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 Weave Cloud Agents chart and their default values.
| Parameter | Description | Default |
| --------- | ----------- | ------- |
| `token` | Weave Cloud service token | _none_ _(**must be set**)_ |

View File

@@ -0,0 +1,28 @@
{{- if .Values.token -}}
Weave Cloud agents had been installed!
First, verify all Pods are running:
kubectl get pods -n {{ .Release.Namespace }}
Next, login to Weave Cloud (https://cloud.weave.works) and verify the agents are connect to your instance.
If you need help or have any question, join our Slack to chat to us https://slack.weave.works.
Happy hacking!
{{- else -}}
#######################################################
#### ERROR: Weave Cloud service token is missing ####
#######################################################
The installation of Weave Cloud agents is incomplete until you set the service token.
To retrieve your Weave Cloud service token, log in to your instance first: https://cloud.weave.works/instances
Then run:
helm upgrade {{ .Release.Name }} --set token=<YOUR_WEAVE_CLOUD_SERVICE_TOKEN> stable/weave-cloud
{{- end }}

View File

@@ -0,0 +1,32 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "weave-cloud.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 "weave-cloud.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 "weave-cloud.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

View File

@@ -0,0 +1,40 @@
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ .Values.agent.name }}
labels:
app: {{ .Values.agent.name }}
chart: {{ template "weave-cloud.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
minReadySeconds: 30
replicas: 1
revisionHistoryLimit: 2
selector:
matchLabels:
app: {{ .Values.agent.name }}
release: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ .Values.agent.name }}
release: {{ .Release.Name }}
spec:
serviceAccount: {{ .Values.agent.name }}
serviceAccountName: {{ .Values.agent.name }}
terminationGracePeriodSeconds: 30
containers:
- name: {{ .Values.agent.name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
args:
- -agent.poll-url=https://get.weave.works/k8s/agent.yaml?instanceID={{"{{.InstanceID}}"}}
- -wc.hostname=cloud.weave.works
- -wc.token=$(WEAVE_CLOUD_TOKEN)
env:
- name: WEAVE_CLOUD_TOKEN
valueFrom:
secretKeyRef:
key: token
name: weave-cloud

View File

@@ -0,0 +1,39 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.agent.name }}
namespace: {{ .Release.Namespace }}
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: {{ .Values.agent.name }}
labels:
name: {{ .Values.agent.name }}
rules:
- apiGroups:
- '*'
resources:
- '*'
verbs:
- '*'
- nonResourceURLs:
- '*'
verbs:
- '*'
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: {{ .Values.agent.name }}
labels:
name: {{ .Values.agent.name }}
roleRef:
kind: ClusterRole
name: {{ .Values.agent.name }}
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: {{ .Values.agent.name }}
namespace: {{ .Release.Namespace }}

View File

@@ -0,0 +1,7 @@
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: weave-cloud
data:
token: {{ .Values.token | b64enc }}

View File

@@ -0,0 +1,12 @@
# Default values for weave-cloud.
# token: ""
agent:
name: weave-agent
image:
repository: quay.io/weaveworks/launcher-agent
tag: master-b60524c
pullPolicy: IfNotPresent

View File

@@ -0,0 +1,21 @@
# 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

View File

@@ -0,0 +1,13 @@
apiVersion: v1
appVersion: "1.3.0"
description: Flux is a tool that automatically ensures that the state of a cluster matches what is specified in version control
name: weave-flux
version: 0.2.0
home: https://weave.works
sources:
- https://github.com/weaveworks/flux
maintainers:
- name: stefanprodan
email: stefan@weave.works
engine: gotpl
icon: https://landscape.cncf.io/logos/weave-flux.svg

115
charts/weave-flux/README.md Executable file
View File

@@ -0,0 +1,115 @@
# Weave Flux OSS
Flux is a tool that automatically ensures that the state of a cluster matches what is specified in version control.
It is most useful when used as a deployment tool at the end of a Continuous Delivery pipeline. Flux will make sure that your new container images and config changes are propagated to the cluster.
## Introduction
This chart bootstraps a [Weave Flux](https://github.com/weaveworks/flux) deployment on
a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.
## Prerequisites
- Kubernetes 1.7+
## Installing the Chart
To install the chart with the release name `cd`:
```console
$ helm install --name cd \
--set git.url=git@github.com:weaveworks/flux-example \
--namespace flux \
./charts/weave-flux
```
To install Flux with the Helm operator:
```console
$ helm install --name cd \
--set git.url=git@github.com:stefanprodan/weave-flux-helm-demo \
--set git.user="Stefan Prodan" \
--set git.email="stefan.prodan@gmail.com" \
--set helmOperator.create=true \
--namespace flux \
./charts/weave-flux
```
Be aware that the Helm operator is alpha quality, DO NOT use it on a production cluster.
The [configuration](#configuration) section lists the parameters that can be configured during installation.
### Setup Git deploy
At startup Flux generates a SSH key and logs the public key.
Find the SSH public key with:
```bash
export FLUX_POD=$(kubectl get pods --namespace flux -l "app=weave-flux,release=cd" -o jsonpath="{.items[0].metadata.name}")
kubectl -n flux logs $FLUX_POD | grep identity.pub | cut -d '"' -f2 | sed 's/.\{2\}$//'
```
In order to sync your cluster state with GitHub you need to copy the public key and
create a deploy key with write access on your GitHub repository.
## Uninstalling the Chart
To uninstall/delete the `cd` deployment:
```console
$ helm delete --purge cd
```
The command removes all the Kubernetes components associated with the chart and deletes the release.
You should also remove the deploy key from your GitHub repository.
## Configuration
The following tables lists the configurable parameters of the Weave Flux chart and their default values.
| Parameter | Description | Default |
| ------------------------------- | ------------------------------------------ | ---------------------------------------------------------- |
| `image.repository` | Image repository | `quay.io/weaveworks/flux`
| `image.tag` | Image tag | `1.2.5`
| `image.pullPoliwell cy` | Image pull policy | `IfNotPresent`
| `resources` | CPU/memory resource requests/limits | None
| `rbac.create` | If `true`, create and use RBAC resources | `true`
| `serviceAccount.create` | If `true`, create a new service account | `true`
| `serviceAccount.name` | Service account to be used | `weave-flux`
| `service.type` | Service type to be used | `ClusterIP`
| `service.port` | Service port to be used | `3030`
| `git.url` | URL of git repo with Kubernetes manifests | None
| `git.branch` | Branch of git repo to use for Kubernetes manifests | `master`
| `git.path` | Path within git repo to locate Kubernetes manifests (relative path) | None
| `git.user` | Username to use as git committer | `Weave Flux`
| `git.email` | Email to use as git committer | `support@weave.works`
| `git.chartsPath` | Path within git repo to locate Helm charts (relative path) | `charts`
| `git.pollInterval` | Period at which to poll git repo for new commits | `30s`
| `helmOperator.create` | If `true`, install the Helm operator | `false`
| `helmOperator.repository` | Helm operator image repository | `quay.io/weaveworks/helm-operator`
| `helmOperator.tag` | Helm operator image tag | `master-6f427cb`
| `helmOperator.pullPolicy` | Helm operator image pull policy | `IfNotPresent`
| `token` | Weave Cloud service token | None
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example:
```console
$ helm upgrade --install --wait cd \
--set git.url=git@github.com:stefanprodan/podinfo \
--set git.path=deploy/auto-scaling \
--namespace flux \
./charts/weave-flux
```
## Upgrade
Update Weave Flux version with:
```console
helm upgrade --reuse-values cd \
--set image.tag=1.2.6 \
./charts/weave-flux
```

View File

@@ -0,0 +1,19 @@
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 "weave-flux.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 "weave-flux.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "weave-flux.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 "weave-flux.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
kubectl -n {{ .Release.Namespace }} port-forward $POD_NAME 8080:3030
{{- end }}
2. Get the Git deploy key by running these commands:
export FLUX_POD=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "weave-flux.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
kubectl -n {{ .Release.Namespace }} logs $FLUX_POD | grep identity.pub | cut -d '"' -f2 | sed 's/.\{2\}$//'

View File

@@ -0,0 +1,43 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "weave-flux.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 "weave-flux.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 "weave-flux.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create the name of the service account to use
*/}}
{{- define "weave-flux.serviceAccountName" -}}
{{- if .Values.serviceAccount.create -}}
{{ default (include "weave-flux.fullname" .) .Values.serviceAccount.name }}
{{- else -}}
{{ default "default" .Values.serviceAccount.name }}
{{- end -}}
{{- end -}}

View File

@@ -0,0 +1,75 @@
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ template "weave-flux.fullname" . }}
labels:
app: {{ template "weave-flux.name" . }}
chart: {{ template "weave-flux.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ template "weave-flux.name" . }}
release: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ template "weave-flux.name" . }}
release: {{ .Release.Name }}
spec:
{{- if .Values.serviceAccount.create }}
serviceAccountName: {{ template "weave-flux.serviceAccountName" . }}
{{- end }}
volumes:
- name: git-key
secret:
secretName: {{ template "weave-flux.fullname" . }}-git-deploy
defaultMode: 0400
- name: git-keygen
emptyDir:
medium: Memory
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 3030
protocol: TCP
volumeMounts:
- name: git-key
mountPath: /etc/fluxd/ssh
readOnly: true
- name: git-keygen
mountPath: /var/fluxd/keygen
args:
- --ssh-keygen-dir=/var/fluxd/keygen
- --k8s-secret-name={{ template "weave-flux.fullname" . }}-git-deploy
- --memcached-hostname={{ template "weave-flux.fullname" . }}-memcached
- --git-url={{ .Values.git.url }}
- --git-branch={{ .Values.git.branch }}
- --git-path={{ .Values.git.path }}
- --git-user={{ .Values.git.user }}
- --git-email={{ .Values.git.email }}
- --git-poll-interval={{ .Values.git.pollInterval }}
- --sync-interval={{ .Values.git.pollInterval }}
{{- if .Values.token }}
- --connect=wss://cloud.weave.works/api/flux
- --token={{ .Values.token }}
{{- end }}
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 }}

View File

@@ -0,0 +1,19 @@
{{- if .Values.helmOperator.create -}}
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: fluxhelmreleases.helm.integrations.flux.weave.works
labels:
app: {{ template "weave-flux.name" . }}
chart: {{ template "weave-flux.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
group: helm.integrations.flux.weave.works
names:
kind: FluxHelmRelease
listKind: FluxHelmReleaseList
plural: fluxhelmreleases
scope: Namespaced
version: v1alpha2
{{- end -}}

View File

@@ -0,0 +1,43 @@
{{- if .Values.helmOperator.create -}}
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ template "weave-flux.fullname" . }}-helm-operator
labels:
app: {{ template "weave-flux.name" . }}-helm-operator
chart: {{ template "weave-flux.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ template "weave-flux.name" . }}-helm-operator
release: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ template "weave-flux.name" . }}-helm-operator
release: {{ .Release.Name }}
spec:
{{- if .Values.serviceAccount.create }}
serviceAccountName: {{ template "weave-flux.serviceAccountName" . }}
{{- end }}
volumes:
- name: git-key
secret:
secretName: {{ template "weave-flux.fullname" . }}-git-deploy
defaultMode: 0400
containers:
- name: flux-helm-operator
image: "{{ .Values.helmOperator.repository }}:{{ .Values.helmOperator.tag }}"
imagePullPolicy: {{ .Values.helmOperator.pullPolicy }}
volumeMounts:
- name: git-key
mountPath: /etc/fluxd/ssh
readOnly: true
args:
- --git-url={{ .Values.git.url }}
- --git-branch={{ .Values.git.branch }}
- --git-charts-path={{ .Values.git.chartsPath }}
{{- end -}}

View File

@@ -0,0 +1,54 @@
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ template "weave-flux.fullname" . }}-memcached
labels:
app: {{ template "weave-flux.name" . }}-memcached
chart: {{ template "weave-flux.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: {{ template "weave-flux.name" . }}-memcached
release: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ template "weave-flux.name" . }}-memcached
release: {{ .Release.Name }}
spec:
containers:
- name: memcached
image: memcached:1.4.25
imagePullPolicy: IfNotPresent
args:
- -m 64 # Maximum memory to use, in megabytes. 64MB is default.
- -p 11211 # Default port, but being explicit is nice.
- -vv # This gets us to the level of request logs.
ports:
- name: memcached
containerPort: 11211
---
apiVersion: v1
kind: Service
metadata:
name: {{ template "weave-flux.fullname" . }}-memcached
labels:
app: {{ template "weave-flux.name" . }}-memcached
chart: {{ template "weave-flux.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
clusterIP: None
ports:
- port: 11211
targetPort: memcached
protocol: TCP
name: memcached
selector:
app: {{ template "weave-flux.name" . }}-memcached
release: {{ .Release.Name }}

View File

@@ -0,0 +1,40 @@
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: {{ template "weave-flux.fullname" . }}
labels:
app: {{ template "weave-flux.name" . }}
chart: {{ template "weave-flux.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
rules:
- apiGroups:
- '*'
resources:
- '*'
verbs:
- '*'
- nonResourceURLs:
- '*'
verbs:
- '*'
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: {{ template "weave-flux.fullname" . }}
labels:
app: {{ template "weave-flux.name" . }}
chart: {{ template "weave-flux.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ template "weave-flux.fullname" . }}
subjects:
- name: {{ template "weave-flux.serviceAccountName" . }}
namespace: {{ .Release.Namespace | quote }}
kind: ServiceAccount
{{- end -}}

View File

@@ -0,0 +1,5 @@
apiVersion: v1
kind: Secret
metadata:
name: {{ template "weave-flux.fullname" . }}-git-deploy
type: Opaque

View File

@@ -0,0 +1,19 @@
apiVersion: v1
kind: Service
metadata:
name: {{ template "weave-flux.fullname" . }}
labels:
app: {{ template "weave-flux.name" . }}
chart: {{ template "weave-flux.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 "weave-flux.name" . }}
release: {{ .Release.Name }}

View File

@@ -0,0 +1,11 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ template "weave-flux.serviceAccountName" . }}
labels:
app: {{ template "weave-flux.name" . }}
chart: {{ template "weave-flux.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
{{- end -}}

View File

@@ -0,0 +1,64 @@
# Default values for weave-flux.
# Weave Cloud service token
token: ""
replicaCount: 1
image:
repository: quay.io/weaveworks/flux
tag: 1.3.0
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 3030
helmOperator:
create: false
repository: quay.io/weaveworks/helm-operator
tag: 0.1.0-alpha
pullPolicy: IfNotPresent
rbac:
# Specifies whether RBAC resources should be created
create: true
serviceAccount:
# Specifies whether a service account should be created
create: true
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name:
resources: {}
# If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
nodeSelector: {}
tolerations: []
affinity: {}
git:
# URL of git repo with Kubernetes manifests; e.g. git@github.com:weaveworks/flux-example
url: ""
# Branch of git repo to use for Kubernetes manifests
branch: "master"
# Path within git repo to locate Kubernetes manifests (relative path)
path: ""
# Username to use as git committer
user: "Weave Flux"
# Email to use as git committer
email: "support@weave.works"
# Path within git repo to locate Helm charts (relative path)
chartsPath: "charts"
# Period at which to poll git repo for new commits
pollInterval: "30s"

View File

@@ -17,7 +17,7 @@ var (
)
func init() {
flag.StringVar(&port, "port", "8989", "Port to listen on.")
flag.StringVar(&port, "port", "9898", "Port to listen on.")
flag.BoolVar(&debug, "debug", false, "sets log level to debug")
}

View File

@@ -0,0 +1,53 @@
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: podinfo-canary
namespace: test
labels:
app: podinfo
release: canary
spec:
replicas: 1
selector:
matchLabels:
app: podinfo
release: canary
template:
metadata:
labels:
app: podinfo
release: canary
annotations:
prometheus.io/scrape: 'true'
spec:
containers:
- name: podinfod
image: quay.io/stefanprodan/podinfo:0.2.2
imagePullPolicy: Always
command:
- ./podinfo
- -port=9898
- -debug=true
ports:
- name: http
containerPort: 9898
protocol: TCP
readinessProbe:
httpGet:
path: /readyz
port: 9898
initialDelaySeconds: 1
periodSeconds: 5
failureThreshold: 1
livenessProbe:
httpGet:
path: /healthz
port: 9898
initialDelaySeconds: 1
periodSeconds: 10
failureThreshold: 2
resources:
requests:
memory: "32Mi"
cpu: "10m"

View File

@@ -0,0 +1,18 @@
---
apiVersion: v1
kind: Service
metadata:
name: podinfo-canary
namespace: test
labels:
app: podinfo-canary
spec:
type: ClusterIP
ports:
- name: http
port: 9898
targetPort: http
protocol: TCP
selector:
app: podinfo
release: canary

View File

@@ -0,0 +1,53 @@
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: podinfo-ga
namespace: test
labels:
app: podinfo
release: ga
spec:
replicas: 1
selector:
matchLabels:
app: podinfo
release: ga
template:
metadata:
labels:
app: podinfo
release: ga
annotations:
prometheus.io/scrape: 'true'
spec:
containers:
- name: podinfod
image: quay.io/stefanprodan/podinfo:0.2.1
imagePullPolicy: Always
command:
- ./podinfo
- -port=9898
- -debug=true
ports:
- name: http
containerPort: 9898
protocol: TCP
readinessProbe:
httpGet:
path: /readyz
port: 9898
initialDelaySeconds: 1
periodSeconds: 5
failureThreshold: 1
livenessProbe:
httpGet:
path: /healthz
port: 9898
initialDelaySeconds: 1
periodSeconds: 10
failureThreshold: 2
resources:
requests:
memory: "32Mi"
cpu: "10m"

View File

@@ -0,0 +1,18 @@
---
apiVersion: v1
kind: Service
metadata:
name: podinfo-ga
namespace: test
labels:
app: podinfo-ga
spec:
type: ClusterIP
ports:
- name: http
port: 9898
targetPort: http
protocol: TCP
selector:
app: podinfo
release: ga

View File

@@ -0,0 +1,17 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: podinfo
namespace: test
annotations:
kubernetes.io/ingress.class: istio
spec:
rules:
- host: podinfo.co.uk
http:
paths:
- path: /.*
backend:
serviceName: podinfo
servicePort: 9898

View File

@@ -0,0 +1,15 @@
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: podinfo
namespace: test
spec:
name: podinfo.test
subsets:
- name: ga
labels:
release: ga
- name: canary
labels:
release: canary

View File

@@ -0,0 +1,19 @@
---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: podinfo-gateway
namespace: test
spec:
selector:
app: podinfo
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- podinfo.co.uk
- podinfo.test.svc.cluster.local

View File

@@ -0,0 +1,40 @@
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: podinfo
namespace: test
spec:
hosts:
- podinfo
- podinfo.co.uk
gateways:
- mesh
- podinfo-gateway
http:
- route:
- destination:
name: podinfo.test
subset: canary
weight: 20
- destination:
name: podinfo.test
subset: ga
weight: 80
# http:
# - match:
# - headers:
# x-user:
# exact: insider
# source_labels:
# release: ga
# route:
# - destination:
# name: podinfo.test
# subset: canary
# weight: 100
# - route:
# - destination:
# name: podinfo.test
# subset: ga
# weight: 100

View File

@@ -0,0 +1,17 @@
---
apiVersion: v1
kind: Service
metadata:
name: podinfo
namespace: test
labels:
app: podinfo
spec:
type: ClusterIP
ports:
- name: http
port: 9898
targetPort: http
protocol: TCP
selector:
app: podinfo

View File

@@ -12,13 +12,22 @@ Create a secret with the Git ssh key:
kubectl apply -f ./deploy/k9/ssh-key.yaml
```
Create the Git Server deploy and service:
Create the Git Server deployment and service:
```bash
kubectl apply -f ./deploy/k9/git-dep.yaml
kubectl apply -f ./deploy/k9/git-svc.yaml
```
Deploy Flux (modify fux-dep.yaml and add your weave token):
```bash
kubectl apply -f ./deploy/k9/memcache-dep.yaml
kubectl apply -f ./deploy/k9/memcache-svc.yaml
kubectl apply -f ./deploy/k9/flux-rbac.yaml
kubectl apply -f ./deploy/k9/flux-dep.yaml
```
Create the Cloud9 IDE deployment:
```bash
@@ -31,35 +40,21 @@ Find the public IP:
kubectl -n ide get svc --selector=name=ide
```
Open Cloud9 IDE in your browser, login with `username/password` and run the following commands:
Open Cloud9 IDE in your browser, login with `username/password` and config git:
```bash
ssh-keyscan gitsrv >> ~/.ssh/known_hosts
git config --global user.email "user@weavedx.com"
git config --global user.name "User"
```
Exec into the Git server and create a repo:
Commit a change to podinfo repo:
```bash
kubectl -n ide exec -it gitsrv-69b4cd5fc-dd6rf -- sh
/git-server # cd repos
/git-server # mkdir myrepo.git
/git-server # cd myrepo.git
/git-server # git init --shared=true
/git-server # git add .
/git-server # git config --global user.email "user@weavedx.com"
/git-server # git config --global user.name "User"
/git-server # git commit -m "init"
/git-server # git checkout -b dummy
```
Go back to the Cloud9 IDE and clone the repo:
```bash
git clone ssh://git@gitsrv/git-server/repos/myrepo.git
cd k8s-podinfo
rm Dockerfile.build
git add .
git commit -m "test"
git push origin master
```

52
deploy/k9/flux-dep.yaml Executable file
View File

@@ -0,0 +1,52 @@
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
labels:
name: flux
name: flux
namespace: ide
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
name: flux
template:
metadata:
labels:
name: flux
spec:
serviceAccount: flux
volumes:
- name: ssh-git
secret:
defaultMode: 0400
secretName: ssh-git
- name: git-keygen
emptyDir:
medium: Memory
containers:
- name: flux
image: quay.io/weaveworks/flux:1.2.5
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3030
volumeMounts:
- name: ssh-git
mountPath: /root/.ssh
readOnly: true
- name: ssh-git
mountPath: /etc/fluxd/ssh
readOnly: true
- name: git-keygen
mountPath: /var/fluxd/keygen
args:
- --ssh-keygen-dir=/var/fluxd/keygen
- --k8s-secret-name=ssh-git
- --git-url=ssh://git@gitsrv/git-server/repos/cluster.git
- --git-branch=master
#- --git-path=deploy/canary
#- --connect=wss://cloud.weave.works/api/flux
#- --token=yghrfcs5berdqp68z7wfndcea93rq6nx

36
deploy/k9/flux-rbac.yaml Executable file
View File

@@ -0,0 +1,36 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
name: flux
name: flux
namespace: ide
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
labels:
name: flux
name: flux
rules:
- apiGroups: ['*']
resources: ['*']
verbs: ['*']
- nonResourceURLs: ['*']
verbs: ['*']
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
labels:
name: flux
name: flux
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: flux
subjects:
- kind: ServiceAccount
name: flux
namespace: ide

View File

@@ -17,8 +17,13 @@ spec:
name: gitsrv
spec:
containers:
- image: jkarlos/git-server-docker
- image: stefanprodan/gitsrv:0.0.5
name: git
env:
- name: REPO
value: "cluster.git"
- name: TAR_URL
value: "https://github.com/stefanprodan/kubecon-cluster/archive/0.0.1.tar.gz"
ports:
- containerPort: 22
name: ssh
@@ -33,5 +38,7 @@ spec:
secret:
secretName: ssh-git
- name: git-server-data
persistentVolumeClaim:
claimName: git-server-data
emptyDir: {}
# - name: git-server-data
# persistentVolumeClaim:
# claimName: git-server-data

16
deploy/k9/k9-cfg.yaml Normal file
View File

@@ -0,0 +1,16 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: k9-cfg
namespace: ide
data:
gcp-clone.sh: |
#!/usr/bin/env sh
export PATH=/google-cloud-sdk/bin:$PATH
git config --global credential.helper gcloud.sh
git config --global user.email "dx+training@weave.works"
git config --global user.name "k8s fan"
git clone -b master $1

View File

@@ -21,23 +21,37 @@ spec:
serviceAccount: ide
serviceAccountName: ide
initContainers:
- command:
- name: git-clone-cluster
command:
- /bin/sh
- -c
- test -d /workspace/k8s-podinfo || git clone https://github.com/stefanprodan/k8s-podinfo
k8s-podinfo
image: stefanprodan/k9c:0.1.0
- test -d /workspace/cluster || git clone -b master ssh://git@gitsrv/git-server/repos/cluster.git
image: stefanprodan/k9c:v2-gcloud
imagePullPolicy: IfNotPresent
name: git-clone
volumeMounts:
- mountPath: /workspace
name: data
name: ide-workspace-data
- mountPath: /root/.ssh
name: ssh-git
- name: git-clone-podinfo
command:
- /bin/bash
- -c
- /root/gcp-clone.sh https://source.developers.google.com/p/dx-general/r/podinfo
image: stefanprodan/k9c:v2-gcloud
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /workspace
name: ide-workspace-data
- mountPath: /root/gcp-clone.sh
subPath: gcp-clone.sh
name: git-init
containers:
- name: ide
args:
- --auth
- username:password
image: stefanprodan/k9c:0.1.0
image: stefanprodan/k9c:v2-gcloud
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
@@ -71,7 +85,7 @@ spec:
timeoutSeconds: 1
volumeMounts:
- mountPath: /workspace
name: data
name: ide-workspace-data
- mountPath: /var/run/docker.sock
name: dockersocket
- mountPath: /root/.ssh
@@ -81,12 +95,16 @@ spec:
secret:
defaultMode: 0600
secretName: ssh-git
- name: data
- name: git-init
configMap:
defaultMode: 0744
name: k9-cfg
- name: dockersocket
hostPath:
path: /var/run/docker.sock
type: ""
- name: ide-workspace-data
emptyDir: {}
# - name: ide-workspace-data
# persistentVolumeClaim:
# claimName: ide-workspace-data
- hostPath:
path: /var/run/docker.sock
type: ""
name: dockersocket

View File

@@ -19,15 +19,11 @@ rules:
resources:
- '*'
verbs:
- get
- list
- watch
- '*'
- nonResourceURLs:
- '*'
verbs:
- get
- list
- watch
- '*'
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding

31
deploy/k9/memcache-dep.yaml Executable file
View File

@@ -0,0 +1,31 @@
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
labels:
name: memcached
name: memcached
namespace: ide
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
name: memcached
template:
metadata:
labels:
name: memcached
spec:
containers:
- name: memcached
image: memcached:1.4.25
imagePullPolicy: IfNotPresent
args:
- -m 64 # Maximum memory to use, in megabytes. 64MB is default.
- -p 11211 # Default port, but being explicit is nice.
- -vv # This gets us to the level of request logs.
ports:
- name: clients
containerPort: 11211

15
deploy/k9/memcache-svc.yaml Executable file
View File

@@ -0,0 +1,15 @@
---
apiVersion: v1
kind: Service
metadata:
name: memcached
namespace: ide
spec:
# The memcache client uses DNS to get a list of memcached servers and then
# uses a consistent hash of the key to determine which server to pick.
clusterIP: None
ports:
- name: memcached
port: 11211
selector:
name: memcached

View File

@@ -3,6 +3,8 @@
apiVersion: v1
kind: Secret
data:
known_hosts: Z2l0c3J2IHNzaC1yc2EgQUFBQUIzTnphQzF5YzJFQUFBQURBUUFCQUFBQkFRRHQ2NU0wc2FGQTZFd3NqYzhtUTQwNWJJNDA2QnNGU0pyYkd6OUdGcmJXQm4wUnMzTG9pNFM2QURXZ1RXbGNzcEh2YmZtZjd2WFc5b2lUanhla2U4b0hQQ2ZGWXJIRmRQSzI2QmlnMkoxa0UyRHpST05pelpXY2R3OGRwcVJodnhsdDIrL0VKdXVheThDR1h6M1ZMQ1Y4TmdKYzVBWW1Bd05Qa25VaFdLeGFBemp3dlJkLzBjeVhyNHZ2Y1REY213UjYzb2lXY1JQa0hDWjVMQ2xGdVpFMDY1VWxtMm82Q2dJdGwrZTZNNW91RFNKV1pEcFlXV21tSkpKdjFEUW9ScnVOYmFmNWY0YmdXVmtLanJRLzBjQTRpV1dsa3dKTWxBV1FncDlzYUQwRzJGODNocmYyWGFwTS9jbFdURnlia3pQcVBxYXcyQkV3WFA2dldwNkExaVVSCmdpdHNydiBlY2RzYS1zaGEyLW5pc3RwMjU2IEFBQUFFMlZqWkhOaExYTm9ZVEl0Ym1semRIQXlOVFlBQUFBSWJtbHpkSEF5TlRZQUFBQkJCTTZXeVV4UVJQdFpoWUx4akc2WVJRT0hEL1NYLyt1STRYQm80NFVUU3UyMXVxbWYvbEc4Y0xXVGRNVnpEbFVEWTkvRHg0dEZ6OTZMVDk3a1VDMXBMSnM9CmdpdHNydiBzc2gtZWQyNTUxOSBBQUFBQzNOemFDMWxaREkxTlRFNUFBQUFJQU12MXoyWW5EdWc1TTRLbHAzRk1iQnZ3OU5kRnJ4N09tNXVFS0ZRczA3dAo=
identity: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBczNuS2xrdkhLYlBEVlZCZTJLdGJSQ0dIcmphYU5MVkI3bVRHMjEwSjZpRXg4RnJYCldkR1YvZDJOUWJhYVFDQ1JDaHc3THdqSFFkeU5lVHJoam0xbGgzY0xzRk04RTJxRUEwZ0hMdVVyL2dlTkx6K0kKN2pzc0xTakJ0MTB6NWVYVzFjNUJaWWRBdElOK3dOTmpPTFptR21uV0NCQjBBUmx2M3d6RFNjOXE4NXZ2UXRjRwpxWjNnY0tReS9ZVDd3TXM0Y052ZW9CWDlBNVZOcnZrTjlrT3VBYmlCTFpUMWtCMWxxNVVsQ3FRVUpBNFQ4bVN5Clh5eXNsejhGcWxTb2xac1FKQmtSZmlDYlNQcENPcEVmc1h4L3ltTzlCaGVzMTVBOW42cDlVc253dDRjRzhwYjYKaEV6K0ZYQ0M5N3QrUXJ6L2dIV2w1bGI5SFViWFJPQ3FSaGxZWFFJREFRQUJBb0lCQURPNmNhcDU4dEJSTUlhQgpZS1RnVnJDL1hVVFlGZ0FGRWhpczBTZmVuQUh3U1YxMlFVVnhBK01rblJjSWsxTFNVQnR5NFpmLzFyWmo1QjdCCjJzcmJPdjBkVWJBamZWZzNSZzlRRGtuMDRZWVpGUmMrSDdCU083eFVWK2tLb3UrckhBMkpvZzJxT3ZzTVAxZEMKVmdHOWlKWXFWUGNFRHZ0V0lvbE9PMmNsc2pTK0REZEd4b0J2amFRbzhHVlZkaUZrekdOVmdTQkZnM1dPZnRsOApKMjZyNndzYVVXZDYrYyt1aTRFdUtJTjg2SEhNT0t0bDExbjd6QjNYVWllTEZVSW1GUjhHNHRHQlZwZXhzeVFpCmxjc2dUM1NnWEZDOUp6Q0VSUGRrTXVLSHVWMDBad01maU1ZK3N4Z3RsdXJRMnNhbVhXTmV4eGRlanpDR1RIcWcKV2xRWkJtRUNnWUVBNE5CN3VwMjZURFlUV0tyZ014aGJueHJaT0wxY3VhT1lWQUJnWWh5b2JnMWVabE10Mk1pVgpVaWxaamFkRnZ5emZjR1BTVEpjSjVmMmkvQ0dzS243RXFxUXdoZnd1S3ZRZTQyazgwbk5BcUczdTkvdkl4bklCCnFGZW5kTTE3SlN2WkU3NXFCVE9uTXVVZ1NuNFJoTXpzOEg3UTFmZFQ4UGMvTVRmRVVKcTQzcGtDZ1lFQXpGOUMKd1g0Z0UvUnZlbWZRc0ZVZ29TQ0lQdkR1bFhNNzNsK09XRnByOE00MWxpeGcvd0lvQ2NFZlpGcFdLUkpqSmwvUwpOVFh3YVhnOGg4RGl3a3d3dzJmcmNvWTl2TGNIcGxvWVRkN1ZjUVk4UGRKdjNJeGFReld6SHpMR3N0M29hZ08rCmJDbStsMEY5TnY0VUdWRHUrT0RSQjJyRWo2b1ZGRmh0SUQxbmRtVUNnWUJHS3V3alQrMkFzZlFSM2F1Q1p4eloKcVFDWmhBajM3QWEwV1RXOENhUE1UYUhrSUJ3VUtHN3FxUHRKaWlicngyNnAzbzRaMTU2QVNVemdrd1h3Y1lhaQptQUtKSHkrdHVtb1ZvcGdZTzE2Mzh5LzkrSGt1N3hCellZQmpwV3JGTEUxaHF6SGVFOFFnejREbm56ZUtrb2QxCmZLOWp5UUZMR1hDQXhSNGg1bGpES1FLQmdRQytqUjlmNjZvYkVQQ1Q3NUhicHpPS0tCd0FtNEhJWkszd2M2WHoKNlRMMVRqOFdhd0J4SStDUzM3YldTWWhHT1RlckF2S3EzRVR4QWNObVM4amhva3BoRjFhbTdGVkp6Rm5jbCtwTApTTFkzOExsZ1p3SVhYK0dWQXMrbENpSExpaTMyRXRHTVpndW5XYzlXNCtWM2lVZVhVMzV4N1BHaWhkR3JxNXJyCjBYVFRKUUtCZ0FReUF0RlloVHRONktCSER2NFdiTDQxcnBtcUlVcUlpV0R6a3FPT1ZXcHgzYkpTdWVNeDEyUjQKWHVVaGkwL2ZqbGFvMmYwWTBqbTBDUlQ5ZmlhQW56WHNMRXNzN2JYQ0ZZcGt3V3ZrNnNqV1BCWGdPUnBZbklHNQpRRWNFeklzRDFKQm1EY0RxdWxpZ0dnUzNIdGhiWTl5WW4vU3l4d0owcU5ob3BDS1d2OWNOCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
id_rsa: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBczNuS2xrdkhLYlBEVlZCZTJLdGJSQ0dIcmphYU5MVkI3bVRHMjEwSjZpRXg4RnJYCldkR1YvZDJOUWJhYVFDQ1JDaHc3THdqSFFkeU5lVHJoam0xbGgzY0xzRk04RTJxRUEwZ0hMdVVyL2dlTkx6K0kKN2pzc0xTakJ0MTB6NWVYVzFjNUJaWWRBdElOK3dOTmpPTFptR21uV0NCQjBBUmx2M3d6RFNjOXE4NXZ2UXRjRwpxWjNnY0tReS9ZVDd3TXM0Y052ZW9CWDlBNVZOcnZrTjlrT3VBYmlCTFpUMWtCMWxxNVVsQ3FRVUpBNFQ4bVN5Clh5eXNsejhGcWxTb2xac1FKQmtSZmlDYlNQcENPcEVmc1h4L3ltTzlCaGVzMTVBOW42cDlVc253dDRjRzhwYjYKaEV6K0ZYQ0M5N3QrUXJ6L2dIV2w1bGI5SFViWFJPQ3FSaGxZWFFJREFRQUJBb0lCQURPNmNhcDU4dEJSTUlhQgpZS1RnVnJDL1hVVFlGZ0FGRWhpczBTZmVuQUh3U1YxMlFVVnhBK01rblJjSWsxTFNVQnR5NFpmLzFyWmo1QjdCCjJzcmJPdjBkVWJBamZWZzNSZzlRRGtuMDRZWVpGUmMrSDdCU083eFVWK2tLb3UrckhBMkpvZzJxT3ZzTVAxZEMKVmdHOWlKWXFWUGNFRHZ0V0lvbE9PMmNsc2pTK0REZEd4b0J2amFRbzhHVlZkaUZrekdOVmdTQkZnM1dPZnRsOApKMjZyNndzYVVXZDYrYyt1aTRFdUtJTjg2SEhNT0t0bDExbjd6QjNYVWllTEZVSW1GUjhHNHRHQlZwZXhzeVFpCmxjc2dUM1NnWEZDOUp6Q0VSUGRrTXVLSHVWMDBad01maU1ZK3N4Z3RsdXJRMnNhbVhXTmV4eGRlanpDR1RIcWcKV2xRWkJtRUNnWUVBNE5CN3VwMjZURFlUV0tyZ014aGJueHJaT0wxY3VhT1lWQUJnWWh5b2JnMWVabE10Mk1pVgpVaWxaamFkRnZ5emZjR1BTVEpjSjVmMmkvQ0dzS243RXFxUXdoZnd1S3ZRZTQyazgwbk5BcUczdTkvdkl4bklCCnFGZW5kTTE3SlN2WkU3NXFCVE9uTXVVZ1NuNFJoTXpzOEg3UTFmZFQ4UGMvTVRmRVVKcTQzcGtDZ1lFQXpGOUMKd1g0Z0UvUnZlbWZRc0ZVZ29TQ0lQdkR1bFhNNzNsK09XRnByOE00MWxpeGcvd0lvQ2NFZlpGcFdLUkpqSmwvUwpOVFh3YVhnOGg4RGl3a3d3dzJmcmNvWTl2TGNIcGxvWVRkN1ZjUVk4UGRKdjNJeGFReld6SHpMR3N0M29hZ08rCmJDbStsMEY5TnY0VUdWRHUrT0RSQjJyRWo2b1ZGRmh0SUQxbmRtVUNnWUJHS3V3alQrMkFzZlFSM2F1Q1p4eloKcVFDWmhBajM3QWEwV1RXOENhUE1UYUhrSUJ3VUtHN3FxUHRKaWlicngyNnAzbzRaMTU2QVNVemdrd1h3Y1lhaQptQUtKSHkrdHVtb1ZvcGdZTzE2Mzh5LzkrSGt1N3hCellZQmpwV3JGTEUxaHF6SGVFOFFnejREbm56ZUtrb2QxCmZLOWp5UUZMR1hDQXhSNGg1bGpES1FLQmdRQytqUjlmNjZvYkVQQ1Q3NUhicHpPS0tCd0FtNEhJWkszd2M2WHoKNlRMMVRqOFdhd0J4SStDUzM3YldTWWhHT1RlckF2S3EzRVR4QWNObVM4amhva3BoRjFhbTdGVkp6Rm5jbCtwTApTTFkzOExsZ1p3SVhYK0dWQXMrbENpSExpaTMyRXRHTVpndW5XYzlXNCtWM2lVZVhVMzV4N1BHaWhkR3JxNXJyCjBYVFRKUUtCZ0FReUF0RlloVHRONktCSER2NFdiTDQxcnBtcUlVcUlpV0R6a3FPT1ZXcHgzYkpTdWVNeDEyUjQKWHVVaGkwL2ZqbGFvMmYwWTBqbTBDUlQ5ZmlhQW56WHNMRXNzN2JYQ0ZZcGt3V3ZrNnNqV1BCWGdPUnBZbklHNQpRRWNFeklzRDFKQm1EY0RxdWxpZ0dnUzNIdGhiWTl5WW4vU3l4d0owcU5ob3BDS1d2OWNOCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
id_rsa.pub: c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFDemVjcVdTOGNwczhOVlVGN1lxMXRFSVlldU5wbzB0VUh1Wk1iYlhRbnFJVEh3V3RkWjBaWDkzWTFCdHBwQUlKRUtIRHN2Q01kQjNJMTVPdUdPYldXSGR3dXdVendUYW9RRFNBY3U1U3YrQjQwdlA0anVPeXd0S01HM1hUUGw1ZGJWemtGbGgwQzBnMzdBMDJNNHRtWWFhZFlJRUhRQkdXL2ZETU5KejJyem0rOUMxd2FwbmVCd3BETDloUHZBeXpodzI5NmdGZjBEbFUydStRMzJRNjRCdUlFdGxQV1FIV1dybFNVS3BCUWtEaFB5WkxKZkxLeVhQd1dxVktpVm14QWtHUkYrSUp0SStrSTZrUit4ZkgvS1k3MEdGNnpYa0QyZnFuMVN5ZkMzaHdieWx2cUVUUDRWY0lMM3UzNUN2UCtBZGFYbVZ2MGRSdGRFNEtwR0dWaGQgdXNlckB3ZWF2ZWR4LmNvbQo=
metadata:

View File

@@ -0,0 +1,48 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: podinfo
labels:
app: podinfo
spec:
replicas: 1
selector:
matchLabels:
app: podinfo
template:
metadata:
labels:
app: podinfo
annotations:
prometheus.io/scrape: 'true'
spec:
containers:
- name: podinfod
image: podinfo
command:
- ./podinfo
- -port=9898
- -debug=true
ports:
- name: http
containerPort: 9898
protocol: TCP
readinessProbe:
httpGet:
path: /readyz
port: 9898
initialDelaySeconds: 1
periodSeconds: 5
failureThreshold: 1
livenessProbe:
httpGet:
path: /healthz
port: 9898
initialDelaySeconds: 1
periodSeconds: 10
failureThreshold: 2
resources:
requests:
memory: "32Mi"
cpu: "10m"

View File

@@ -0,0 +1,50 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: podinfo
labels:
app: podinfo
annotations:
flux.weave.works/automated: 'true'
spec:
replicas: 1
selector:
matchLabels:
app: podinfo
template:
metadata:
labels:
app: podinfo
annotations:
prometheus.io/scrape: 'true'
spec:
containers:
- name: podinfod
image: stefanprodan/podinfo:92114c0
command:
- ./podinfo
- -port=9898
- -debug=true
ports:
- name: http
containerPort: 9898
protocol: TCP
readinessProbe:
httpGet:
path: /readyz
port: 9898
initialDelaySeconds: 1
periodSeconds: 5
failureThreshold: 1
livenessProbe:
httpGet:
path: /healthz
port: 9898
initialDelaySeconds: 1
periodSeconds: 10
failureThreshold: 2
resources:
requests:
memory: "32Mi"
cpu: "10m"

View File

@@ -7,26 +7,26 @@ Prometheus query examples of key metrics to measure and alert upon.
**Request Rate** - the number of requests per second by instance
```
sum(irate(http_requests_count{job=~".*podinfo"}[1m])) by (instance)
sum(irate(http_request_duration_seconds_count{job=~".*podinfo"}[1m])) by (instance)
```
**Request Errors** - the number of failed requests per second by URL path
```
sum(irate(http_requests_count{job=~".*podinfo", status=~"5.."}[1m])) by (path)
sum(irate(http_request_duration_seconds_count{job=~".*podinfo", status=~"5.."}[1m])) by (path)
```
**Request Duration** - average duration of each request over 10 minutes
```
sum(rate(http_requests_sum{job=~".*podinfo"}[10m])) /
sum(rate(http_requests_count{job=~".*podinfo"}[10m]))
sum(rate(http_request_duration_seconds_sum{job=~".*podinfo"}[10m])) /
sum(rate(http_request_duration_seconds_count{job=~".*podinfo"}[10m]))
```
**Request Latency** - 99th percentile request latency over 10 minutes
```
histogram_quantile(0.99, sum(rate(http_requests_bucket{job=~".*podinfo"}[10m])) by (le))
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket{job=~".*podinfo"}[10m])) by (le))
```
**Goroutines Rate** - the number of running goroutines over 10 minutes

View File

@@ -1,4 +1,4 @@
# Canary Deployments and A/B Testing
# A/B Testing and Canary Deployments
Canary Deployment and A/B testing with Ambassador's Envoy API Gateway.

View File

@@ -1,13 +1,13 @@
# Expose Kubernetes services over HTTPS with Ngrok
Have you ever wanted to expose a Kubernetes service running on Minikube on the internet and have a
temporary HTTPS address for it? If so then Ngrok is the perfect solution to do that without any
temporary HTTPS address for it? If so then Ngrok is a great fit to do that without any
firewall, NAT or DNS configurations.
If you are developing an application that works with webhooks or oauth callbacks
Ngrok can create a tunnel between your Kubernetes service and their cloud platform and provide you with
a unique HTTPS URL that you can use to test and debug your service.
For this purpose I've made a Helm chart that you can use to deploy Ngrok on Kubernetes by specifying
I've made a Helm chart that you can use to deploy Ngrok on Kubernetes by specifying
a ClusterIP service that will get exposed on the internet.
What follows is a step-by-step guide on how you can use Ngrok as a reverse proxy to
@@ -63,13 +63,36 @@ helm install sp/podinfo --name webhook
This deploys `podinfo` in the default namespace and
creates a ClusterIP service with the address `webhook-podinfo:9898`.
```yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: podinfo
chart: podinfo-0.1.0
heritage: Tiller
release: webhook
name: webhook-podinfo
namespace: default
spec:
ports:
- name: http
port: 9898
protocol: TCP
targetPort: http
selector:
app: podinfo
release: webhook
type: ClusterIP
```
### Deploy Ngrok
Before you begin go to [ngrok.com](https://ngrok.com) and register for a free account.
Ngrok will create a token for you, use it when installing the Ngrok chart.
Install Ngrok:
Install Ngrok by specifying the ClusterIP address you want to expose:
```bash
$ helm install sp/ngrok --name tunnel \

231
docs/7-istio.md Normal file
View File

@@ -0,0 +1,231 @@
# Canary Deployments with Istio
### Install Istio
Download latest release:
```bash
curl -L https://git.io/getLatestIstio | sh -
```
Add the istioctl client to your PATH:
```bash
cd istio-0.7.1
export PATH=$PWD/bin:$PATH
```
Install Istio services without enabling mutual TLS authentication:
```bash
kubectl apply -f install/kubernetes/istio.yaml
```
### Set Istio automatic sidecar injection
Generate certs:
```bash
./install/kubernetes/webhook-create-signed-cert.sh \
--service istio-sidecar-injector \
--namespace istio-system \
--secret sidecar-injector-certs
```
Install the sidecar injection configmap:
```bash
kubectl apply -f install/kubernetes/istio-sidecar-injector-configmap-release.yaml
```
Set the caBundle in the webhook install YAML that the Kubernetes api-server uses to invoke the webhook:
```bash
cat install/kubernetes/istio-sidecar-injector.yaml | \
./install/kubernetes/webhook-patch-ca-bundle.sh > \
install/kubernetes/istio-sidecar-injector-with-ca-bundle.yaml
```
Install the sidecar injector webhook:
```bash
kubectl apply -f install/kubernetes/istio-sidecar-injector-with-ca-bundle.yaml
```
Create the `test` namespace:
```bash
kubectl create namespace test
```
Label the `test` namespace with `istio-injection=enabled`:
```bash
kubectl label namespace test istio-injection=enabled
```
### Run GA and Canary Deployments
Apply the podinfo ga and canary deployments and service:
```bash
kubectl -n test apply -f ./deploy/istio-v1alpha3/ga-dep.yaml,./deploy/istio-v1alpha3/canary-dep.yaml,./deploy/istio-v1alpha3/svc.yaml
```
Apply the istio destination rule, virtual service and gateway:
```bash
kubectl -n test apply -f ./deploy/istio-v1alpha3/istio-destination-rule.yaml
kubectl -n test apply -f ./deploy/istio-v1alpha3/istio-virtual-service.yaml
kubectl -n test apply -f ./deploy/istio-v1alpha3/istio-gateway.yaml
```
Create a `loadtest` pod for testing:
```bash
kubectl -n test run -i --rm --tty loadtest --image=stefanprodan/loadtest --restart=Never -- sh
```
Start the load test:
```bash
hey -n 1000000 -c 2 -q 5 http://podinfo.test:9898/version
```
**Initial state**
All traffic is routed to the GA deployment:
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: podinfo
namespace: test
spec:
hosts:
- podinfo
- podinfo.co.uk
gateways:
- mesh
- podinfo-gateway
http:
- route:
- destination:
name: podinfo.test
subset: canary
weight: 0
- destination:
name: podinfo.test
subset: ga
weight: 100
```
![s1](https://github.com/stefanprodan/k8s-podinfo/blob/master/docs/screens/istio-c-s1.png)
**Canary warm-up**
Route 10% of the traffic to the canary deployment:
```yaml
http:
- route:
- destination:
name: podinfo.test
subset: canary
weight: 10
- destination:
name: podinfo.test
subset: ga
weight: 90
```
![s2](https://github.com/stefanprodan/k8s-podinfo/blob/master/docs/screens/istio-c-s2.png)
**Canary promotion**
Increase the canary traffic to 60%:
```yaml
http:
- route:
- destination:
name: podinfo.test
subset: canary
weight: 60
- destination:
name: podinfo.test
subset: ga
weight: 40
```
![s3](https://github.com/stefanprodan/k8s-podinfo/blob/master/docs/screens/istio-c-s3.png)
Full promotion, 100% of the traffic to the canary:
```yaml
http:
- route:
- destination:
name: podinfo.test
subset: canary
weight: 100
- destination:
name: podinfo.test
subset: ga
weight: 0
```
![s4](https://github.com/stefanprodan/k8s-podinfo/blob/master/docs/screens/istio-c-s4.png)
Measure requests latency for each deployment:
![s5](https://github.com/stefanprodan/k8s-podinfo/blob/master/docs/screens/istio-c-s5.png)
Observe the traffic shift with Scope:
![s0](https://github.com/stefanprodan/k8s-podinfo/blob/master/docs/screens/istio-c-s0.png)
### Applying GitOps
![gitops](https://github.com/stefanprodan/k8s-podinfo/blob/master/docs/diagrams/istio-gitops.png)
Prerequisites for automating Istio canary deployments:
* create a cluster config Git repo that contains the desire state of your cluster
* keep the GA and Canary deployment definitions in Git
* keep the Istio destination rule, virtual service and gateway definitions in Git
* any changes to the above resources are performed via `git commit` instead of `kubectl apply`
Assuming that the GA is version `0.1.0` and the Canary is at `0.2.0`, you would probably
want to automate the deployment of patches for 0.1.x and 0.2.x.
Using Weave Cloud you can define a GitOps pipeline that will continuously monitor for new patches
and will apply them on both GA and Canary deployments using Weave Flux filters:
* `0.1.*` for GA
* `0.2.*` for Canary
Let's assume you've found a performance issue on the Canary by monitoring the request latency graph, for
some reason the Canary is responding slower than the GA.
CD GitOps pipeline steps:
* An engineer fixes the latency issue and cuts a new release by tagging the master branch as 0.2.1
* GitHub notifies GCP Container Builder that a new tag has been committed
* GCP Container Builder builds the Docker image, tags it as 0.2.1 and pushes it to Google Container Registry
* Weave Flux detects the new tag on GCR and updates the Canary deployment definition
* Weave Flux commits the Canary deployment definition to GitHub in the cluster repo
* Weave Flux triggers a rolling update of the Canary deployment
* Weave Cloud sends a Slack notification that the 0.2.1 patch has been released
Once the Canary is fixed you can keep increasing the traffic shift from GA by modifying the weight setting
and committing the changes in Git. Weave Cloud will detect that the cluster state is out of sync with
desired state described in git and will apply the changes.
If you notice that the Canary doesn't behave well under load you can revert the changes in Git and
Weave Flux will undo the weight settings by applying the desired state from Git on the cluster.
Keep iterating on the Canary code until the SLA is on a par with the GA release.

BIN
docs/diagrams/flux-helm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

View File

@@ -9,5 +9,6 @@ that showcases best practices of running microservices in Kubernetes.
* [Horizontal Pod Auto-scaling](2-autoscaling.md)
* [Monitoring and alerting with Prometheus](3-monitoring.md)
* [StatefulSets with local persistent volumes](4-statefulsets.md)
* [Canary Deployments and A/B Testing](5-canary.md)
* [Expose Kubernetes services over HTTPS with Ngrok](6-ngrok.md)
* [A/B Testing with Ambassador API Gateway](5-canary.md)
* [Canary Deployments with Istio](7-istio.md)

View File

@@ -3,7 +3,7 @@ entries:
ambassador:
- apiVersion: v1
appVersion: 0.29.0
created: 2018-03-25T11:44:07.51723005+03:00
created: 2018-05-10T11:55:31.454625986+03:00
description: A Helm chart for Datawire Ambassador
digest: a30c8cb38e696b09fda8269ad8465ce6fec6100cfc108ca85ecbc85913ca5c7f
engine: gotpl
@@ -19,7 +19,7 @@ entries:
grafana:
- apiVersion: v1
appVersion: "1.0"
created: 2018-03-25T11:44:07.518148658+03:00
created: 2018-05-10T11:55:31.455693067+03:00
description: A Helm chart for Kubernetes
digest: abdcadc5cddcb7c015aa5bb64e59bfa246774ad9243b3eb3c2a814abb38f2776
name: grafana
@@ -29,19 +29,19 @@ entries:
ngrok:
- apiVersion: v1
appVersion: "1.0"
created: 2018-03-25T11:44:07.518483193+03:00
created: 2018-05-10T11:55:31.456078781+03:00
description: A Ngrok Helm chart for Kubernetes
digest: 50036d831c06f55ef0f3a865613489d341f425b51f88bf25fe2005708ea24df5
digest: 7bf5ed2ef63ccd5efb76bcd9a086b04816a162c51d6ab592bccf58c283acd2ea
name: ngrok
urls:
- https://stefanprodan.github.io/k8s-podinfo/ngrok-0.1.0.tgz
version: 0.1.0
podinfo:
- apiVersion: v1
appVersion: 0.2.1
created: 2018-03-25T11:44:07.518906367+03:00
appVersion: 0.3.0
created: 2018-05-10T11:55:31.456571425+03:00
description: Podinfo Helm chart for Kubernetes
digest: f762207915a73faee72683b8ef8ac53da9db2dcbcf2107b2479d11beeb8f661f
digest: 4865a2d8b269cf453935cda9661c2efb82c16411471f8c11221a6d03d9bb58b1
engine: gotpl
home: https://github.com/stefanprodan/k8s-podinfo
maintainers:
@@ -53,4 +53,41 @@ entries:
urls:
- https://stefanprodan.github.io/k8s-podinfo/podinfo-0.1.0.tgz
version: 0.1.0
generated: 2018-03-25T11:44:07.516193733+03:00
weave-flux:
- apiVersion: v1
appVersion: 1.3.0
created: 2018-05-10T11:55:31.457640563+03:00
description: Flux is a tool that automatically ensures that the state of a cluster
matches what is specified in version control
digest: 1f52e427bb1d728641405f5ad9c514e8861905c110c14db95516629d24443b7d
engine: gotpl
home: https://weave.works
icon: https://landscape.cncf.io/logos/weave-flux.svg
maintainers:
- email: stefan@weave.works
name: stefanprodan
name: weave-flux
sources:
- https://github.com/weaveworks/flux
urls:
- https://stefanprodan.github.io/k8s-podinfo/weave-flux-0.2.0.tgz
version: 0.2.0
- apiVersion: v1
appVersion: 1.2.5
created: 2018-05-10T11:55:31.457125049+03:00
description: Flux is a tool that automatically ensures that the state of a cluster
matches what is specified in version control
digest: 9e18fb8d175f4fac3b054905c7110d18b6d18f884011df9e9d010c66337da7ec
engine: gotpl
home: https://weave.works
icon: https://www.weave.works/assets/images/bltd108e8f850ae9e7c/weave-logo-512.png
maintainers:
- email: stefan@weave.works
name: Stefan Prodan
name: weave-flux
sources:
- https://github.com/weaveworks/flux
urls:
- https://stefanprodan.github.io/k8s-podinfo/weave-flux-0.1.0.tgz
version: 0.1.0
generated: 2018-05-10T11:55:31.453916675+03:00

Binary file not shown.

Binary file not shown.

BIN
docs/screens/istio-c-s0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

BIN
docs/screens/istio-c-s1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

BIN
docs/screens/istio-c-s2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

BIN
docs/screens/istio-c-s3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
docs/screens/istio-c-s4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

BIN
docs/screens/istio-c-s5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

BIN
docs/weave-flux-0.1.0.tgz Normal file

Binary file not shown.

BIN
docs/weave-flux-0.2.0.tgz Normal file

Binary file not shown.

View File

@@ -2,7 +2,7 @@ package server
import (
"bytes"
"crypto/sha1"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"io/ioutil"
@@ -267,7 +267,7 @@ func (s *Server) panic(w http.ResponseWriter, r *http.Request) {
}
func hash(input string) string {
h := sha1.New()
h := sha256.New()
h.Write([]byte(input))
return hex.EncodeToString(h.Sum(nil))
}

View File

@@ -22,7 +22,7 @@ func NewInstrument() *Instrument {
// used for monitoring and alerting (RED method)
histogram := prometheus.NewHistogramVec(prometheus.HistogramOpts{
Subsystem: "http",
Name: "requests",
Name: "request_duration_seconds",
Help: "Seconds spent serving HTTP requests.",
Buckets: prometheus.DefBuckets,
}, []string{"method", "path", "status"})

View File

@@ -1,4 +1,4 @@
package version
var VERSION = "0.2.2"
var VERSION = "0.4.0"
var GITCOMMIT = "unknown"

33
skaffold.yaml Normal file
View File

@@ -0,0 +1,33 @@
apiVersion: skaffold/v1alpha2
kind: Config
## Default profile for use with `skaffold dev`
build:
artifacts:
- imageName: podinfo
docker:
dockerfilePath: ./Dockerfile.ci
deploy:
kubectl: { manifests: [ deploy/skaffold/dev/* ] }
profiles:
- name: test
## This profile runs unit tests and builds the image
build:
local: { skipPush: true }
artifacts:
- imageName: stefanprodan/podinfo
docker:
dockerfilePath: ./Dockerfile.ci
deploy: {} # not needed here as such
- name: production
## This profile pushes the image
build:
local: { skipPush: false }
artifacts:
- imageName: stefanprodan/podinfo
docker:
dockerfilePath: ./Dockerfile.ci
deploy: {} # no-op, flux will take care of this