原标题:APISIX Ingress + Flagger实现顺滑的金丝雀发布
作者:谭恒亮,Github ID: Gallardot。开源项目爱好者,CNCF Chaos Mesh 项目 Maintainer,CNCF KubeVela、Apache APISIX、CNCF Flagger、CNCF Argo Rollouts 等项目 Contributor。目前在小鹏汽车任职基础架构研发专家。
在日常的项目开发过程中时,我们时常会面临服务变更的挑战,为了不影响用户体验,我们往往尽可能需要规避服务不可用的风险。因此,持续交付便应运而生,其被接受为一种企业软件实践,并且是完善的持续集成原则的自然演变。
然而,持续部署仍然非常罕见,这可能是由于管理的复杂性以及担心部署失败会影响系统可用性。在整个持续交付体系中,金丝雀发布或许是最为经典的一个场景。基于此,我们能够很快发现“不健康”和“有问题”的服务,并且可以毫不费力地回滚到上一个版本。
金丝雀发布也称“灰度发布”。通常来讲,在原有版本可用的情况下,同时发布部署一个新版本应用作为“金丝雀”,其目的是为了测试新版本的性能和表现,在保障整体系统稳定的前提下,尽早发现和及时调整。
金丝雀发布并非黑即白的发布方式,它能够缓慢地将特定百分比的流量引导至一小部分用户。若验证没有问题,再推广到全部用户,并逐步淘汰旧版本,以降低生产环境引入新功能带来的风险。
本文将介绍如何通过 Apache APISIX Ingress 和 Flagger 实现顺滑的金丝雀发布,从而提高发布效率,降低发布风险。
项目介绍
Apache APISIX Ingress
Apache APISIX Ingress 使用 Apache APISIX 作为数据面代理的 Kubernetes Ingress controller 实现,提供了负载均衡、动态上游、金丝雀发布、精细化路由、限流限速、服务降级、服务熔断、身份认证、可观测性等数百项功能。目前已被包括 Zoom、腾讯云、驾考宝典、地平线、欧洲哥白尼参考系统等国内外公司和组织采用。
Flagger
Flagger 是一个 CNCF 云原生计算基金会项目,是 GitOps 工具 Flux 系列的一部分。最近 CNCF 云原生计算基金会也宣布了 Flux 正式毕业,很好地表明了云原生技术当前的成功与光明前景。作为一种渐进式交付工具,Flagger 可自动执行在 Kubernetes 上运行的应用程序的发布过程。它通过在衡量分析指标和运行一致性测试的同时逐渐将流量转移到新版本来降低在生产中引入新软件版本的风险。
经过 Apache APISIX 和 Flux 两个社区的合作与努力,Flagger 在近期也发布了 v1.27.0 版本,支持使用 Apache APISIX Ingress 和 Flagger 进行自动化的金丝雀发布。
下文将通过实践,一步步为大家展示下这个顺滑的金丝雀发布过程。
金丝雀发布准备环节
环境与组件准备
首先需要一个 v1.19 或更新版本的 Kubernetes 集群,你可以通过 kind进行安装。
然后使用 Helm V3 来安装 Apache APISIX 和 Apache APISIX Ingress Controller,具体操作如下所示:
helm repo add apisix https: //charts.apiseven.com kubectl create ns apisixhelm upgrade -i apisix apisix/apisix –version= 0.11.3 — namespaceapisix — setapisix.podAnnotations. “prometheus.io/scrape”= true — setapisix.podAnnotations. “prometheus.io/port”= 9091 — setapisix.podAnnotations. “prometheus.io/path”= /apisix/prometheus/metrics — setpluginAttrs.prometheus.export_addr.ip= 0.0.0.0 — setpluginAttrs.prometheus.export_addr.port= 9091 — setpluginAttrs.prometheus.export_uri= /apisix/prometheus/metrics — setpluginAttrs.prometheus.metric_prefix=apisix_ — setingress-controller.enabled= true — setingress-controller.config.apisix.serviceNamespace=apisix
完成后,在 apisix namespace 中安装 Flagger 和 Prometheus 附加组件。
helm repo add flagger https: //flagger.apphelm upgrade -i flagger flagger/flagger — namespaceapisix — setprometheus.install= true — setmeshProvider=apisix
注意,如需使用自建 prometheus 或者 prometheus operator,可以自行搜索相关文章进行修改。
初始化应用
Flagger 可以作用于 Kubernetes 的 deployment 以及其他的 workload,也可以和 HPA 结合在一起工作。它将会创建一系列的对象(比如 Kubernetes deployments、ClusterIP services 和 ApisixRoute)。这些对象可以将应用暴露到集群外提供服务,并用于金丝雀发布过程的分析和发布。
首先使用 kubectl create ns test 命令来新建一个 namespace,这里我们将其命名为 test。然后通过 kubectl apply -k https://github.com/fluxcd/flagger//kustomize/podinfo?ref=main 命令,新建一个 deployment 和 HPA,这里使用 Flagger 官方示例程序。
接下来可通过 helm upgrade -i flagger-loadtester flagger/loadtester
–namespace=test 指令来部署 Flagger 的负载测试服务,用于在金丝雀发布期间产生流量时,方便对其进行分析。
此时,创建 Apache APISIX 的ApisixRoute,Flagger 将会引用该资源,并且生成金丝雀版本的 Apache APISIX Ingress 的ApisixRoute,具体可参考下方示例(示例中的app.example.com可以替换成你的实际域名)。
apiVersion: apisix.apache.org/v2kind: ApisixRoutemetadata: name: podinfonamespace: testspec: http: –backends:–serviceName: podinfoservicePort: 80match: hosts: –app.example.commethods: –GETpaths: –/*name: methodplugins: –name: prometheusenable: trueconfig: disable: falseprefer_name: true将上方代码保存为 podinfo-apisixroute.yaml 文件并且提交到集群中。
kubectlapply -f ./podinfo-apisixroute.yaml接下来可以创建 Flagger 的自定义资源 Canary,如下所示(示例中的 app.example.com可以替换成你的实际域名)。
apiVersion: flagger.app/v1beta1kind: Canarymetadata: name: podinfonamespace: testspec: provider: apisixtargetRef: apiVersion: apps/v1kind: Deploymentname: podinfo# 引用 apisix route routeRef: apiVersion: apisix.apache.org/v2kind: ApisixRoutename: podinfoprogressDeadlineSeconds: 60service: port: 80targetPort: 9898analysis: # 调度间隔 (默认 60s)interval: 10s# 最大的metric检测失败次数,超过将会自动回滚threshold: 10# 流量路由到canary应用的最大百分比# (0-100)maxWeight: 50# 金丝雀分析渐进的步长# (0-100)stepWeight: 10# 通过Prometheus检查APISIX上的流量状况metrics: –name: request-success-rate# 最小的请求成功率 (非 5xx 响应)# (0-100)thresholdRange: min: 99interval: 1m–name: request-duration# P99 最大的请求延迟# 单位是毫秒thresholdRange: max: 500interval: 30swebhooks: # 自动产生流量以便进行金丝雀分析,根据实际业务场景修改–name: load-testurl: http://flagger-loadtester.test/timeout: 5stype: rolloutmetadata: cmd: |-hey-z 1m -q 10 -c 2 -h2 -host app.example.com http://apisix-gateway.apisix/api/info将上述代码保存为 podinfo-canary.yaml 文件,并提交到集群中。
kubectlapply -f ./podinfo-canary.yaml稍等一下 Flagger 就会自动生成相关的资源。
# 主动提交的deployment.apps/podinfo horizontalpodautoscaler.autoscaling/podinfo apisixroute/podinfo canary.flagger.app/podinfo# 自动生成的deployment.apps/podinfo-primary horizontalpodautoscaler.autoscaling/podinfo-primary service/podinfo service/podinfo-canary service/podinfo-primary apisixroute/podinfo-podinfo-canary
此时你通过域名 app.example.com 访问应用(示例中的app.example.com可以替换成你的实际域名),你将会看到当前版本的应用细节。
具体功能实践
自动金丝雀发布
Flagger 实现了一个控制循环,在持续测量 HTTP 请求成功率、请求平均持续时间和 Pod 健康状况等关键性能指标的同时,逐渐将流量转移至金丝雀节点。根据对相关指标的分析,发布或中止金丝雀部署,并将分析结果发布到相关平台例如 Slack、MS Teams 或者 Prometheus Alert Manager 等。
具体可通过更新容器镜像版本,来触发金丝雀发布。
kubectl -n testsetimage deployment/podinfo podinfod=stefanprodan/podinfo:6.0.1当 Flagger 检测到 deployment 有新版变更时,就会开始试运行金丝雀分析发布。
kubectl -n test describecanary/podinfo Status: Canary Weight: 0Conditions:Message: Canary analysis completed successfully, promotion finished.Reason: SucceededStatus: TrueType: Promoted FailedChecks: 1Iterations: 0Phase: SucceededEvents: TypeReason Age FromMessage —- —— —- —- ——-WarningSynced 2m59s flagger podinfo-primary.test notready: waiting forrollout tofinish: observed deployment generation lessthandesired generation WarningSynced 2m50s flagger podinfo-primary.test notready: waiting forrollout tofinish: 0of1(readyThreshold 100%) updatedreplicas areavailable NormalSynced 2m40s (x3 over2m59s) flagger allthe metrics providers areavailable! NormalSynced 2m39s flagger Initialization done! podinfo.test NormalSynced 2m20s flagger Newrevision detected! Scaling up podinfo.test WarningSynced 2m (x2 over2m10s) flagger canary deployment podinfo.test notready: waiting forrollout tofinish: 0of1(readyThreshold 100%) updatedreplicas areavailable NormalSynced 110s flagger Startingcanary analysis forpodinfo.test NormalSynced 109s flagger Advance podinfo.test canary weight 10WarningSynced 100s flagger Halt advancement novaluesfoundforapisix metric request- success-rate probably podinfo.test isnotreceiving traffic: running queryfailed: novaluesfoundNormalSynced 90s flagger Advance podinfo.test canary weight 20NormalSynced 80s flagger Advance podinfo.test canary weight 30NormalSynced 69s flagger Advance podinfo.test canary weight 40NormalSynced 59s flagger Advance podinfo.test canary weight 50WarningSynced 30s (x2 over40s) flagger podinfo-primary.test notready: waiting forrollout tofinish: 1oldreplicas arepending termination NormalSynced 9s (x3 over50s) flagger (combined fromsimilar events): Promotion completed! Scaling down podinfo.test在新版本金丝雀发布的过程中,你可以通过域名 app.example.com 访问应用(示例中的app.example.com可以替换成你的实际域名),这里将会出现不同版本的响应切换。
通过查看由 Flagger 自动创建出来的 Apache APISIX 的ApisixRoute 资源 podinfo-podinfo-canary,会发现 service podinfo-primary 和 service podinfo-canary 的权重跟随着发布过程一起变化。
spec: http: –backends:–serviceName: podinfo-primaryservicePort: 80# Flagger自动调整weight: 80–serviceName: podinfo-canaryservicePort: 80# Flagger自动调整weight: 20当最终发布完成后,将会看到稳定的最新版本。
注意:如若在金丝雀发布期间再次变更了 deployment,Flagger 将会重新进行金丝雀分析。你可以通过以下命令来观察到所有的金丝雀发布细节。
watchkubectlgetcanaries–all-namespacesNAMESPACENAMESTATUSWEIGHTLASTTRANSITIONTIMEtestpodinfo-2Progressing10 2022 -11-23T05:00:54ZtestpodinfoSucceeded0 2022 -11-23T06:00:54Z自动回滚
在金丝雀发布分析期间,你可以通过生成 HTTP 500 错误请求,测试 Flagger 暂停金丝雀发布并回滚到旧版本。
首先需要触发另一个金丝雀发布。
kubectl -n testsetimage deployment/podinfo podinfod=stefanprodan/podinfo:6.0.2然后进入到 load tester 容器中。
kubectl -n testexec-it deploy/flagger-loadtester bash接着去生成 HTTP 500 错误,并模拟服务延迟。
hey-z 1m-c 5-q 5-host app.example.com http://apisix-gateway.apisix/status/500watch -n 1curl -H “host: app.example.com” http://apisix-gateway.apisix/delay/1
当失败指标的检测次数达到金丝雀分析的阈值时,流量将被自动路由到主节点。金丝雀节点被缩小到零,该金丝雀发布过程被标记为失败。
kubectl-n apisix logs deploy/flagger -f | jq .msg “New revision detected! Scaling up podinfo.test”“canary deployment podinfo.test not ready: waiting for rollout to finish: 0 of 1 (readyThreshold 100%) updated replicas are available”“Starting canary analysis for podinfo.test”“Advance podinfo.test canary weight 10”“Halt podinfo.test advancement success rate 0.00% < 99%”“Halt podinfo.test advancement success rate 26.76% < 99%”“Halt podinfo.test advancement success rate 34.19% < 99%”“Halt podinfo.test advancement success rate 37.32% < 99%”“Halt podinfo.test advancement success rate 39.04% < 99%”“Halt podinfo.test advancement success rate 40.13% < 99%”“Halt podinfo.test advancement success rate 48.28% < 99%”“Halt podinfo.test advancement success rate 50.35% < 99%”“Halt podinfo.test advancement success rate 56.92% < 99%”“Halt podinfo.test advancement success rate 67.70% < 99%”“Rolling back podinfo.test failed checks threshold reached 10”“Canary failed! Scaling down podinfo.test”自定义指标金丝雀分析
金丝雀分析可以通过查询 Prometheus 的指标进行扩展,具体可根据实际业务场景进行调整。主要操作是需要创建一个指标模板,并提交到集群。
apiVersion: flagger.app/v1beta1kind: MetricTemplatemetadata: name: not-found-percentagenamespace: testspec: provider: type: prometheusaddress: http://flagger-prometheus.apisix:9090query: |sum(rate(apisix_http_status{route= ~”{{ namespace }}_{{ route }}-{{ target }}-canary_.+”,code!~”4..”}[{{interval }}]))/sum(rate(apisix_http_status{route= ~”{{ namespace }}_{{ route }}-{{ target }}-canary_.+”}[{{interval }}]))* 100修改金丝雀发布中的analysis,添加上面创建的指标模版。
analysis: metrics: –name: “404s percentage”templateRef: name: not-found-percentagethresholdRange: max: 5interval: 1m上述配置内容主要是通过检查 HTTP 404 请求的 QPS 是否高于总流量的 5% 来验证金丝雀。如果 HTTP 404 请求超过 5% 的阈值,那么金丝雀发布就失败了。
总结
当然,以上过程还可以通过更多的自定义指标检查、Webhook、手动审批和 Slack 或 MS Teams 通知等进行扩展。
通过 Apache APISIX 和 Flagger 的整合,实现了非常顺滑的金丝雀发布。在业务实践的过程中,提高了发布效率,降低了发布风险。后续两个社区也会通过更紧密的合作,去实现 Blue/Green Mirroring 和 A/B Testing 等更多的发布能力特性。
微软工程师展望Rust 2023:重写编译器、解决管理问题 英特尔发布新的 “Xe” Linux 内核图形驱动程序 黑客在线出售4亿Twitter用户数据,喊话马斯克破财消灾
这里有最新开源资讯、软件更新、技术干货等内容
点这里 ↓↓↓ 记得 关注✔ 标星⭐ 哦~
责任编辑: