Node Allocatable Resources
Allcatable
除了 kubelet、runtime 等 kubernetes 守护进程和用户 pod 之外,Kubernetes 节点通常还运行许多操作系统系统守护进程。 Kubernetes 假设节点中的所有可用计算资源(称为容量)都可用于用户 Pod。 实际上,系统守护进程使用大量资源,它们的可用性对于系统的稳定性至关重要。 为了解决这个问题,该提案引入了 Allocatable 的概念,它标识了用户 Pod 可用的计算资源量。 具体来说,kubelet 将提供一些旋钮来为 OS 系统守护进程和 kubernetes 守护进程保留资源
Kubernetes 的节点可以按照 Capacity调度。默认情况下 pod 能够使用节点全部可用容量。 但这样也存在问题,因为节点自己通常运行了不少驱动 OS 和 Kubernetes 的系统守护进程。 除非为这些系统守护进程留出资源,否则它们将与 pod 争夺资源并导致节点资源短缺问题。kubelet公开了一个名为node allocatable的特性,有助于为系统守护进程预留计算资源。 Kubernetes 推荐集群管理员按照每个节点上的工作负载密度配置node allocatable
Node Capacity
---------------------------
| kube-reserved |
|-------------------------|
| system-reserved |
|-------------------------|
| eviction-threshold |
|-------------------------|
| allocatable |
| (available for pods) |
---------------------------
| Node Capacity | 是指Kubernetes Node所有资源总量 |
|---|---|
| Kube-reserved | 是指为Kubernetes组件预留的资源量,如(Docker deamon, kubelet, kube proxy) |
| System-reserved | 是指为系统守护进程预留的资源量,如不受kubernetes 管理的进程、一般涵盖在/system 下的raw container的所有进程 |
| eviction-threshold | 是指节点的驱逐策略,根据kubelet启动时注入的参数(--eviction-hard等其它)设定的阈值,如果触发该阈值,kubelet会根据Kubenetes中的Qos的等级进行驱逐Pod |
| allocatable | 是指节点上的Pod所完全能够分配的资源,具体公式如:[Allocatable] = [Node Capacity] - [Kube-Reserved] - [System-Reserved] - [Hard-Eviction-Threshold] |
Kubernetes 节点上的 Allocatable 被定义为 pod 可用计算资源量。调度器不会超额申请 Allocatable。 目前支持 CPU, memory 和 ephemeral-storage 这几个参数
Kube-Reserved
kubereserved是为kubernetes组件预留资源而设立的参数配置,设置此参数必须需要重启kubelet(在kublet启动时通过cmd-line引入),因此kubelet正常运行时无法将其更改(不排除在以后的版本fix这一缺陷实现热加载)
--kube-reserved=cpu=500m,memory=500Mi
早期的功能仅支持CPU & MEM资源预留,但在以后kubernetes会相继支持更多的资源限制,比如本地存储 & IO 权重以实现kubernetes node的资源分配可靠性
System-Reserved
最初实现,systemreserved 与 kubereserved 的功能是一样的,同样都是资源预留功能,但是二者的意义是不同的,很明显kubereserved是为kubernetes组件实现资源预留;而systemreserved是为非kubernetes组件的系统进程而预留的资源值
Evictions Thresholds
为了提高节点的可靠性,每当节点内存或本地存储耗尽时,kubelet 都会驱逐 pod, evictions & node allocatable可共同有助于提高节点稳定性
自1.5版本开始,evictions是基于节点整体的capacity的使用情况,kubelet驱逐pod是基于Qos与自定义的eviction thresholds,更多的细节请参考文档
从1.6版本开始,默认情况下,节点上的所有pod使用 cgroups 强制执行 Allocatable,pod 不能超过 Allocatable的值,cgroups强制执行 meory & cpu resource.limits
- --kube-reserved
kubernetes 系统预留的资源配置,以一组 ResourceName=ResourceQuantity 格式表示。(例如:cpu=200m,memory=500Mi,ephemeral-storage=1Gi)。当前支持用于根文件系统的 CPU、内存(memory)和本地临时存储。请参阅 kubernetes.io/docs/user-g… 获取更多信息。(默认值为 none)(已弃用:在 --config 指定的配置文件中进行设置。有关更多信息,请参阅 kubernetes.io/docs/tasks/…
- --kube-reserved-cgroup
通过--kube-reserved参数配置为 kubernetes 组件其保留计算资源而设置的最顶层cgroup的绝对路径,与--kube-reserved相呼应,成对配置
Example /kube.slice
- --system-reserved
系统预留的资源配置,以一组 ”ResourceName=ResourceQuantity“ 的格式表示,(例如:cpu=200m,memory=500Mi,ephemeral-storage=1Gi)。目前仅支持 CPU 和内存(memory)的设置【官方原文,但是可以支持本地存储限额配置】 。请参考 kubernetes.io/docs/user-g… 获取更多信息。(默认值为 ”none“)(已弃用:在 --config 指定的配置文件中进行设置。有关更多信息,请参阅 kubernetes.io/docs/tasks/…
- --system-reserved-cgroup
简单来讲就是使用--system-reserved为非Kubernetes组件的系统进程而预留的一部分资源,就等于是为系统进程预留的资源配置,但是必须设置--system-reserved的最顶层的cgroup的绝对路径,(默认值为 ‘’ 空)(已弃用:在 --config 指定的配置文件中进行设置。有关更多信息,请参阅 kubernetes.io/docs/tasks/…
Example /system.slice
- --eviction-hard
强驱逐阈值,代表如果触发此值,立即驱逐节点的Pod,具体如何驱逐Pod则根本Kubernetes定义的Qos等级(例如:memory.available < 1Gi(内存可用值小于 1 G))设置。(默认值为 imagefs.available<15%,memory.available<100Mi,nodefs.available<10%,nodefs.inodesFree<5%)(已弃用:在 --config 指定的配置文件中进行设置。有关更多信息,请参阅 kubernetes.io/docs/tasks/…
配置过程
规则说明:如果--enforce-node-allocatable(enforceNodeAllocatable)指定systemReserved & kubeReserved值时,那么必须配置对应的cgroup参数(systemReservedCgroup & kubeReservedCgroup),相反如果enforceNodeAllocatable没有指定(systemReserved & kubeReserved)则不会生效,虽然从kubectl describe nodes看到的Allocatable的值减少,但是并没有真正限制Kubernetes组件及OS守护进程的资源限制,也就说OS守护进程及组件在资源请求分配时是无限的
解释说明:为什么Kubernetes官方默认并没有限制kubeReserved & systemReserved是因为它他们资源使用很难控制,如果设置不当后果很严重直接会影响整个平台或者是OS无法正常运行,将是致命性问题,但是Kubernetes保留了evictionHard默认驱逐策略
-
具体配置如下
"evictionHard": { "imagefs.available": "15%", "memory.available": "100Mi", "nodefs.available": "10%", "nodefs.inodesFree": "5%" }
-
验证参数设置关联性
开启kubelet日志等级模式,如下
<root@HK-K8S-WN4 /var/lib/kubelet># cat kubeadm-flags.env #KUBELET_KUBEADM_ARGS="--cgroup-driver=systemd --network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.2" # 上面--cgroup-driver=systemd 因为在新版本此方法虽然还可以使用,但是启动时会报错,需要在config.yaml配置,所以删除了此部分配置,具体配置如下文 KUBELET_KUBEADM_ARGS="--network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.2 --v=5"
配置kubeReserved(具体的配置在/var/lib/kubelet目录下,配置文件config.yaml安装之后默认生成的配置文件,当然kubelet启动的时候会指向该配置--config=/var/lib/kubelet/config.yaml)默认kubeadm配置文件/var下,由systemctl cat kubelet指向此文件
- 文件主要配置
# 只开启对kube-reserved资源预留 enforceNodeAllocatable: - pods - kube-reserved # - system-reserved # 以下仅仅是验证,是在以上enforceNodeAllocatable只开启kube-reserved时,但下文同时一配置kubeRserved & systemReserved,在kubelet启动时是否报错 systemReserved: cpu: 200m memory: 2000Mi kubeReserved: cpu: 200m memory: 500Mi kubeReservedCgroup: /kube.slice systemReservedCgroup: /system.slice cgroupDriver: systemd maxPods: 64
查询节点可分配资源
执行以下命令,查看节点的资源总量和可分配资源。
** **
kubectl describe node [NODE_NAME] | grep Allocatable -B 7 -A 6
预期输出:
** **
Capacity:
cpu: 4 #节点的CPU总核数。
ephemeral-storage: 123722704Ki #节点的临时存储总量,单位KiB。
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 7925980Ki #节点的内存总量,单位KiB。
pods: 64
Allocatable:
cpu: 3900m #节点可分配的CPU核数。
ephemeral-storage: 114022843818 #节点可分配的临时存储,单位Byte。
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 5824732Ki #节点可分配的内存,单位KiB。
pods: 64
计算节点可分配资源
可分配资源的计算公式:可分配资源(Allocatable) = 总资源(Capacity)-预留资源(Reserved)-驱逐阈值(Eviction-Threshold)
公式说明:
资源预留策略
节点的预留资源量通常要考虑以下因素:
- 由于规格较高的ECS节点通常会运行更多的Pod,为了保证节点的性能,ACK会为Kubernetes组件预留更多资源。
- 由于Windows节点需要使用额外的资源来运行Windows操作系统和Windows Server相关组件,Windows节点通常会比Linux节点需要更多的预留资源。更多信息,请参见创建Windows节点池。
预留资源包括给kube组件预留的资源(kubeReserved)和给system进程预留的资源(systemReserved)。kubeReserved和systemReserved各占预留资源的50%。例如,节点总CPU 1 Core,则预留CPU为100 milliCore,其中kubeReserved占用50 milliCore,systemReserved占用50 milliCore。修改资源预留的值,请参见自定义节点池kubelet配置。
ACK会根据CPU和内存所在的不同区间来计算预留的资源量,节点的总预留资源量等于各区间的预留资源量之和。
-
CPU:计算节点的总CPU预留量示意图如下。
以32核的节点为例,总的CPU预留量计算如下:
100+(32000-4000)×2.5%=800 milliCore
-
内存:计算节点的总内存预留量示意图如下所示。
以256 GiB内存的节点为例,总的内存预留量计算如下:
4×25%+(8-4)×20%+(16-8)×10%+(128-16)×6%+(256-128)×2%=11.88 GiB
ACK节点预留资源示例
| **** | **** |
|---|
| 节点总资源 | 预留资源 | ||
|---|---|---|---|
| CPU(单位:Core) | Memory(单位:GiB) | CPU(单位:milliCore) | Memory(单位:MiB) |
| 1 | 2 | 100 | 512 |
| 2 | 4 | 100 | 1024 |
| 4 | 8 | 100 | 1843 |
| 8 | 16 | 200 | 2662 |
| 16 | 32 | 400 | 3645 |
| 32 | 64 | 800 | 5611 |
| 64 | 128 | 1600 | 9543 |
| 128 | 256 | 2400 | 12164 |
| 256 | 512 | 3040 | 17407 |
| 512 | 1024 | 4320 | 27893 |
常见问题
如何查看节点总CPU和内存?
CPU
执行如下命令,查询节点总CPU。
cat /proc/cpuinfo | grep processor
预期输出:
processor : 0
processor : 1
processor : 2
processor : 3
内存
执行如下命令,查询节点总内存。
cat /proc/meminfo | grep MemTotal
预期输出:
MemTotal: 7660952 kB
参考文献: