批量更新运行中容器镜像且不停机,标准做法是使用 Kubernetes 的滚动更新策略或 Docker Swarm 的 service update 命令。单机 Docker 容器无法原生支持不停机批量更新,需配合负载均衡器手动脚本实现。
先说结论:实现不停机批量更新必须依赖容器编排工具的健康检查与流量切换机制,单机 Docker 环境无法原生保证。
- 适合:Kubernetes Deployment 滚动更新、Docker Swarm 服务更新场景
- 先准备:配置 readinessProbe 就绪探针、设定资源请求与限制、备份当前镜像版本
- 验收:通过 kubectl rollout status 确认更新完成、验证业务接口响应正常、检查旧 Pod 是否完全终止
命令速用版
Kubernetes 环境更新镜像命令:
kubectl set image deployment/<部署名称> <容器名称>=<新镜像地址>: <标签> -n <命名空间>查看更新状态命令:
kubectl rollout status deployment/<部署名称> -n <命名空间>Docker Swarm 环境更新服务命令:
docker service update `--image` <新镜像地址>: <标签> <服务名称>为什么会这样
容器不可变特性决定了更新镜像必须启动新容器并停止旧容器,编排工具通过控制新旧实例比例实现流量平滑过渡。Kubernetes 的 RollingUpdate 策略会先启动新 Pod,待就绪探针检查通过后,再逐步终止旧 Pod,确保服务始终有可用实例。单机 Docker 容器直接重启会导致服务中断,除非外部有负载均衡器感知容器状态并自动剔除重启中的实例。
分步处理
步骤 1:确认当前状态与备份
适用场景:任何生产环境更新前。操作动作:记录当前镜像标签,确认副本数。验证结果:kubectl get deploy <名称> -o yaml 能看到当前 image 字段。风险边界:若未记录旧版本,更新失败后无法快速回滚。
步骤 2:配置健康检查(若未配置)
适用场景:首次实施滚动更新。操作动作:在 Deployment YAML 中添加 readinessProbe。验证结果:新 Pod 启动后不会立即接收流量,直到探针返回成功。风险边界:缺少探针会导致流量打入未启动完成的容器,引发 502 错误。
步骤 3:执行更新命令
适用场景:正式更新。操作动作:执行 kubectl set image 命令。验证结果:命令返回 image updated。风险边界:镜像拉取失败会导致 Pod 处于 ImagePullBackOff 状态,阻塞更新。
步骤 4:监控滚动过程
适用场景:更新进行中。操作动作:执行 kubectl rollout status。验证结果:显示 deployment successfully rolled out。风险边界:若卡住不动,需检查新 Pod 事件日志。
怎么验证是否生效
检查 Pod 镜像版本:
kubectl get pods -o wide | grep <部署名称>查看容器内实际运行的镜像:
kubectl describe pod <Pod 名称> | grep Image业务验证:通过 curl 或浏览器访问服务接口,确认返回数据符合新版本预期。日志验证:查看新 Pod 日志,确认启动无报错且业务逻辑正常。
常见坑
镜像拉取超时:大镜像在网络不佳时拉取缓慢,导致就绪探针超时,更新卡住。建议提前在节点预拉取镜像或使用私有仓库加速。
资源不足导致无法调度:新 Pod 需要额外资源,若集群资源紧张,旧 Pod 不会终止,新 Pod 无法启动。建议更新前检查集群资源余量。
缺少回滚计划:更新后发现业务逻辑错误。建议更新前确认 kubectl rollout undo 命令可用,并保留旧镜像标签至少 24 小时。
状态服务更新失败:有状态服务(StatefulSet)更新策略不同,需逐个更新。建议确认 workload 类型,StatefulSet 需使用 partition 策略或手动逐个更新。
常见问题
Docker run 启动的容器支持不停机更新吗
不支持。docker run 启动的容器是独立实例,更新镜像必须停止并删除旧容器,期间服务会中断。
更新失败如何快速回滚
Kubernetes 环境执行 kubectl rollout undo deployment/<名称> 即可回滚到上一个稳定版本。
如何确保更新期间零错误请求
必须配置 readinessProbe 就绪探针,并确保负载均衡器健康检查间隔小于探针超时时间,否则流量仍可能打入未就绪容器。
批量更新多个部署有顺序要求吗
有依赖关系的部署需按调用链顺序更新,通常先更新被调用方(后端),再更新调用方(前端),避免接口协议不兼容。