原文链接:https://medium.com/scout24-engineering/cluster-overprovisiong-in-kubernetes-79433cb3ed0e
cluster-autoscaler是Kubernetes Github组织的一部分,但它是一个纯粹的可选工具。您需要像常规部署一样将其部署到群集并对其进行配置,以便它可以查找和管理您的节点组(如果是AWS,则为Autoscaling组)。cluster-autoscaler将开箱即用:
嗯,这听起来很棒!但容器的一个很好的特性是它们的启动速度比VM快得多,对吧?在其默认配置中使用cluster-autoscaler时,您将有一些缓慢且不可预测的缩放行为。只有当pod进入暂挂状态时,cluster-autoscaler才会通过添加节点做出反应。由于EC2实例可能需要几分钟才能启动并准备好运行pod,因此如果您运行对此类扩展延迟敏感的服务,则这不是理想情况。我们怎么解决这个问题?
虽然cluster-autoscaler有替代方案([ 1 ],[ 2 ]),但我们希望继续使用Kubernetes社区提供的最常用解决方案。事实证明,有一种非常优雅的方式来对Node进行扩缩容,以便它总是预留一些动态缓冲区资源,以避免需要扩容的pod进入Pending
状态几分钟。
Pod Priority和Preemption是Kubernetes功能,允许您为pod分配优先级。简而言之,这意味着当群集资源不足时,它可以抢占(驱逐)优先级较低的pod,以便为等待安排的更高优先级的pod腾出空间。使用pod优先级,我们可以运行一些虚拟pod来保留集群中的额外空间,只要“真正的”pod需要运行就会释放。用于预订的吊舱理想情况下不应该使用任何资源,而只是坐在那里什么都不做。您可能听说过Pause容器已经在Kubernetes中用于共享namespace、network网络栈、PID Namespace,Pause容器的一个属性是它主要只是调用暂停系统调用,这意味着“睡眠直到收到信号”。
常规Pod和过度配置的Pod
总而言之,我们可以在群集中运行一堆Pause容器,其唯一目的是保留空间以欺骗cluster-autoscaler过早添加额外节点。由于这些Pod的优先级低于常规Pod,因此一旦资源变得稀缺,它们就会从群集中被驱逐。Pause容器将进入Pending状态
,进而触发cluster-autoscaler以增加node节点。总的来说,这是一种非常优雅的方式,可以在群集中始终拥有动态缓冲区。
---
apiVersion: scheduling.k8s.io/v1beta1
kind: PriorityClass
metadata:
name: overprovisioning
value: -1
globalDefault: false
description: "Priority class used by overprovisioning."
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: overprovisioning
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
run: overprovisioning
template:
metadata:
labels:
run: overprovisioning
spec:
priorityClassName: overprovisioning
containers:
- name: reserve-resources
image: k8s.gcr.io/pause
resources:
requests:
#According to your cluster environment config
cpu: 4
memory: 8Gi
运行不执行任何操作的pod的想法起初看起来有点奇怪,但这种方法有一个很大的优势。我们可以肯定我们实际上可以运行其他pod,缓冲区不仅仅是通过某些算法计算生成,例如可选择的autoscaler。除了CPU和内存之外,还有其他资源可以用尽,比如我们使用Amazon VPC CNI插件时的IP地址。通过运行实际的pod,我们可以确定缓冲区实际上可以被其他业务的pod使用。
现在,这已经很好地工作但是如何扩展过度配置部署本身的大小呢?今天,集群可能包含10个工作节点,但在几个月内它可以增长到100个节点或更多节点。如果缓冲区空间与簇大小成比例增长,那将是理想的。事实证明,有一种解决方案正是名为cluster-proportional-autoscaler。您可以将其应用于K8s部署并指定coresPerReplica值。这意味着您的部署的一个副本弥补了整个群集的指定数量的核心。
举一个具体的例子:
如果您的部署使用4个CPU内核并且您希望确保10%的缓冲区,则需要将coresPerReplica设置为40.这意味着对于整个群集大小的每40个核心,将有一个Pod副本(4个核心)。
---
kind: ConfigMap
apiVersion: v1
metadata:
name: overprovisioning
namespace: kube-system
data:
linear: |-
{
"coresPerReplica": 40
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: overprovisioning-autoscaler
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app: overprovisioning-autoscaler
template:
metadata:
labels:
app: overprovisioning-autoscaler
spec:
containers:
- image: k8s.gcr.io/cluster-proportional-autoscaler-amd64:1.1.2
name: autoscaler
command:
- /cluster-proportional-autoscaler
- --namespace=kube-system
- --configmap=overprovisioning
- --target=deployment/overprovisioning
- --logtostderr=true
- --v=2
serviceAccountName: cluster-proportional-autoscaler
10%过度配置缓冲区(RBAC为简洁而省略)
https://github.com/kubernetes-incubator/cluster-proportional-autoscaler
https://wemp.app/posts/57abb519-8309-4373-b175-2620d54c33fe