Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AnalysisTemplate & update logic for canary rollout strategy #46

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ jobs:
kubectl apply -f https://raw.githubusercontent.com/opsgy/loki-rule-operator/main/chart/crds/logging.opsgy.com_lokirules.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/manifests/charts/base/crds/crd-all.gen.yaml
kubectl apply -f https://raw.githubusercontent.com/argoproj/argo-rollouts/master/manifests/crds/rollout-crd.yaml
kubectl apply -f https://raw.githubusercontent.com/argoproj/argo-rollouts/master/manifests/crds/analysis-template-crd.yaml
- name: Install charts
run: ct install --all
6 changes: 5 additions & 1 deletion charts/generic-service/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,11 @@ app:
| `rollout.autoPromotion` | `true` | Automatically promote rollouts (if `rollout.strategy` is `BlueGreen` and `rollout.flagger` if `false`) |
| `rollout.flagger` | `false` | Use Flagger to control rollouts (`rollout.controller` must be `Deployment` or `StatefulSet`) |
| `rollout.analysis` | req. for Canary or Flagger | Flagger or Argo Rollouts analysis for automatic `Canary` or `BlueGreen` promotion |
| `rollout.revisionHistoryLimit` | `null` | Number of old ReplicaSets to retain (`rollout.controller` must be `Deployment` or `ArgoRollout`) |
| `rollout.revisionHistoryLimit` | `600` | Number of old ReplicaSets to retain (`rollout.controller` must be `Deployment` or `ArgoRollout`) |
| `rollout.progressDeadlineSeconds` | `null` | The maximum time in seconds for a deployment to make progress before it is considered to be failed |
| `rollout.minReadySeconds` | `0` | Minimum number of seconds for which a new pod should be ready for it to be considered available |
| `rollout.progressDeadlineAbort` | `false` | Whether to abort the update when `rollout.progressDeadlineSeconds` is exceeded (`rollout.controller` must be `ArgoRollout` and `rollout.strategy` `Canary`) |
| `rollout.notifications` | `{}` | Option to subscribe to argo rollout events and send slack notifications |
| `replicas` | `1` | The number of instances of the service to run (set at least `2` for Pod Disruption Budget) |
| `autoscaling.enabled` | `false` | Enables automatic starting of additional instances |
| `autoscaling.maxReplicas` | `3` | The maximum number of instances to run (must be larger than `replicas`) |
Expand Down
20 changes: 20 additions & 0 deletions charts/generic-service/ci/argo-bluegreen-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Argo Rollout controller BlueGreen test

image:
repository: jwilder/whoami
tag: latest

ingress:
enabled: true
port: 8000

rollout:
controller: ArgoRollout
strategy: BlueGreen
autoPromotion: true
analysis:
templates:
- templateName: success-rate
args:
- name: service-name
value: canary-demo
48 changes: 48 additions & 0 deletions charts/generic-service/ci/argo-canary-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Argo Rollout controller Canary test

image:
repository: jwilder/whoami
tag: latest

ingress:
enabled: true
port: 8000

replicas: 2

