简介
Flagger是一个能使运行在k8s体系上的应用发布流程全自动(无人参与)的工具, 它能减少发布的人为关注时间, 并且在发布过程中能自动识别一些风险(例如:RT,成功率,自定义metrics)并回滚.
主要特性
整体架构
简单介绍下上图含义:
• primary service: 服务稳定版本. 可以理解为已发布在线的服务
• canary service: 即将发布的新版本服务.
• Ingress: 服务网关.
• Flagger: 会通过flagger spec(下面会介绍), 以ingress/service mesh的规范来调整primary和canary的流量策略.以此来达到A/B testing, blue/green, canary(金丝雀)发布效果. 在调整流量过程中, 根据prometheus采集的各项指标(RT,成功率等)来决策是否回滚发布或者继续调整流量比例。在此过程中,用户可以自定义是否人工干预,审核,收到通知等.
实现原理
注: 以下原理介绍, 主要基于以下的官方的实例说明:
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: 进度详情, 告警通知等
整体流程
说明:
• 上图Start到End的整个流程是在一个定时器中执行
• 上图中cancary和Canary不是同一个含义. Canary一般指Canary(Kind)对象或者指Canary 部署策略, canary指的是targetRef的对象(deployment, service)。
• VirtualSerivice(privider是Istio): 是A/B testing, Blue/Green, Canry Release实现的关键. 具体可以参考Istio关于VirtualService相关介绍
• 关于A/B testing, Blue/Green, Canary下文会详细介绍
部署策略
A/B testing
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
• 如果是, 会将primary替换成cananry的spec(deployemnt spec, configmap)相关信息
• 如果否, 继续等待
Blue/Green
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
• 如果是, 会将primary替换成cananry的spec(deployemnt spec, configmap)相关信息
• 如果否, 继续等待
如果配置了mirror=true(只有provider=istio时才支持该特性), 则会使用istio的mirror特性, 将流量分别copy 到primary和canary, 使用primary的reponse作为返回值. 这个时候要特别注意业务是否幂等.
Canary
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
• 如果是, 会将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
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
- 创建MetricTemplate. 比如业务自定义的业务metrics, 如订单支付失败率
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
-
引用MetricTemplate
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)
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
analysis:
alerts:
- name: "on-call Slack"
severity: error
providerRef:
name: on-call
namespace: flagger
• serverity: 通知信息的等级, 类似日志级别. 包含info, warn, error
在整个部署过程中,不同阶段都会使用alter来发送通知信息, 例如发布成功, webhook执行失败等场景。
总结
• Flagger对应用自动化发布流程进行了很好的抽象, 提供了丰富的扩展机制(webhook, alter, metrics等).
这些特性比较吸引人,那是否能能直接就能在集团内使用呢?
答案是不行。Flagger要求应用构建在k8s基础上, 例如服务发现机制, 另外要求部署Ingress/service mesh(这两者都具备调整流量策略的能力). 以HSF为例,它的服务发现机制是根据configserver, 服务是面向接口, 而不是应用。
如果不经过一定改造,估计还是无法使用.
• 另外Flagger也有一些改进的地方(我个人人为):
canary实例在切流过程中的扩缩容是根据HPA(如果配置了)来进行的, HPA扩缩容不及时就会对业务有影响.
改进方案: 可以根据stepWeight的变化动态调整canary的实例数, 这个只针对Canary release.
对于Blue/Green, A/B tesing可以通过webhook提前准备容量.
• Flagger正在规划primary和canary流量比较特性,这个似乎和集团Doom干的是同一件事情。未来可以期待一下.