【问题标题】:Kubernetes AutoScaler or changing Desired Nodes in AWS prematurely terminates Docker PodsKubernetes AutoScaler 或更改 AWS 中的所需节点会过早终止 Docker Pod
【发布时间】:2022-04-12 01:32:35
【问题描述】:

我构建了一个利用 docker pod 处理数据的服务。所需时间从 15 分钟到 1 小时不等。

我的应用程序捕获 SIGTERM 以确保在 Pod 和节点退役时需求下降时正常关闭。

在每个 docker 映像中,我放置了代码来报告它是否因完成工作而关闭,以及是否发生 SIGTERM 事件并因此完成其处理并终止。

我的系统使用 EKS 部署在 AWS 中。当需求上升时,我使用 EKS 来管理节点部署,并在需求下降时管理节点。我使用 KEDA 来管理 POD 部署,这有助于触发是否需要额外的节点。在 KEDA 中,我将 cooldownPeriod 定义为 2 小时,这是我期望 pod 占用的最大值,即使它需要的最大值是 1 小时。

在 AWS EKS 中,我还定义了 2 小时的 terminateGracePeriodSeconds。

我在节点缩减期间隔离了这个问题,即当节点被终止时,terminationGracePeriodSeconds 没有得到遵守,并且我的 Pod 在大约 30 分钟内被关闭。由于 Pod 被突然移除,我无法查看它们的日志以了解发生了什么。

我尝试通过发出 kubernetes 节点耗尽来模拟此问题并保持我的 pod 运行

kubectl drain <MY NODE>

我看到 SIGTERM 通过了,我还注意到 pod 仅在 2 小时后才终止,而不是之前。

所以有那么一分钟我想也许我没有正确配置terminationGracePeriod,所以我检查了:

kubectl get deployment test-mypod -o yaml|grep terminationGracePeriodSeconds
  terminationGracePeriodSeconds: 7200

我什至重新部署了配置,但这并没有什么不同。

但是,我能够通过修改 Node 组的 desiredSize 来重现该问题。我可以通过这样做在 Python 中以编程方式重现它:

        resp = self.eks_client.update_nodegroup_config(clusterName=EKS_CLUSTER_NAME,
                                                       nodegroupName=EKS_NODE_GROUP_NAME,
                                                       scalingConfig={'desiredSize': configured_desired_size})

或者只需转到 AWS 控制台并在那里修改所需的大小。

我看到 EKS 选择了一个节点,如果碰巧有一个 pod 处理数据需要大约一个小时,那么该 pod 有时会过早终止。

我已经登录到那个正在缩减的节点,并且在日志中没有发现 Pod 提前终止的证据。

我曾经能够捕捉到这些信息

kubectl get events | grep test-mypod-b8dfc4665-zp87t
54m         Normal    Pulling    pod/test-mypod-b8dfc4665-zp87t         Pulling image ...
54m         Normal    Pulled     pod/test-mypod-b8dfc4665-zp87t         Successfully pulled image ...
54m         Normal    Created    pod/test-mypod-b8dfc4665-zp87t         Created container mypod
54m         Normal    Started    pod/test-mypod-b8dfc4665-zp87t         Started container mypod
23m         Normal    ScaleDown  pod/test-mypod-b8dfc4665-zp87t         deleting pod for node scale down
23m         Normal    Killing    pod/test-mypod-b8dfc4665-zp87t         Stopping container mypod
13m         Warning   FailedKillPod   pod/test-po-b8dfc4665-zp87t       error killing pod: failed to "KillContainer" for "mypod" with KillContainerError: "rpc error: code = Unknown desc = operation timeout: context deadline exceeded"

我曾经看到一个 pod 在禁用 scaledown 时无缘无故被移除,但它决定移除我的 pod:

kubectl get events | grep test-mypod-b8dfc4665-vxqhv
45m         Normal    Pulling    pod/test-mypod-b8dfc4665-vxqhv Pulling image ...
45m         Normal    Pulled     pod/test-mypod-b8dfc4665-vxqhv Successfully pulled image ...
45m         Normal    Created    pod/test-mypod-b8dfc4665-vxqhv Created container mypod
45m         Normal    Started    pod/test-mypod-b8dfc4665-vxqhv Started container mypod
40m         Normal    Killing    pod/test-mypod-b8dfc4665-vxqhv Stopping container mypod

这是我的 kuberenets 版本

Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.0" GitCommit:"9e991415386e4cf155a24b1da15becaa390438d8", GitTreeState:"clean", BuildDate:"2020-03-25T14:58:59Z", GoVersion:"go1.13.8", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"18+", GitVersion:"v1.18.20-eks-8c49e2", GitCommit:"8c49e2efc3cfbb7788a58025e679787daed22018", GitTreeState:"clean", BuildDate:"2021-10-17T05:13:46Z", GoVersion:"go1.13.15", Compiler:"gc", Platform:"linux/amd64"}

