flagger 解析

flagger

应用自动发布组件

官网地址

https://github.com/weaveworks/flagger

官方介绍

Flagger can be configured to automate the release process for Kubernetes workloads with a custom resource named canary.

支持的 custom resource(即下文中的 provider)

- istio

- Linkerd

- App Mesh

- Nginx

- contour

- CNI

- Kubernetes

组件架构图

flagger-arch
架构图解释

- primary service:已发布的在线服务(旧版本)

- canary service: 即将发布的新版本服务(新版本)

- Ingress:发布过程中发布粒度控制的 提供者

- Flagger:通过Flagger Spec 以 提供者提供的规范来调整 primary 与 canary 的 流量/副本运行 策略。调整过程中,根据 prometheus 采集的各项指标来决策是否回滚发布 或者 继续调整 流量/副本运行 比例。!!!此过程中,用户可自定义是否人工干预、审核、通知等动作。

示例 yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
namespace: test
spec:
# service mesh provider (optional)
# can be: kubernetes, istio, linkerd, appmesh, nginx, contour, gloo, supergloo
provider: istio
# deployment reference
targetRef:
apiVersion: apps/v1
kind: Deployment
name: podinfo
# the maximum time in seconds for the canary deployment
# to make progress before it is rollback (default 600s)
progressDeadlineSeconds: 60
# HPA reference (optional)
autoscalerRef:
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
name: podinfo
service:
# service name (defaults to targetRef.name)
name: podinfo
# ClusterIP port number
port: 9898
# container port name or number (optional)
targetPort: 9898
# port name can be http or grpc (default http)
portName: http
# add all the other container ports
# to the ClusterIP services (default false)
portDiscovery: true
# HTTP match conditions (optional)
match:
- uri:
prefix: /
# HTTP rewrite (optional)
rewrite:
uri: /
# request timeout (optional)
timeout: 5s
# promote the canary without analysing it (default false)
skipAnalysis: false
# define the canary analysis timing and KPIs
analysis:
# schedule interval (default 60s)
interval: 1m
# max number of failed metric checks before rollback
threshold: 10
# max traffic percentage routed to canary
# percentage (0-100)
maxWeight: 50
# canary increment step
# percentage (0-100)
stepWeight: 5
# validation (optional)
metrics:
- name: request-success-rate
# builtin Prometheus check
# minimum req success rate (non 5xx responses)
# percentage (0-100)
thresholdRange:
min: 99
interval: 1m
- name: request-duration
# builtin Prometheus check
# maximum req duration P99
# milliseconds
thresholdRange:
max: 500
interval: 30s
- name: "database connections"
# custom Prometheus check
templateRef:
name: db-connections
thresholdRange:
min: 2
max: 100
interval: 1m
# testing (optional)用户自定义干预
webhooks:
- name: "conformance test"
type: pre-rollout
url: http://flagger-helmtester.test/
timeout: 5m
metadata:
type: "helmv3"
cmd: "test run podinfo -n test"
- name: "load test"
type: rollout
url: http://flagger-loadtester.test/
metadata:
cmd: "hey -z 1m -q 10 -c 2 http://podinfo.test:9898/"
# alerting (optional)
alerts:
- name: "dev team Slack"
severity: error
providerRef:
name: dev-slack
namespace: flagger
- name: "qa team Discord"
severity: warn
providerRef:
name: qa-discord
- name: "on-call MS Teams"
severity: info
providerRef:
name: on-call-msteams

基本使用

- targetRef: 当前部署的新版本服务(可以是Deployment, 也可以是DaemonSet).

- progressDeadlineSeconds: canary, primary 部署超时时间.如果超过这个时间还没有部署好, 则不会进行 流量/组件副本 调整.

- autoscalerRef: K8s原生的HPA(自动伸缩).

- service: k8s service。当provider是Istio时, 和VirtualSercice(具有调整流量比例,路由策略等能力)相对应

- skipAnalysis: 是否跳过metrcis分析. 如果为true, 相当于一次性将primary替换成canary service.

分析

analysis:

- 包含一些调整primary, canary流量策略配置

