华为云 CCE 容器集群灰度发布实战:从流量切分到自动化回滚的完整实践
最近把手上的一个定时数据同步任务从虚拟机上的 crontab 整体搬到了华为云 CCE 集群上,做完之后最大的感受是:容器化真正带来的收益不是"部署更方便",而是"回滚成本降到了接近零"。这篇记录一下我在 CCE 上做灰度发布的一些实践过程,主要面向刚开始用 CCE、还在用 Deployment 一把梭的开发者。
一、先说清楚灰度发布到底解决什么问题
我们线上有一个订单聚合服务,流量高峰在每天上午十点。之前的发布方式是 kubectl set image 直接覆盖,结果出现过两次事故:第一次是镜像 tag 打错,配置读取失败直接 502;第二次更隐蔽,新版本的一个序列化逻辑变更导致响应体变大,而上游网关的超时时间没有跟着调,结果大量请求堆积在网关侧。
灰度发布的核心思路是:不要一次性把全部流量切到新版本,而是先切一小部分,观察指标,没问题再继续扩大,出问题立刻把这一小部分切回去。要注意这里的关键不是"分批"本身,而是"每一步都能立刻回退"。
二、我的环境基线
集群版本是 CCE 1.29,使用的是 ARM 架构的鲲鹏节点(业务侧确实有信创需求,这一点华为云的支持做得挺好,镜像拉取和 nodeSelector 配合起来很顺)。Ingress 用的是自带的 ELB 7 层转发,Service 类型是 LoadBalancer。镜像仓库用的是 SWR 私有仓库,配合 CodeArts 的构建流水线推镜像。
这里插一句题外话,如果你也在信创环境上折腾,可以留意一下 amd64 和 arm64 的多架构镜像构建方式,避免以后换架构时推倒重来。
三、流量切分的几种做法对比
第一种是按 Pod 数量切分,也就是最常见的 canary Deployment:同一个 Deployment 下同时跑 9 个老版本 Pod 和 1 个新版本 Pod,流量按 Pod 数量自然分成 10% 和 90%。这个做法的优点是简单,不需要任何额外的组件;缺点是负载均衡并不完全按 Pod 数量来,实际比例会有偏差,而且新老版本之间共享同一个 Service,session 粘连的问题需要自己处理。
第二种是按请求头或者用户标识切分,需要在 Ingress 上加匹配规则,比如把带有特定 header 或者指定用户 ID 的请求转发到 canary Service。这个方式的精度更高,适合做定向验证,比如先让内部同事的账号走新版本。我的实践里,这套规则的维护成本主要在规则变更时的回滚动作上,改完之后要确认 ELB 的健康检查和后端组都已经刷新,不能只看控制台显示"已生效"。
第三种是金丝雀加自动分析,也就是每切一批流量就跑一轮自动化校验脚本,指标不达标自动停手。我个人比较推荐这条路,因为它把"人工盯着看"变成了"规则替你盯着看"。我这边的校验脚本做的事情比较朴素:定时跑一遍核心接口的冒烟用例,校验响应体结构和关键字段值,同时对比新老版本的错误率和 P99 延迟,超过阈值就把金丝雀副本数回滚到 0。
四、回滚这一环必须提前演练
这一点我踩过坑。最初我以为回滚就是把副本数改回去就好了,但实际演练的时候发现,回滚同样需要拉镜像,而拉镜像依赖 SWR,如果回滚的时候刚好赶上仓库的并发限流或者跨区域同步延迟,回滚本身会变成一个很慢的过程。
后来我做了两个改动:一是给每个发布版本打一个不可变的 tag,不用 latest,确保任何时刻都能明确知道线上跑的是哪个版本;二是每周做一次回滚演练,在测试环境把版本切到三天前,然后完整走一遍回滚流程并计时。现在从发现问题到流量完全切回稳定版本,我们的耗时控制在 4 分钟以内。
五、灰度期间最容易踩的几个细节
首先是健康检查的时机。Pod 的 readiness 探针如果只检查进程是否存活,滚动更新会出现流量在容器还没真正准备好之前就被摘掉,表现为发布期间偶发 502。我的做法是把探针改成检查业务侧的轻量接口,确保真正能处理请求才标记为就绪。
其次是资源限制。canary 副本如果和主版本用同一套 requests/limits,在只有 10% 流量的情况下,它的 CPU 利用率会明显偏低,看起来很健康,实际上一旦全量放开就会因为资源不足而崩溃。所以灰度期间要给 canary 副本留足余量,最好按压测得出的单实例容量反推所需的副本数。
再次是配置和代码的分离。灰度期间如果配置变更和代码变更同时进行,出问题的时候你很难判断到底是哪一个引起的。我的习惯是灰度窗口内只允许代码变更,配置变更单独走另一条流程、单独发布。
最后是日志和链路的打通。灰度期间新旧版本并行,如果两套版本的日志格式或者 traceId 规则不一致,排查会非常痛苦。我们统一了日志规范,并且要求 traceId 里带上版本标记,这样在链路追踪系统里可以直接按版本过滤。
六、一点体会
CCE 的门槛主要不在 Kubernetes 本身,而在你对流量入口和发布策略的理解。很多时候我们花在排查问题上的时间,其实都消耗在"我到底不知道流量去了哪里"。把灰度发布、指标校验、自动回滚这三件事串起来之后,发布的心理负担会小很多——因为最坏的情况已经被自动流程兜住了。
如果你也在做容器化改造,我的建议是不要一上来就追求全自动的发布链路。先把"可观测"和"可回滚"这两件事做扎实,哪怕回滚还要人工点两下,至少出事的时候你知道怎么退回去。等这两块稳了,再考虑把校验脚本接进流水线,实现真正的无人值守发布。
- 点赞
- 收藏
- 关注作者
评论(0)