为了最大程度地减少此问题,我在高峰时段部署了 Pod 中断预算以阻止缩减,并在晚上需求低迷时删除了启动缩减的 PDB。但是,这不是正确的解决方案,即使在低峰期间,仍有 pod 过早停止。

【问题讨论】:

  • 您是否使用 cluster-autoscaler 来扩展节点?如果是,您能否针对您的问题列出用于配置 cluster-autoscaler 的所有参数。如果没有,您能否详细说明如何扩展节点(不是 pod,例如,您使用 karpenter?您设置了什么配置?)。
  • 您好 Amro Younes,您能否提供有关您按照 gohm'c 要求使用的自动缩放器的更多信息?
  • 我使用集群自动扩缩器。并遵循以下步骤:docs.aws.amazon.com/eks/latest/userguide/…。我将编辑问题并包含我为 v1.18 下载的自动缩放器配置模板
  • 这是我下载的集群自动缩放器:raw.githubusercontent.com/kubernetes/autoscaler/master/… 并针对我的集群进行了修改。附带说明一下,我正在将集群版本从 1.18 升级到 1.22。当我重新部署自动缩放器时,我意识到我拥有的模板适用于 1.21 版。我需要解决这个问题才能消除这种可能性,但即使我有 1.18 模板,这个问题仍然存在
  • 我将控制平面和节点集群升级到v1.21。我从系统中删除了 ELK 监控的 HELM 部署。当节点缩小时,我仍然看到 Pod 突然终止的问题。同时,我恢复了 PDB 配置以阻止缩减。

标签: docker kubernetes amazon-eks keda


【解决方案1】:

在使用 Amazon EKS 时,节点自动扩缩器不遵守 TerminationGracePeriodSeconds。每

https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#does-ca-respect-gracefultermination-in-scale-down

Node Autoscaler 仅提供 10 分钟的宽限期。我在这里提取了相关文字:

Cluster Autoscaler 有多快?

默认情况下,在 pod 标记为不可调度后 10 秒内考虑纵向扩展,并在节点变为不需要节点后 10 分钟内缩减。有多个标志可用于配置这些阈值。例如,在某些环境中,您可能希望给 k8s 调度程序比 CA 的扫描间隔多一点的时间来调度 Pod。一种方法是设置 --new-pod-scale-up-delay,这会导致 CA 忽略不可调度的 pod,直到它们达到某个“年龄”,而不管扫描间隔如何。如果 k8s 在延迟结束时还没有安排它们,那么 CA 可能会考虑它们以进行可能的扩展。

另一个相关链接:https://github.com/kubernetes/autoscaler/issues/147

我实现了一个脚本作为 preStop Hook 调用,它有望阻止发出 SIGTERM 的下一个状态并开始 10 分钟倒计时,让我有机会优雅地关闭我的服务。但是,preStopHook 不会延迟 10 分钟计时器。

对该设置的一些参考:

https://www.ithands-on.com/2021/07/kubernetes-101-pods-lifecycle-hooks_30.html

https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/

相反,我根据以下参考在我的 pod 部署配置中添加了以下注释:

https://aws.github.io/aws-eks-best-practices/cluster-autoscaling/#prevent-scale-down-eviction

template:
  metadata:
    labels:
      annotations:
        cluster-autoscaler.kubernetes.io/safe-to-evict: 'false'

然后我确保我的 pod 成为按需 pod,即没有 pod 部署为空闲,因为空闲 pod 会影响 EKS 缩减,并且仅在需要时生成并在其任务完成时关闭。这会减慢我对作业的响应时间,但与在昂贵的计算中关闭 Pod 相比,这是一个较小的代价。

如果有人对如何部署 AWS Cluster Autoscaler 感到好奇: https://docs.aws.amazon.com/eks/latest/userguide/autoscaling.html#cluster-autoscaler

它也有关于禁用 Pod 驱逐的参考

在负载下,我们仍然看到 safe-to-evict 注释未得到遵守,并将此情况报告给 Amazon AWS。通过额外的调试,我发现 EKS 看到托管 Pod 的节点正在消失,尽管 EKS 忽略了可以安全驱逐的节点。 EKS 和 EC2 之间可能存在互操作性问题。在解决此问题之前,我正在考虑使用 Fargate 作为备用自动扩缩器。

【讨论】:

    猜你喜欢
    • 2020-09-30
    • 2018-10-09
    • 1970-01-01
    • 1970-01-01
    • 2020-07-25
    • 2017-07-09
    • 1970-01-01
    • 2022-01-12
    • 1970-01-01
    相关资源
    最近更新 更多