Kubernetes HPA未充分利用节点资源且缩容偏好新Pod
解决Kubernetes 1.9.7中HPA缩容优先删除新Pod的问题
首先得明确:HPA本身并不决定要删除哪个Pod——它的工作只是根据负载调整Deployment/ReplicaSet的副本数量。真正执行Pod删除操作的是ReplicaSet控制器,而在Kubernetes 1.9.7版本里,ReplicaSet的默认逻辑就是优先删除最新创建的Pod(它会把Pod按创建时间从新到旧排序,先删排在最前面的那个)。这就是你看到缩容时新Pod被优先移除的根本原因。
下面给你几个可行的解决方案,按推荐程度排序:
方案1:自定义控制器(长期最优解)
因为K8s 1.9.x没有官方配置项能直接修改ReplicaSet的删除顺序,最靠谱的长期解决办法是写一个轻量的自定义控制器,覆盖默认的删除逻辑:
- 让控制器监听ReplicaSet的副本数变化事件
- 当检测到当前副本数超过期望副本数(也就是需要缩容)时,拉取该ReplicaSet下所有Pod,按创建时间升序排序(最老的Pod排在前面)
- 调用K8s API删除最老的Pod,这样ReplicaSet的副本数会自动匹配期望值,也就不会触发它默认的删新Pod逻辑了
这个方法需要一点开发工作,但能完全贴合你的需求,适合长期在生产环境使用。
方案2:半自动化脚本(临时过渡)
如果暂时不想开发控制器,可以用这个变通的临时方案:
- 在Deployment的Pod模板里添加一个带创建时间戳的标签,比如:
(如果用Helm管理的话,直接用模板函数生成时间戳就行;手动写YAML的话,需要在创建Pod时动态注入这个值)spec: template: metadata: labels: pod-created-at: "{{ now | unixEpoch }}" - 写一个定时脚本或者CronJob,定期做以下检查:
- 遍历所有需要调整的Deployment,对比当前副本数和期望副本数
- 当发现当前副本数多于期望时,查询该Deployment下所有Pod的
pod-created-at标签,找到数值最小的(也就是最老的Pod) - 执行
kubectl delete pod <老Pod的名称>删除它
这个方法实现简单,但存在一定的延迟,适合临时过渡使用。
方案3:升级Kubernetes版本(长远考虑)
虽然直到最新版本的K8s也没有官方配置项能直接修改ReplicaSet的删除顺序,但升级到较新版本(比如1.15+)后,你可以借助更成熟的工具(比如Operator SDK这类自定义控制器框架)来更轻松地实现自定义删除逻辑,同时还能获得K8s新版本带来的功能增强和稳定性提升。
另外补充一句:如果你只是想避免删除某个特定节点上的Pod(比如老Pod所在节点资源充足,不想动它),可以给节点加污点或者给Pod配置节点亲和性,但这和删除新/老Pod的优先级无关,只是调整Pod的调度位置。
内容的提问来源于stack exchange,提问作者syscll
相关产品推荐
相关产品推荐