- metrics: 指标来源. 例如: avg RT, 成功率, 自定义metrics(可以直接配置prometheus PQL)等

- webhook:可以用来人工审核接入, 压力测试等.

- alerts: 进度详情, 告警通知等

flagger 工作流程

flagger 流程

!核心:webhook——人工干预,实现暂停、回滚、继续、策略调整

部署策略

A/B testing

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
analysis:
# schedule interval (default 60s)
interval: 1m
# total number of iterations
iterations: 10
# max number of failed iterations before rollback
threshold: 2
# canary match condition
match:
- headers:
x-canary:
regex: ".*insider.*"
- headers:
cookie:
regex: "^(.*?;)?(canary=always)(;.*)?$"

以上面代码示例为例:
• 会在创建VirtualService过(istio)程中, 设置多个HTTPRoute.
• 默认流量, 访问primary service
• 通过http header或者cookie 正则匹配方式, 将流量路由到canary service.
• 整个流程会执行10次,每次间隔1分钟, 最多允许2次metrics验证失败. 如果超过2次, 则进行回滚.
• 正常结束后, 会执行”confirm-promotion” webhook, 确认是否将primary替换成cannay

1
2
• 如果是, 会将primary替换成cananry的spec(deployemnt spec, configmap)相关信息
• 如果否, 继续等待

Blue/Green

1
2
3
4
5
6
7
8
9
10
11
12
13
analysis:
# schedule interval (default 60s)
interval: 1m
# total number of iterations
iterations: 10
# max number of failed iterations before rollback
threshold: 2
webhooks:
- name: "load test"
type: rollout
url: http://flagger-loadtester.test/
metadata:
cmd: "hey -z 1m -q 10 -c 2 http://podinfo.test:9898/"

以上面代码示例为例:
• 整个流程会执行10次,每次间隔1分钟, 最多允许2次metrics验证失败.如果超过2次, 则进行回滚.
• 在这段时间会对canary service进行压力测试
• 正常结束后, 会执行”confirm-promotion” webhook, 确认是否将primary替换成cannay

1
2
• 如果是, 会将primary替换成cananry的spec(deployemnt spec, configmap)相关信息
• 如果否, 继续等待

如果配置了mirror=true(只有provider=istio时才支持该特性), 则会使用istio的mirror特性, 将流量分别copy 到primary和canary, 使用primary的reponse作为返回值. 这个时候要特别注意业务是否幂等.

Canary

1
2
3
4
5
6
7
8
9
10
11
12
13
14
analysis:
# schedule interval (default 60s)
interval: 1m
# max number of failed metric checks before rollback
threshold: 2
# max traffic percentage routed to canary
# percentage (0-100)
maxWeight: 50
# canary increment step
# percentage (0-100)
stepWeight: 2
# deploy straight to production without
# the metrics and webhook checks
skipAnalysis: false

以上面代码示例为例:
• 整个流程会执行25(maxWeight/maxWeight)次,每次间隔1分钟, 最多允许2次metrics验证失败.如果超过2次, 则进行回滚.
• 每次primary减少stepWeight%流量, canary增加stepWeight%流量, 直到canary到达maxWeight
• 执行”confirm-promotion” webhook, 确认是否将primary替换成cannay

1
2
• 如果是, 会将primary替换成cananry的spec(deployemnt spec, configmap)相关信息
• 如果否, 继续等待

其它

Webhooks

webhooks: 在整个发布过程中, 定义了相应的扩展点:
• confirm-rollout: 在canary接收流量之前执行. 可以用于人工审核发布, 自动化测试通过等场景.
如果该webhook没有返回成功(例如:请求返回状态码200), 则发布一直等待.
• pre-rollout: 在第一次切流到canary前执行的webhook. 如果执行失败次数超过阀值, 则进行回滚
• rollout: 在发布的每个周期(例如每个stepWeight)中的metrics分析之前执行.如果执行失败次数超过阀值, 则进行回滚
• confirm-promotion: 在primary变更到canary配置相关信息之前执行.
如果不成功, 会一直等待.在等待的过程中, Flagger会继续执行metrics验证直到最终回滚.
• post-rollout: 在rollback或者finish后执行. 如果执行失败只会记录Event日志。
• rollback: 当Canary处于Progressing或者Waiting状态时. 提供人工执行回滚的能力.
• event: 在每个生命周期,都会产生一些相关k8s event. 如果配置event webhook, 则在产生k8s event的同时,发送相关event事件信息.