rollout:
controller: ArgoRollout
strategy: Canary
analysis:
templates:
- templateName: success-rate
args:
- name: service-name
value: canary-demo
steps:
- setWeight: 20
- analysis:
templates:
- templateName: success-rate
args:
- name: service-name
value: canary-demo
- pause:
duration: 1h
- setWeight: 40
analysisTemplates:
- name: success-rate
args:
- name: service-name
metrics:
- name: success-rate
interval: 5m
count: 10
successCondition: "result[0] >= 0.95"
query: |
sum(irate(
istio_requests_total{reporter="source",destination_service=~"{{args.service-name}}",response_code!~"5.*"}[5m]
)) /
sum(irate(
istio_requests_total{reporter="source",destination_service=~"{{args.service-name}}"}[5m]
))
55 changes: 55 additions & 0 deletions charts/generic-service/templates/analysis-template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{{- if eq .Values.rollout.controller "ArgoRollout" }}
{{- range .Values.rollout.analysisTemplates }}
---
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: {{ include "generic-service.fullname" $ }}-{{ .name }}
spec:
{{- if .args }}
args:
{{- toYaml .args | nindent 4 }}
j-jasmin marked this conversation as resolved.
Show resolved Hide resolved
{{- end }}
{{- if .dryRun }}
dryRun:
{{- toYaml .dryRun | nindent 4 }}
j-jasmin marked this conversation as resolved.
Show resolved Hide resolved
{{- end }}
{{- if .measurementRetention }}
measurementRetention:
{{- toYaml .measurementRetention | nindent 4 }}
j-jasmin marked this conversation as resolved.
Show resolved Hide resolved
{{- end }}
metrics:
{{- range .metrics }}
- name: {{ .name }}
{{- if .consecutiveErrorLimit }}
consecutiveErrorLimit: {{ .consecutiveErrorLimit }}
{{- end }}
{{- if .count }}
count: {{ .count }}
{{- end }}
{{- if .failureCondition }}
failureCondition: {{ .failureCondition }}
{{- end }}
{{- if .successCondition }}
successCondition: {{ .successCondition }}
{{- end }}
{{- if .failureLimit }}
failureLimit: {{ .failureLimit }}
{{- end }}
{{- if .inconclusiveLimit }}
inconclusiveLimit: {{ .inconclusiveLimit }}
{{- end }}
{{- if .initialDelay }}
initialDelay: {{ .initialDelay }}
{{- end }}
{{- if .interval }}
interval: {{ .interval }}
{{- end }}
provider:
prometheus:
address: {{ .prometheusAddress | default "http://prometheus-prometheus.monitoring:9090" }}
query: |
{{ .query | nindent 12 }}
j-jasmin marked this conversation as resolved.
Show resolved Hide resolved
{{- end }}
{{- end }}
{{- end }}
49 changes: 26 additions & 23 deletions charts/generic-service/templates/controller.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ spec:
selector:
matchLabels: {{- include "generic-service.selector-labels" . | nindent 6 }}

progressDeadlineSeconds: {{ .Values.rollout.progressDeadlineSeconds| int }}
j-jasmin marked this conversation as resolved.
Show resolved Hide resolved
minReadySeconds: {{ .Values.rollout.minReadySeconds | int }}

{{- if and .Values.rollout.progressDeadlineAbort (eq .Values.rollout.controller "ArgoRollout") }}
progressDeadlineAbort: {{ .Values.rollout.progressDeadlineAbort }}
{{- end }}

strategy:
{{- if eq .Values.rollout.strategy "RollingUpdate" }}
{{- if eq .Values.rollout.controller "ArgoRollout" }}
Expand All @@ -51,14 +58,15 @@ spec:
{{- end }}
type: OnDelete
{{- else if eq .Values.rollout.strategy "Canary" }}
{{- if not .Values.ingress.enabled }}
{{ fail "ingress.enabled must be true if rollout.strategy is Canary" }}
{{- end }}
{{- if not .Values.ingress.domains }}
{{ fail "ingress.domains must not be empty if rollout.strategy is Canary" }}
{{- end }}
{{- if eq .Values.rollout.controller "ArgoRollout" }}
canary:
{{- if .Values.rollout.analysis }}
analysis: {{- .Values.rollout.analysis | toYaml | nindent 8 }}
{{- end }}
{{- if .Values.rollout.useTrafficRouting -}}
{{- if ne .Values.rollout.strategy "Canary" }}
{{ fail "Traffic routing is only available if rollout.strategy is Canary" }}
{{- end }}
stableService: {{ include "generic-service.fullname" . }}
stableMetadata:
labels:
Expand All @@ -67,25 +75,23 @@ spec:
canaryMetadata:
labels:
role: preview
analysis: {{- .Values.rollout.analysis | required "rollout.analysis is required if rollout.strategy is Canary" | toYaml | nindent 8 }}
trafficRouting:
{{- if .Values.ingress.istio.enabled }}
istio:
virtualService:
name: {{ include "generic-service.fullname" . }}
{{- else if contains "nginx" .Values.ingress.class }}
nginx:
stableIngress: {{ include "generic-service.fullname" . }}
istio:
virtualService:
name: {{ include "generic-service.fullname" . }}
{{- else if eq .Values.ingress.class "nginx" }}
nginx:
stableIngress: {{ include "generic-service.fullname" . }}
{{- else }}
{{ fail "Ingress must use Istio or nginx if rollout.strategy is Canary" }}
{{- end }}
{{- else if not .Values.rollout.flagger }}
{{ fail "rollout.flagger must be true or rollout.controller must be ArgoRollout if rollout.strategy is Canary" }}
{{- end }}
{{- with .Values.rollout.steps }}
steps: {{- . | toYaml | nindent 8 }}
{{- end }}
{{- end }}
{{- else if eq .Values.rollout.strategy "BlueGreen" }}
{{- if not .Values.ingress.enabled }}
{{ fail "ingress.enabled must be true if rollout.strategy is BlueGreen" }}
{{- end }}
{{- if eq .Values.rollout.controller "ArgoRollout" }}
blueGreen:
activeService: {{ include "generic-service.fullname" . }}
Expand All @@ -97,13 +103,11 @@ spec:
labels:
role: preview
autoPromotionEnabled: {{ .Values.rollout.autoPromotion }}
{{- if .Values.rollout.analysis }}
{{- if and (.Values.rollout.analysis) (.Values.rollout.autoPromotion) }}
prePromotionAnalysis: {{- .Values.rollout.analysis | toYaml | nindent 8 }}
{{- end }}
{{- else if not .Values.rollout.flagger }}
{{ fail "rollout.flagger must be true or rollout.controller must be ArgoRollout if rollout.strategy is BlueGreen" }}
{{- end }}
{{ else }}
{{- else }}
{{ fail "Unknown rollout.strategy" }}
{{- end }}

