智享教程网
白蓝主题五 · 清爽阅读
首页  > 日常经验

容器版本滚动更新实战经验分享

最近在公司负责一个微服务项目的运维,服务都跑在 Kubernetes 上。前阵子要上线新功能,涉及到多个服务的版本升级。最开始我直接删掉旧 Pod 起新的,结果用户反映服务中断了几秒,虽然不长,但在高峰期挺致命的。后来改用滚动更新,问题就解决了。

什么是滚动更新

简单说,滚动更新就是不一次性把所有实例全换掉,而是逐个替换。比如你有 3 个 Pod 在运行旧版本,K8s 会先起一个新版本的 Pod,等它就绪后,再干掉一个旧的,如此反复,直到全部换成新版本。整个过程服务始终在线,用户几乎无感。

怎么配置滚动更新策略

Kubernetes 默认就是滚动更新,但你可以自定义策略来控制节奏。比如下面这个 Deployment 配置:

apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app-container
image: my-app:v1.0

这里 maxSurge: 1 表示最多可以比目标副本多启动一个 Pod,也就是更新时最多有 4 个 Pod 在跑。maxUnavailable: 0 表示更新过程中不允许有任何一个 Pod 不可用,保证服务始终有 3 个健康实例。

实际操作中的小技巧

有一次我更新时发现新版本启动失败,Pod 一直在 CrashLoopBackOff。因为设置了 maxUnavailable: 0,系统不会继续替换,旧的 Pod 还在撑着,服务没挂。我赶紧查看日志,发现是环境变量写错了,修复后重新打镜像,推上去就恢复正常了。

建议每次更新前先把镜像推到仓库,确认 tag 没问题。更新时可以用 kubectl set image deployment/my-app my-app-container=my-app:v2.0 快速触发滚动更新。

还可以用 kubectl rollout status deployment/my-app 实时观察更新进度。如果发现问题,立刻执行 kubectl rollout undo deployment/my-app 回滚到上一版,特别救命。

别忘了健康检查

滚动更新能顺利进行,前提是 K8s 能准确判断新 Pod 是否就绪。所以一定要配好 readinessProbelivenessProbe。比如你的应用启动要 10 秒,那 readinessProbe 的 initialDelaySeconds 至少设成 12 秒,不然 K8s 以为你挂了,直接把你干掉。

有一次我就栽在这儿,新 Pod 没准备好就被加进服务,结果请求打进来直接 500。加上合理的探针后,这种问题再没出现过。