我有一个相当昂贵的工作量,一些同事需要在工作日的某些时候运行它(不按照任何既定时间表运行)。我使用 Google Cloud Kubernetes。
它由三个 statefulset 组成,每个 statefulset 都有一个副本。
我已经告诉他们如何将其“打开”和“关闭”。要将其“打开”,他们将每个 statefulset 缩放为 1 个副本。要将其“关闭”,他们将每个 statefulset 缩放为 0 个副本。
最初,我有一个默认大小为三个节点的自动缩放节点池(每个有状态集几乎消耗整个节点的 CPU 和 RAM)。我观察到,即使缩减到 0,一两个小时后至少会剩下一个(有时是两个)节点。我原本以为最终所有节点都会消失,但事实并非如此。
kube-system
我注意到正在运行的节点仍然有一些 Pod,只是在不同的命名空间中。除了一个 Pod 在命名空间中外,其余 Pod 都在命名空间中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
。但一定有更好的方法,对吧?
答案1
在 GKE 1.18 上,我的实验表明,我必须添加节点污点才能使节点池能够缩小到零:
$ gcloud container node-pools create ... \
--min-nodes 0 \
--max-nodes 2 \
--node-taints=... # Without a taint, my node pool won't scale down to zero somehow.
答案2
自动缩放器不会将您的节点池减少到 0。
笔记:如果您指定最小节点数为零,则空闲节点池可以完全缩减。但是,集群中必须始终有一个节点可用来运行系统 Pod。
-- Google Cloud:Kubernetes 引擎集群自动扩缩器
但是,集群自动扩缩器无法完全将整个集群缩减为零。集群中必须始终有一个节点可用来运行系统 pod。因此,您需要保留至少一个节点。但这并不意味着您需要保留一个昂贵的节点空闲运行。
您可以明确地将节点池减少到零 (0)使用命令:
$ gcloud container clusters resize CLUSTER_NAME --node-pool NAME_OF_THE_POOL --num-nodes 0
但请注意,这种方法有一个缺点。
想象一下这样的情况:
- 您将集群缩小到零使用上述命令的节点
- 您在集群上创建了以下工作负载:零节点
Autoscaler将无法增加节点数量零。它无法判断是否需要额外的资源。kube-system
在这些节点上运行的 pod 对于确定是否需要另一个节点至关重要。
有一篇文章的用例和你的类似。请看一下:Medium.com:使用 gke autoscaler 将 kubernetes 集群扩展到几乎为零
另一种方法是使用 pod 中断预算。请查看以下资源:
可能阻止集群自动扩缩器删除节点的原因有:
- 具有限制性 PodDisruptionBudget 的 Pod。
- Kube 系统 Pod 可以:
- 默认情况下不在节点上运行,
- 没有 pod 中断预算 设置或其 PDB 过于严格(自 CA 0.6 起)。
- 不受控制器对象支持的 Pod(因此不是由部署、副本集、作业、状态集等创建的)。
- 具有本地存储的 Pod。
- 由于各种限制(缺乏资源、节点选择器或亲和性不匹配、反亲和性匹配等)而无法移动到其他地方的 Pod
- 设置了以下注释的 Pod:
"cluster-autoscaler.kubernetes.io/safe-to-evict": "false"
除非 pod 有以下注解(CA 1.0.3 或更高版本支持):
"cluster-autoscaler.kubernetes.io/safe-to-evict": "true"
如果未充分利用的节点正在运行不应驱逐的 Pod,CA 不会删除这些节点
不缩减规模的其他可能原因:
- 节点组已达到最小规模,
- 尝试删除此特定节点失败,在这种情况下,Cluster Autoscaler 将等待额外 5 分钟,然后再次考虑删除它,