如何延迟 Deployment Pod 重启

How to delay Deployment Pod restart

我使用的是一个简单的模式,其中一个节点中有一个 Pod,并且该 Pod 由具有一组副本的 Deployment 控制。

部署是为了确保 Pod 在被 DiskPressureEviction 驱逐时重新启动。 我面临的问题是由于 Deployment 重试重启 Pod 的速度过快。由于 Pod 设置在尚未清理 DiskPressure 的特定节点中,因此在节点准备好接受新 Pod 之前重启 Pod 会依次失败:

NAME                                 READY   STATUS              RESTARTS   AGE
deployment-adid-7bb998fccc-4v9dx     0/1     Evicted             0          6m17s
deployment-adid-7bb998fccc-59kvv     0/1     Evicted             0          6m20s
deployment-adid-7bb998fccc-59zzl     0/1     Evicted             0          6m20s
deployment-adid-7bb998fccc-dmm9k     0/1     Evicted             0          6m16s
deployment-adid-7bb998fccc-gn59z     0/1     Evicted             0          6m20s
deployment-adid-7bb998fccc-j4v25     0/1     Evicted             0          6m18s
deployment-adid-7bb998fccc-mw4ps     0/1     Evicted             0          6m20s
deployment-adid-7bb998fccc-n7krq     0/1     Evicted             0          18h
deployment-adid-7bb998fccc-rm4tr     0/1     Evicted             0          6m18s
deployment-adid-7bb998fccc-vn44q     0/1     ContainerCreating   0          6m15s

在这里,在第 9 个被指定节点接受之前,大约 5 秒内创建和驱逐了 8 个 Pods。

虽然最后一个Pod终于变成了Running我不喜欢制造垃圾Pods。如果 Pod 可以等待节点准备就绪,那就太好了,但如果不可能,我想重启可能会被简单地延迟。大概是通过在开始重新创建 Pod 之前描述 waitTime,或者描述 restartInterval 说明 Deployment 应该在哪个时间间隔内尝试重新启动 Pod。

那么如何在 Deployment 的规范中设置这种控件?

添加:

排除无意义的标签,部署规范是这样的:

deployment_template = {
    'apiVersion': 'apps/v1',
    'kind': 'Deployment',
    'metadata': {
        'name': 'first',
    },
    'spec': {
        'replicas': '1',
        'selector': {
            'matchLabels': {
                "podName" : "first"
            }
        },
        'template': {
            'metadata': {
                'labels': {
                    "podName" : "first"
                }
            },
            'spec': {
                'nodeSelector': {
                    "node": "1"
                },
                'restartPolicy': 'Always',
                'hostNetwork': True,
                'dnsPolicy': 'ClusterFirstWithHostNet',
                'containers': [
                    {
                        'name': 'containername',
                        'image': "somecontainerimage",
                        'imagePullPolicy': 'Always',
                    }
                ]
            }
        }
    }
}

...should Node reject Pods when it is resolving DiskPressure?

当节点处于磁盘压力下时,您应该会看到该节点自动被 node.kubernetes.io/disk-pressure 污染。除非您在部署规范中故意容忍此类污点,否则调度程序不会在此类节点上部署您的 pod。

请注意,工作节点不会自行执行磁盘清理。

首先,我建议更新到最新的、受支持的 Kubernetes 版本。您正在使用的 1.17 版本的维护支持 ended 11 months ago. The actual version (as of today 15.12.2021) is v1.23. Since Kubernetes v1.18 the feature TaintBasedEvictions 处于稳定模式。

另一件事是,与其尝试延迟部署,不如尝试延迟部署,这是一种变通方法,而不是最佳做法,最好解决一个主要问题,即您正在发生的磁盘压力驱逐。您应该考虑更改应用程序的行为,或者至少尝试通过增加节点的存储大小来避免节点上的磁盘压力。

无论如何,如果你想保持这种状态,你可以尝试设置一些额外的参数。您不能自己延迟部署,但可以更改节点上 kubelet agent 的行为。


以下示例适用于 Kubernetes 版本 1.23。请记住,对于版本 1.17,它可能会有所不同。

我创建了一个有一个主节点和一个工作节点的集群,pods 只在工作节点上调度。我正在完成工作人员存储以创建 node.kubernetes.io/disk-pressure。默认情况下,行为类似于您的行为,许多 pods 是在 Evicted 状态下创建的,值得注意的是,这是完全正常的,并且是预期的行为。他们一直在创建,直到节点受到污染 disk-pressurewhich is occurring after ~10 seconds by default:

nodeStatusUpdateFrequency is the frequency that kubelet computes node status. ... Default: "10s"

在那之后,您可以观察到,Evicted 状态下没有创建 pods。 ~5 分钟后,污点被删除(即在你的情况下,节点上的磁盘存储恢复到正确的值),它是 defined by evictionPressureTransitionPeriod parameter:

evictionPressureTransitionPeriod is the duration for which the kubelet has to wait before transitioning out of an eviction pressure condition. ... Default: "5m"

好的,让我们通过在工作节​​点上编辑 kubelet config file 来更改一些配置 - 它位于 kubeadm 的 /var/lib/kubelet/config.yaml

我将更改三个参数:

文件 var/lib/kubelet/config.yaml - 仅更改/添加的字段:

evictionPressureTransitionPeriod: 120s
evictionSoftGracePeriod: 
  nodefs.available: 60s
evictionSoft:
  nodefs.available: 15Gi 

综上所述——我的节点存储小于15GB后,pod将处于运行ning状态60秒。之后,如果存储空间仍小于 15 GB,pods 将进入 Evicted / Completed 状态,新的 pods 将进入 Pending 状态:

NAME                                   READY   STATUS      RESTARTS   AGE
my-nginx-deployment-6cf77b6d6b-2hr2s   0/1     Completed   0          115m
my-nginx-deployment-6cf77b6d6b-8f8wv   0/1     Completed   0          115m
my-nginx-deployment-6cf77b6d6b-9kpc9   0/1     Pending     0          108s
my-nginx-deployment-6cf77b6d6b-jbx5g   0/1     Pending     0          107s

可用存储高于 15 GB 后,将需要 2 分钟来删除污点并创建新的 pods。

如果在这 60 秒内可用存储再次高于 15GB,则不会执行任何操作,pods 仍将处于 Running 状态。

如果你有任何垃圾pods运行ning,运行这个命令删除它们:

kubectl get pods | grep -e "ContainerStatusUnknown" -e "Evicted" -e "Completed" -e "Error" | awk '{print }' | xargs kubectl delete pod

请记住,pod 逐出的行为可能因不同 QoS classes and priority classes- check this article -> Node-pressure Eviction - Pod selection for kubelet eviction 以获取更多信息。

您应该尝试监控节点上磁盘压力的准确程度,并相应地调整 kubelet 配置。另请查看这些文章: