如何限制Kubernetes Pod数量,避免旧Pod未终止前创建新Pod
问题描述
我有一个包含20个副本的Kubernetes Deployment,用于运行长时间的Celery任务。我们会频繁向集群部署(最多约每10分钟一次),为避免任务中断,我为Pod设置了3小时的终止宽限期。但每次部署时Kubernetes都会尝试额外创建20个Pod,如何阻止Kubernetes在现有Pod终止前调度新Pod?
部署方式
我的部署通过GitHub Action执行helm升级,替换刚构建好的新镜像标签:
helm upgrade --kube-context SK2 --install -f ./kube/helm/p1/values_SK2.yaml -n $REPOSITORY_NAME --set image.tag=$GIT_COMMIT $REPOSITORY_NAME ./kube/helm/p1 --atomic --debug --history-max=100 --timeout 6m
尝试过的方案
方案1:配置RollingUpdate策略
尝试设置RollingUpdate策略,将maxUnavailable设为20,maxSurge设为1,期望部署时仅创建1个额外Pod,且在所有旧Pod终止后再调度新Pod:
strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 20 maxSurge: 1
方案2:先固定镜像再更新标签
先将镜像固定为latest,而非部署时直接更新镜像,之后在helm安装完成后修改Deployment的镜像标签:
kubectl --context SK2 -n p1 set image deployment/celery-io-long celery-io-long=stringking/p1:$GIT_COMMIT
但这两种方法最终都会在部署时创建一批新的20个Pod,且旧Pod尚未终止。我哪里操作错了?
解决方案
你的核心问题在于RollingUpdate策略的参数配置不符合需求,以及对参数含义的理解偏差:
- 修正RollingUpdate策略参数
要实现“旧Pod终止后再创建新Pod”的逻辑,需要设置:
strategy: type: RollingUpdate rollingUpdate: maxSurge: 0 # 不允许超过副本数创建额外Pod maxUnavailable: 1 # 每次仅允许1个Pod不可用(即先终止1个旧Pod,再创建1个新Pod)
maxSurge: 0:严格限制Kubernetes不能创建超过Deployment副本数的Pod,彻底避免额外Pod出现。maxUnavailable: 1:控制每次仅终止1个旧Pod,等它完全终止(走完3小时宽限期)后,再启动1个新Pod。如果想加快替换速度,可以适当调高这个值(比如设为2,每次替换2个),但不会出现额外Pod。
你之前设置的maxUnavailable: 20意味着允许所有20个旧Pod同时被终止,配合maxSurge:1会让Kubernetes触发批量调度逻辑,提前创建大量新Pod,导致额外实例出现。
- 确保Helm配置生效
检查你的Helm模板(./kube/helm/p1/templates下的Deployment文件),确认strategy配置已经正确引用了values.yaml中的参数,避免被模板默认配置覆盖。模板中应有类似代码:
strategy: {{- toYaml .Values.deployment.strategy | nindent 4 }}
- 排除Recreate策略
不要使用Recreate策略,它会先删除所有旧Pod再创建新Pod,会导致任务完全中断,不符合你“避免任务中断”的需求。
内容的提问来源于stack exchange,提问作者MikeSchem
相关产品推荐
相关产品推荐