Metrics

Metrics: 用于决策(A/B, Blue/Green, Canary)流量是否验证失败, 超过制定阀值(threshold)就会回滚发布
• 缺省自带的metrics

1
2
3
4
5
6
7
8
9
10
11
12
13
14
analysis:
metrics:
- name: request-success-rate
interval: 1m
# minimum req success rate (non 5xx responses)
# percentage (0-100)
thresholdRange:
min: 99
- name: request-duration
interval: 1m
# maximum req duration P99
# milliseconds
thresholdRange:
max: 500
  • request-success-rate(请求成功率). 上例说明成功率不能低于99%
  • request-duration(avg RT): RT均值不能超过500ms
    request-success-rate和request-duration是Flagger缺省自带的metrics.

不同的provider有不通实现. 例如:应用可以提供prometheus metrics

• 自定义metrics

  1. 创建MetricTemplate. 比如业务自定义的业务metrics, 如订单支付失败率
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
name: not-found-percentage
namespace: istio-system
spec:
provider:
type: prometheus
address: http://promethues.istio-system:9090
query: |
100 - sum(
rate(
istio_requests_total{
reporter="destination",
destination_workload_namespace="{{ namespace }}",
destination_workload="{{ target }}",
response_code!="404"
}[{{ interval }}]
)
)
/
sum(
rate(
istio_requests_total{
reporter="destination",
destination_workload_namespace="{{ namespace }}",
destination_workload="{{ target }}"
}[{{ interval }}]
)
) * 100
  1. 引用MetricTemplate

    1
    2
    3
    4
    5
    6
    7
    8
    9
    analysis:
    metrics:
    - name: "404s percentage"
    templateRef:
    name: not-found-percentage
    namespace: istio-system
    thresholdRange:
    max: 5
    interval: 1m

    上例表示canary的关于404错误/s的metrics不能超过5%

Alter

Alter: 用于发布过程中信息通知.
1.定义AlterProvider(可以是slack, 也可以是dingding)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: flagger.app/v1beta1
kind: AlertProvider
metadata:
name: on-call
namespace: flagger
spec:
type: slack
channel: on-call-alerts
username: flagger
# webhook address (ignored if secretRef is specified)
address: https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK
# secret containing the webhook address (optional)
secretRef:
name: on-call-url
---
apiVersion: v1
kind: Secret
metadata:
name: on-call-url
namespace: flagger
data:
address: <encoded-url>

2.使用Alter

1
2
3
4
5
6
7
analysis:
alerts:
- name: "on-call Slack"
severity: error
providerRef:
name: on-call
namespace: flagger

• serverity: 通知信息的等级, 类似日志级别. 包含info, warn, error
在整个部署过程中,不同阶段都会使用alter来发送通知信息, 例如发布成功, webhook执行失败等场景。

!使用 flagger 保证 0 宕机 所需 注意点

  • Deployment的重启策略必须为 RollingUpdate,且

  • Liveness/Readiness 健康检测需要添加

  • Graceful shutdown 必须设置

  • 使用 资源申请和上限 限制

限制:

单纯 kubernetes CNI 仅支持 蓝绿发布

额外发布支持:

NGINX 支持 金丝雀、A/B、蓝绿发布

ISTIO 所有发布类型支持


发布策略、动作支持 核心

webhook

支持以下

  • 确认发布——confirm rollout(确认发布将开始)
  • 预发布——pre-rollout(发布开始时确认动作)
  • 发布每一步——rollout(每次发布变更步骤执行)
  • 确认发布生效——confirm-promotion(确认发布将生效)
  • 预生效——post-rollout(每次生效时确认动作)
  • 回退——rollback(处于 发布中 /等待中 状态时可以执行回滚)
  • 事件——event(发布过程中,发布相关事件都可以被监听,来执行对应的策略)

参考连接

https://docs.flagger.app/usage/webhooks