Kubernetes 节点池不会自动缩放到 0 个节点

Kubernetes 节点池不会自动缩放到 0 个节点

我有一个相当昂贵的工作量,一些同事需要在工作日的某些时候运行它(不按照任何既定时间表运行)。我使用 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。因此,您需要保留至少一个节点。但这并不意味着您需要保留一个昂贵的节点空闲运行。

-- Medium.com:使用 gke autoscaler 将 kubernetes 集群扩展到几乎为零

您可以明确地将节点池减少到零 (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"

-- Github.com:Kubernetes 自动扩缩器:哪些类型的 pod 可以阻止 ca 删除节点

如果未充分利用的节点正在运行不应驱逐的 Pod,CA 不会删除这些节点

不缩减规模的其他可能原因:

  • 节点组已达到最小规模,
  • 尝试删除此特定节点失败,在这种情况下,Cluster Autoscaler 将等待额外 5 分钟,然后再次考虑删除它,

-- Github.com:我有几个利用率较低的节点,但它们没有缩小规模,为什么

相关内容