我有一个相当昂贵的工作负载,一些同事有时需要在工作日运行(而不是按照任何设定的时间表)。我使用谷歌云 Kubernetes。
它由三个 statefulsets 组成,每个 statefulsets 有一个副本。
我已经指导他们如何“打开”和“关闭”它。为了“打开”它,他们将每个 statefulset 扩展到 1 个副本。为了“关闭”它,他们将每个 statefulset 扩展为 0 个副本。
最初,我有一个默认大小为三个节点的自动缩放节点池(每个状态集几乎消耗整个节点的 CPU 和 RAM)。我观察到,即使在缩小到 0 之后,一两个小时后至少会保留一个(有时是两个)节点。我期待最终所有节点都会消失,但这并没有发生。
我注意到正在运行的节点仍然有一些 pod,只是在不同的命名空间中。其余的 pod 都在kube-system
命名空间中,除了一个在custom-metrics
命名空间中。
所以我想,好吧——即使没有用户定义的工作负载/pod,Kubernetes 也可能想要运行其他服务。所以我创建了另一个节点池,有一个非常小但足够的节点。该节点足够大,可以运行 Kubernetes 报告在那些非default
命名空间中运行的所有内容。
在新节点池与一个节点一起运行后,我继续手动将原始节点池的大小调整为 0。这很好。我希望此时我有一个用于运行kube-system
和其他东西的“系统”节点池,以及一个用于运行我自己的东西的“用户”节点池。
所以对于我的下一个测试,这次我只扩展了一个 statefulset 副本。最终一个节点上线,statefulset pod 正在运行/准备就绪。然后我再次将其缩小到 0 并等待......等待......并且节点没有消失。
使自动缩放节点池实际达到 0 个节点需要什么?显然我遗漏了一些东西(或更多东西),但我很难找到有关触发节点缩放器将节点池缩小到 0 所需的信息。
任何建议表示赞赏。
附加信息
当我查看节点池中的节点上运行的内容时,我想转到 0,这就是我看到的
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE
--------- ---- ------------ ---------- --------------- ------------- ---
kube-system fluentd-gcp-v3.1.1-mfkxf 100m (0%) 1 (3%) 200Mi (0%) 500Mi (0%) 28m
kube-system kube-proxy-gke-tileperformance-pool-1-14d3671d-jl76 100m (0%) 0 (0%) 0 (0%) 0 (0%) 28m
kube-system prometheus-to-sd-htvnw 1m (0%) 3m (0%) 20Mi (0%) 20Mi (0%) 28m
如果我尝试访问drain
节点,它会抱怨它们是通过 管理的DaemonSet
,所以我可以强制它,但显然我试图不必以任何方式手动干预。
哈克
为了让自动缩放器“工作”并缩小到 0,我暂时nodeSelector
在所有kube-system
部署中添加了一个,以便将它们分配到一个单独的池中kube-system
。但必须有更好的方法,对吧?
Autoscaler 不会将您的节点池减少到 0。
您可以使用以下命令将节点池显式减少为零 (0):
$ gcloud container clusters resize CLUSTER_NAME --node-pool NAME_OF_THE_POOL --num-nodes 0
但请注意,这种方法会有一个缺点。
想象一种情况:
Autoscaler 将无法从零增加节点数。它无法判断是否需要额外的资源。在这些节点上运行的 pod
kube-system
对于确定是否需要另一个节点至关重要。有一篇文章的用例与您的相似。请看一下:Medium.com:使用 gke autoscaler 将您的 kubernetes 集群扩展到几乎为零
另一种方法是使用 pod 中断预算。请查看以下资源:
可能阻止集群自动扩缩程序删除节点的可能原因:
如果它们正在运行不应驱逐的 pod,CA 不会删除未充分利用的节点
不按比例缩小的其他可能原因:
在 GKE 1.18 上,我的实验表明我必须添加节点污染才能使节点池能够缩小到零: