如何在推送新镜像至DO容器仓库时触发K8S Deployment滚动更新?
问题描述
我通过控制面板手动创建了一个包含两个节点和K8S负载均衡器的DigitalOcean(DO)Kubernetes集群。使用Gitlab CI构建Docker镜像并推送到已与集群关联的DO容器镜像仓库。遇到的问题是:推送到镜像仓库的新镜像无法触发Deployment滚动更新——原本以为推送带有latest标签的新镜像会自动触发更新,但实际并未生效,应用下方的deployment.yaml文件时系统提示文件未发生变更。
apiVersion: apps/v1 kind: Deployment metadata: name: api labels: app: api spec: replicas: 2 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0 selector: matchLabels: app: api template: metadata: name: api labels: app: api spec: containers: - name: api image: <image> ports: - containerPort: 80 protocol: TCP hostPort: 80
解决方案
1. 使用唯一镜像标签(推荐)
放弃latest标签,每次构建用唯一标识作为镜像标签,比如Git提交哈希、版本号或时间戳。Gitlab CI中可以直接使用内置变量CI_COMMIT_SHA作为标签:
- 构建镜像时:
docker build -t registry.digitalocean.com/your-repo/api:$CI_COMMIT_SHA . - 推送镜像后,更新
deployment.yaml中的image字段为registry.digitalocean.com/your-repo/api:$CI_COMMIT_SHA - 执行
kubectl apply -f deployment.yaml,K8S会检测到镜像标签变更,自动触发滚动更新
2. 手动触发滚动更新
如果坚持使用latest标签,可在Gitlab CI的部署阶段执行以下命令强制触发更新:
kubectl rollout restart deployment/api
注意:需确保Deployment中容器的imagePullPolicy设置为Always,否则节点可能使用本地缓存的旧镜像,导致更新后仍运行旧版本。
3. 通过Pod模板注解触发更新
在Deployment的Pod模板中添加动态变更的注解,让K8S检测到Pod模板变化从而触发滚动更新:
kubectl set annotation deployment/api rollout=$(date +%s) --overwrite
每次推送镜像后执行此命令,注解值(当前时间戳)的变更会让K8S重新创建Pod并拉取最新镜像。
补充:为什么latest标签无法自动触发更新
K8S默认的镜像拉取策略是IfNotPresent,即节点本地已有该标签的镜像时,不会重新拉取。即使把拉取策略改为Always,只要Deployment的Pod模板没有任何字段变更,K8S就不会主动重新创建Pod,因此latest标签无法触发自动滚动更新。
内容的提问来源于stack exchange,提问作者Kostas
相关产品推荐
相关产品推荐

