├── .gitignore ├── LICENSE ├── README.md ├── docs └── diagrams │ └── gitops-flagger.png ├── namespaces ├── istio-system.yaml ├── prod.yaml └── test.yaml ├── releases └── podinfo.yaml └── workloads ├── prod ├── canary.yaml ├── deployment.yaml └── hpa.yaml └── test └── tester.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Stefan Prodan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gitops-progressive-delivery 2 | 3 | Progressive delivery GitOps pipeline with [Istio](https://istio.io), [Prometheus](https://prometheus.io/), 4 | [Weave Flux](https://github.com/weaveworks/flux) and [Flagger](https://github.com/stefanprodan/flagger). 5 | 6 | ![gitops-pipeline](https://raw.githubusercontent.com/stefanprodan/gitops-progressive-delivery/master/docs/diagrams/gitops-flagger.png) 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/diagrams/gitops-flagger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanprodan/gitops-progressive-delivery/50fadddb9307da0041b108c5b0435b1dda0688e6/docs/diagrams/gitops-flagger.png -------------------------------------------------------------------------------- /namespaces/istio-system.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | labels: 5 | name: istio-system 6 | name: istio-system 7 | -------------------------------------------------------------------------------- /namespaces/prod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: prod 5 | labels: 6 | istio-injection: enabled 7 | -------------------------------------------------------------------------------- /namespaces/test.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: test 5 | labels: 6 | istio-injection: enabled 7 | -------------------------------------------------------------------------------- /releases/podinfo.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: flux.weave.works/v1beta1 3 | kind: HelmRelease 4 | metadata: 5 | name: podinfo 6 | namespace: default 7 | annotations: 8 | flux.weave.works/ignore: "true" 9 | flux.weave.works/automated: "false" 10 | flux.weave.works/tag.chart-image: semver:~1.4 11 | spec: 12 | timeout: 0 13 | chart: 14 | repository: https://stefanprodan.github.io/k8s-podinfo 15 | name: podinfo 16 | version: 1.4.2 17 | values: 18 | image: 19 | repository: quay.io/stefanprodan/podinfo 20 | tag: 1.4.1 21 | replicaCount: 1 22 | -------------------------------------------------------------------------------- /workloads/prod/canary.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: flagger.app/v1alpha3 2 | kind: Canary 3 | metadata: 4 | name: podinfo 5 | namespace: prod 6 | spec: 7 | provider: istio 8 | # deployment reference 9 | targetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: podinfo 13 | # the maximum time in seconds for the canary deployment 14 | # to make progress before it is rollback (default 600s) 15 | progressDeadlineSeconds: 60 16 | # HPA reference (optional) 17 | autoscalerRef: 18 | apiVersion: autoscaling/v2beta1 19 | kind: HorizontalPodAutoscaler 20 | name: podinfo 21 | service: 22 | # container port 23 | port: 9898 24 | # Istio gateways (optional) 25 | gateways: 26 | - public-gateway.istio-system.svc.cluster.local 27 | # Istio virtual service host names (optional) 28 | hosts: 29 | - podinfo.istio.weavedx.com 30 | # for emergency cases when you want to ship changes 31 | # in production without analysing the canary 32 | skipAnalysis: false 33 | canaryAnalysis: 34 | # schedule interval (default 60s) 35 | interval: 10s 36 | # max number of failed metric checks before rollback 37 | threshold: 10 38 | # max traffic percentage routed to canary 39 | # percentage (0-100) 40 | maxWeight: 50 41 | # canary increment step 42 | # percentage (0-100) 43 | stepWeight: 5 44 | metrics: 45 | - name: request-success-rate 46 | # minimum req success rate (non 5xx responses) 47 | # percentage (0-100) 48 | threshold: 99 49 | interval: 1m 50 | - name: request-duration 51 | # maximum req duration P99 52 | # milliseconds 53 | threshold: 500 54 | interval: 30s 55 | # external checks (optional) 56 | webhooks: 57 | - name: acceptance-test 58 | type: pre-rollout 59 | url: http://flagger-loadtester.test/ 60 | timeout: 30s 61 | metadata: 62 | type: bash 63 | cmd: "curl -sd 'test' http://podinfo-canary.prod:9898/token | grep token" 64 | - name: load-test 65 | url: http://flagger-loadtester.test/ 66 | timeout: 5s 67 | metadata: 68 | cmd: "hey -z 1m -q 10 -c 5 http://podinfo.prod:9898/" 69 | -------------------------------------------------------------------------------- /workloads/prod/deployment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: podinfo 6 | namespace: prod 7 | labels: 8 | app: podinfo 9 | annotations: 10 | flux.weave.works/tag.podinfod: semver:~1.4 11 | flux.weave.works/automated: 'false' 12 | spec: 13 | strategy: 14 | rollingUpdate: 15 | maxUnavailable: 0 16 | type: RollingUpdate 17 | selector: 18 | matchLabels: 19 | app: podinfo 20 | template: 21 | metadata: 22 | labels: 23 | app: podinfo 24 | annotations: 25 | prometheus.io/scrape: "true" 26 | spec: 27 | containers: 28 | - name: podinfod 29 | image: quay.io/stefanprodan/podinfo:1.7.2 30 | imagePullPolicy: IfNotPresent 31 | ports: 32 | - containerPort: 9898 33 | name: http 34 | protocol: TCP 35 | command: 36 | - ./podinfo 37 | - --port=9898 38 | - --level=info 39 | - --random-delay=false 40 | - --random-error=false 41 | env: 42 | - name: PODINFO_UI_COLOR 43 | value: green 44 | livenessProbe: 45 | httpGet: 46 | path: /healthz 47 | port: 9898 48 | readinessProbe: 49 | httpGet: 50 | path: /readyz 51 | port: 9898 52 | resources: 53 | limits: 54 | cpu: 2000m 55 | memory: 512Mi 56 | requests: 57 | cpu: 100m 58 | memory: 64Mi 59 | -------------------------------------------------------------------------------- /workloads/prod/hpa.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: autoscaling/v2beta1 2 | kind: HorizontalPodAutoscaler 3 | metadata: 4 | name: podinfo 5 | namespace: prod 6 | spec: 7 | scaleTargetRef: 8 | apiVersion: apps/v1 9 | kind: Deployment 10 | name: podinfo 11 | minReplicas: 2 12 | maxReplicas: 4 13 | metrics: 14 | - type: Resource 15 | resource: 16 | name: cpu 17 | # scale up if usage is above 18 | # 99% of the requested CPU (100m) 19 | targetAverageUtilization: 99 20 | -------------------------------------------------------------------------------- /workloads/test/tester.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: tester 6 | namespace: test 7 | labels: 8 | app: tester 9 | annotations: 10 | flux.weave.works/tag.podinfod: semver:~1.3 11 | spec: 12 | replicas: 1 13 | strategy: 14 | rollingUpdate: 15 | maxUnavailable: 0 16 | type: RollingUpdate 17 | selector: 18 | matchLabels: 19 | app: tester 20 | template: 21 | metadata: 22 | annotations: 23 | prometheus.io/scrape: "true" 24 | labels: 25 | app: tester 26 | spec: 27 | containers: 28 | - name: podinfod 29 | image: quay.io/stefanprodan/podinfo:1.3.2 30 | imagePullPolicy: IfNotPresent 31 | ports: 32 | - containerPort: 9898 33 | name: http 34 | protocol: TCP 35 | command: 36 | - ./podinfo 37 | - --port=9898 38 | env: 39 | - name: PODINFO_UI_COLOR 40 | value: green 41 | livenessProbe: 42 | httpGet: 43 | path: /healthz 44 | port: 9898 45 | readinessProbe: 46 | httpGet: 47 | path: /readyz 48 | port: 9898 49 | resources: 50 | limits: 51 | cpu: 2000m 52 | memory: 512Mi 53 | requests: 54 | cpu: 10m 55 | memory: 64Mi 56 | --------------------------------------------------------------------------------