Expand Down Expand Up @@ -463,4 +467,3 @@ spec:
{{- end }}
{{- end }}
{{- end }}

2 changes: 1 addition & 1 deletion charts/generic-service/templates/service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ spec:
{{- end }}
{{- end }}

{{- if eq .Values.rollout.controller "ArgoRollout" }}
{{- if and (eq .Values.rollout.controller "ArgoRollout") (or (eq .Values.rollout.strategy "BlueGreen") (eq .Values.rollout.useTrafficRouting true)) }}
---
apiVersion: v1
kind: Service
Expand Down
29 changes: 28 additions & 1 deletion charts/generic-service/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -301,11 +301,38 @@
"description": "Use Flagger to control rollouts (rollout.controller must be Deployment or StatefulSet)"
},
"analysis": {
"description": "Flagger or Argo Rollouts analysis for automatic Canary or BlueGreen promotion"
"type": "object",
"description": "Flagger or Argo Rollouts analysis for automatic Canary promotion"
},
"steps": {
"type": "array",
"description": "Argo Rollouts list of steps to perform during a canary rollout"
},
"analysisTemplates": {
"type": "array",
"description": "List of analysis templates to create (only applicable if rollout.controller is ArgoRollout)"
},
"useTrafficRouting": {
"type": "boolean",
"default": false,
"description": "Whether to use Argo Rollouts traffig routing feature"
},
"revisionHistoryLimit": {
"type": ["integer", "null"],
"description": "Number of old ReplicaSets to retain (rollout.controller must be Deployment or ArgoRollout)"
},
"progressDeadlineSeconds": {
"type": ["integer"],
"description": "The maximum time in seconds for a deployment to make progress before it is considered to be failed"
},
"minReadySeconds": {
"type": ["integer"],
"description": "Minimum number of seconds for which a new pod should be ready for it to be considered available"
},
"progressDeadlineAbort": {
"type": ["boolean"],
j-jasmin marked this conversation as resolved.
Show resolved Hide resolved
"default": false,
"description": "Whether to abort the update when progressDeadlineSeconds is exceeded (rollout.controller must be ArgoRollout and rollout.strategy Canary)"
}
},
"additionalProperties": false
Expand Down
8 changes: 7 additions & 1 deletion charts/generic-service/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,16 @@ resources:
rollout:
controller: Deployment
strategy: RollingUpdate
useTrafficRouting: false
autoPromotion: true
flagger: false
analysis: null
analysis: {}
steps: []
analysisTemplates: []
revisionHistoryLimit: null
progressDeadlineSeconds: 600
minReadySeconds: 0
progressDeadlineAbort: false

replicas: 1

Expand Down