[英]Docker Kubernetes (Mac) - Autoscaler unable to find metrics
[英]Kubernetes AutoScaler or changing Desired Nodes in AWS prematurely terminates Docker Pods
我构建了一个服务,利用 docker 个 pod 来处理数据。 所需时间少则 15 分钟,多则 1 小时。
我的应用程序捕获 SIGTERM 以确保在 Pod 和节点退役时需求下降时正常关闭。
在每个 docker 图像中,我都放置了代码来报告它是否因为它完成了工作而关闭,以及是否发生了 SIGTERM 事件并因此完成了它的处理并终止了。
我的系统使用 EKS 部署在 AWS 中。 我使用 EKS 在需求上升时管理节点部署,在需求下降时管理节点停转。 我使用 KEDA 来管理 POD 部署,这有助于触发是否需要额外的节点。 在 KEDA 中,我将 cooldownPeriod 定义为 2 小时,这是我希望 pod 花费的最大值,即使它花费的最大值是 1 小时。
在 AWS EKS 中,我也定义了 2 小时的 terminationGracePeriodSeconds。
我在节点缩减期间隔离了这个问题,当节点被终止时,terminationGracePeriodSeconds 没有得到遵守,我的 Pod 在大约 30 分钟内被关闭。 因为 Pod 被突然移除,所以我无法查看它们的日志以了解发生了什么。
我试图通过发出 kube.netes 节点耗尽来模拟这个问题并让我的 pod 保持运行
kubectl drain <MY NODE>
我看到 SIGTERM 通过,我还注意到 pod 仅在 2 小时后而不是之前终止。
所以有那么一小会儿我想也许我没有正确配置 terminationGracePeriod,所以我检查了:
kubectl get deployment test-mypod -o yaml|grep terminationGracePeriodSeconds
terminationGracePeriodSeconds: 7200
我什至重新部署了配置,但这没有任何区别。
但是,我能够通过修改节点组的 desiredSize 来重现该问题。 我可以通过这样做以编程方式在 Python 中重现它:
resp = self.eks_client.update_nodegroup_config(clusterName=EKS_CLUSTER_NAME,
nodegroupName=EKS_NODE_GROUP_NAME,
scalingConfig={'desiredSize': configured_desired_size})
或者只需转到 AWS 控制台并在那里修改 desiredSize。
我看到 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
这是我的 kuber.nets 版本
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 过早停止。
使用 Amazon EKS 时,节点自动扩缩器不遵守 TerminationGracePeriodSeconds。 每
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 作为备用自动扩缩器。
我们在使用 AWS EKS 和 cluster-autoscaler 时遇到了同样的问题 - 节点意外关闭,没有任何预防措施起作用,甚至节点注释cluster-autoscaler.kubernetes.io/scale-down-disabled=true
也没有任何区别.
经过两天的排查,我们找到了原因——因为我们在 ASG 配置中使用了 Multiple Availability Zone,它有一个自动的“AZRebalance”过程。 AZRebalance 尝试确保所有可用区之间的节点数大致相同。 因此,有时当扩展事件发生时,它会尝试通过杀死一个节点并在不同时区创建另一个节点来重新平衡节点。 事件日志中的消息如下所示:
Cluster-autoscaler 不控制此过程,因此有两个系统(cluster-autoscaler 和 AWS ASG)同时管理节点数量,这会导致意外行为。
作为一种解决方法,我们暂停了 ASG 中的“AZRebalance”进程。
另一种解决方案是分别为每个可用区使用 ASG,并在集群自动缩放器中使用--balance-similar-node-groups
功能。
我们与亚马逊支持合作解决了这个问题。 最终的解决方案与@lub0v 的答案相差不远,但仍然缺少一个组件。
我们的 EKS 系统只有一个管理多个可用区的节点组。 相反,我为每个可用区部署了一个节点组。 一旦我们这样做了,TerminationGracePeriod 就被兑现了。
另外,不要忘记我之前添加的先前答案,确保您的 pod 注释包含 safe-to-evict 设置为 false
最后,如果您希望在升级期间部署相同数量的节点,请在集群自动缩放器命令行参数中使用 --balance-similar-node-groups 。 目前这个参数在缩减尺度时不被接受。
自动缩放参考: https://github.com/kube.netes/autoscaler/blob/master/cluster-autoscaler/FAQ.md
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.