如何设置Kubernetes Deployment Pod重启延迟避免DiskPressure产生垃圾驱逐Pod
解决方案
原生Deployment没有直接提供重建Pod前等待的waitTime或restartInterval配置参数,可通过以下两种可行方案实现需求,避免快速重试产生大量被驱逐的垃圾Pod:
方案1:配置指数退避+自动清理规则
Deployment控制器本身默认支持失败重试的指数退避逻辑,可通过调整以下参数拉长重试间隔、自动清理垃圾Pod:
- 在Deployment的
spec下添加progressDeadlineSeconds参数:设置部署超时时间,超过该时间后Deployment会停止快速重试,进入指数退避逻辑,示例配置为600秒(10分钟),可根据节点磁盘清理的平均耗时调整 - 在Pod模板的
spec下添加ttlSecondsAfterFinished参数(要求K8s版本≥1.21,且集群开启TTLAfterFinished特性门控):被驱逐的Pod会在到期后自动删除,无需手动清理,示例配置为300秒(5分钟)后自动清理 - 配置
spec.revisionHistoryLimit参数:限制Deployment留存的历史副本集数量,默认是10,可调整为2-3减少冗余资源
修改后的配置示例(仅展示新增/调整字段):
deployment_template = { 'apiVersion': 'apps/v1', 'kind': 'Deployment', 'metadata': { 'name': 'first', }, 'spec': { 'replicas': 1, # 注意这里是数字不是字符串,原配置写法有误 'progressDeadlineSeconds': 600, # 新增:部署超时时间 'revisionHistoryLimit': 2, # 新增:历史副本集留存数量 'selector': { 'matchLabels': { "podName" : "first" } }, 'template': { 'metadata': { 'labels': { "podName" : "first" } }, 'spec': { 'ttlSecondsAfterFinished': 300, # 新增:失效Pod自动清理时间 'nodeSelector': { "node": "1" }, 'restartPolicy': 'Always', 'hostNetwork': True, 'dnsPolicy': 'ClusterFirstWithHostNet', 'containers': [ { 'name': 'containername', 'image': "somecontainerimage", 'imagePullPolicy': 'Always', } ] } } } }
方案2:添加InitContainer等待节点就绪(更推荐)
直接在Pod中添加前置初始化容器,检测到目标节点无DiskPressure污点后再启动业务容器,从根源避免创建后立即被驱逐的问题:
- InitContainer可调用K8s apiserver查询目标节点的状态,确认没有磁盘压力污点后再退出
- 若节点仍有磁盘压力,InitContainer休眠指定时间后重试,直到节点就绪
修改后的配置示例(新增InitContainer字段):
deployment_template = { 'apiVersion': 'apps/v1', 'kind': 'Deployment', 'metadata': { 'name': 'first', }, 'spec': { 'replicas': 1, 'progressDeadlineSeconds': 600, 'revisionHistoryLimit': 2, 'selector': { 'matchLabels': { "podName" : "first" } }, 'template': { 'metadata': { 'labels': { "podName" : "first" } }, 'spec': { 'serviceAccountName': 'node-query-sa', # 需提前创建有节点查询权限的SA 'nodeSelector': { "node": "1" }, 'restartPolicy': 'Always', 'hostNetwork': True, 'dnsPolicy': 'ClusterFirstWithHostNet', # 新增InitContainer 'initContainers': [ { 'name': 'wait-node-ready', 'image': 'bitnami/kubectl:latest', # 包含kubectl命令的镜像 'command': [ '/bin/sh', '-c', 'while true; do if kubectl get node 1 -o jsonpath="{.status.conditions[?(@.type==\"DiskPressure\")].status}" | grep -q "False"; then exit 0; fi; sleep 30; done' ] } ], 'containers': [ { 'name': 'containername', 'image': "somecontainerimage", 'imagePullPolicy': 'Always', } ] } } } }
注意:使用该方案需要提前创建拥有节点查询权限的ServiceAccount(
node-query-sa),并绑定对应的ClusterRole权限。
额外说明
如果你的K8s集群版本较低不支持TTLAfterFinished,也可以定期执行命令清理被驱逐的Pod:
kubectl get pods --all-namespaces | grep Evicted | awk '{print $1 " " $2}' | xargs -n2 kubectl delete pod -n
内容的提问来源于stack exchange,提问作者김기영
相关产品推荐
相关产品推荐

