深色模式
灰度发布引发的故障
摘要:灰度故障的处置原则是"先回滚、后定位"。本文给出回滚操作、新旧版本对比方法,以及灰度期间最容易踩的三类不兼容:配置、数据结构、接口协议。
适用环境
bash
kubectl version --short 2>/dev/null || kubectl version
kubectl get deploy -n <ns>1
2
2
排障步骤
第 1 步:确认当前处于灰度状态
bash
kubectl get pod -n <ns> -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'
kubectl get rs -n <ns> --sort-by=.metadata.creationTimestamp | tail -51
2
2
同时存在新旧两个 ReplicaSet 即说明处在灰度/滚动中。
第 2 步:优先止血 —— 回滚
bash
kubectl rollout history deployment/<name> -n <ns>
kubectl rollout undo deployment/<name> -n <ns>
kubectl rollout undo deployment/<name> -n <ns> --to-revision=<n>1
2
3
2
3
回滚前先确认旧版本与当前数据兼容
如果新版本已写入新格式数据,旧版本可能无法读取,回滚会引发二次故障。这类变更需先做数据兼容。
第 3 步:对比新旧版本指标
bash
kubectl logs -l app=<name>,version=new -n <ns> --tail=100 | grep -ci error
kubectl logs -l app=<name>,version=old -n <ns> --tail=100 | grep -ci error
kubectl top pod -n <ns> -l app=<name>1
2
3
2
3
对比维度应为:错误率、P95/P99 延迟、CPU/内存、GC 次数。只看总量会被稀释。
第 4 步:核对灰度与全量的配置差异
bash
kubectl get deploy <name> -n <ns> -o jsonpath='{.spec.template.spec.containers[*].env}' | tr ',' '\n'
kubectl diff -f deploy.yaml 2>/dev/null1
2
2
灰度实例使用了未全量推送的配置
配置中心按实例灰度时,新旧版本读到不同配置,表现为"只有部分实例异常"。这类问题回滚代码无效。
第 5 步:检查数据结构与接口兼容性
bash
kubectl logs <new-pod> -n <ns> --tail=100 | grep -iE 'unknown field|deserialize|schema|class not found'1
新旧版本并存期间,序列化协议必须双向兼容:允许新增字段但不可删改字段类型。
第 6 步:确认灰度流量比例是否可信
bash
kubectl get pod -n <ns> -l version=new | grep -c Running1
灰度实例太少时指标不可信
1~2 个实例承接少量流量,其错误率统计噪声极大,可能漏掉低频但严重的问题,也可能因单实例抖动误报。
验证
bash
kubectl rollout status deployment/<name> -n <ns>
kubectl get pod -n <ns> -l app=<name> -o wide
kubectl logs -l app=<name> -n <ns> --tail=50 | grep -ci error1
2
3
2
3
常见坑
只看整体错误率发现不了灰度问题
1% 流量的错误会被 99% 正常流量平均掉,必须按版本标签拆分指标。
灰度与全量共用数据库
新版本的 schema 变更会影响全量实例,灰度"只影响少量用户"的假设不成立。
回滚后未验证
rollout undo 只是发起回滚,必须用 rollout status 确认完成,并复验业务指标。
为快速恢复直接删除新版本 Pod
会导致流量瞬间全部切到旧版本且副本数不足。应使用回滚或调整副本/权重平滑切回。