为系统守护进程预留计算资源
Kubernetes 节点可以被调度至 容量
。默认情况下,Pod 可以消耗节点上的所有可用容量。这是一个问题,因为节点通常会运行相当多的系统守护进程,这些进程为操作系统和 Kubernetes 本身提供支持。除非为这些系统守护进程预留资源,否则 Pod 和系统守护进程会争夺资源,并导致节点上的资源耗尽问题。
kubelet
公开了一个名为“节点可分配资源”的功能,该功能有助于为系统守护进程保留计算资源。 Kubernetes 建议集群管理员根据每个节点上的工作负载密度配置“节点可分配资源”。
开始之前
你需要有一个 Kubernetes 集群,并且必须配置 kubectl 命令行工具与你的集群通信。建议在至少两个不充当控制平面主机的节点上运行此教程。如果你还没有集群,可以使用 minikube 创建一个集群,或者可以使用这些 Kubernetes 游乐场之一
你可以使用 kubelet 配置文件 配置以下 kubelet 配置设置。
节点可分配资源
Kubernetes 节点上的“可分配资源”定义为可用于 Pod 的计算资源量。调度器不会过度订阅“可分配资源”。目前支持“CPU”、“内存”和“临时存储”。
节点可分配资源作为 API 中 v1.Node
对象的一部分以及 CLI 中 kubectl describe node
的一部分公开。
可以在 kubelet
中为两类系统守护进程保留资源。
启用 QoS 和 Pod 级 cgroup
为了在节点上正确强制执行节点可分配资源约束,你必须通过 cgroupsPerQOS
设置启用新的 cgroup 层次结构。默认情况下启用此设置。启用后,kubelet
会将所有最终用户 Pod 置于由 kubelet
管理的 cgroup 层次结构下。
配置 cgroup 驱动程序
kubelet
支持使用 cgroup 驱动程序操作主机上的 cgroup 层次结构。该驱动程序通过 cgroupDriver
设置配置。
支持的值如下
cgroupfs
是默认驱动程序,它直接操作主机上的 cgroup 文件系统以管理 cgroup 沙箱。systemd
是一种替代驱动程序,它使用由该初始化系统支持的资源的瞬态切片来管理 cgroup 沙箱。
根据关联的容器运行时的配置,操作员可能必须选择特定的 cgroup 驱动程序以确保正确的系统行为。例如,如果操作员使用 containerd
运行时提供的 systemd
cgroup 驱动程序,则必须将 kubelet
配置为使用 systemd
cgroup 驱动程序。
Kube 保留资源
- KubeletConfiguration 设置:
kubeReserved: {}
。示例值{cpu: 100m, memory: 100Mi, ephemeral-storage: 1Gi, pid=1000}
- KubeletConfiguration 设置:
kubeReservedCgroup: ""
kubeReserved
旨在捕获 kubernetes 系统守护进程(如 kubelet
、容器运行时
等)的资源保留。它不旨在为作为 Pod 运行的系统守护进程保留资源。 kubeReserved
通常是节点上 Pod 密度
的函数。
除了 cpu
、memory
和 ephemeral-storage
之外,还可以指定 pid
为 kubernetes 系统守护进程保留指定数量的进程 ID。
要选择性地在 kubernetes 系统守护进程上强制执行 kubeReserved
,请将 Kube 守护进程的父控制组指定为 kubeReservedCgroup
设置的值,并将 kube-reserved
添加到 enforceNodeAllocatable
。
建议将 kubernetes 系统守护进程放置在顶层控制组下(例如,在 systemd 机器上为 runtime.slice
)。每个系统守护进程最好在其自己的子控制组中运行。有关推荐的控制组层次结构的更多详细信息,请参阅 设计提案。
请注意,如果 kubeReservedCgroup
不存在,Kubelet 不会 创建它。如果指定了无效的 cgroup,kubelet 将无法启动。对于 systemd
cgroup 驱动程序,你应该遵循定义的 cgroup 名称的特定模式:名称应为你为 kubeReservedCgroup
设置的值,并附加 .slice
。
系统保留资源
- KubeletConfiguration 设置:
systemReserved: {}
。示例值{cpu: 100m, memory: 100Mi, ephemeral-storage: 1Gi, pid=1000}
- KubeletConfiguration 设置:
systemReservedCgroup: ""
systemReserved
旨在捕获 OS 系统守护进程(如 sshd
、udev
等)的资源保留。systemReserved
还应为 kernel
保留 memory
,因为目前 Kubernetes 中 kernel
内存不计入 Pod。还建议为用户登录会话保留资源(systemd 世界中的 user.slice
)。
除了 cpu
、memory
和 ephemeral-storage
之外,还可以指定 pid
为 OS 系统守护进程保留指定数量的进程 ID。
要选择性地在系统守护进程上强制执行 systemReserved
,请将 OS 系统守护进程的父控制组指定为 systemReservedCgroup
设置的值,并将 system-reserved
添加到 enforceNodeAllocatable
。
建议将 OS 系统守护进程放置在顶层控制组下(例如,在 systemd 机器上为 system.slice
)。
请注意,如果 systemReservedCgroup
不存在,kubelet
不会 创建它。如果指定了无效的 cgroup,kubelet
将会失败。对于 systemd
cgroup 驱动程序,你应该遵循定义的 cgroup 名称的特定模式:名称应为你为 systemReservedCgroup
设置的值,并附加 .slice
。
显式保留的 CPU 列表
Kubernetes v1.17 [稳定]
KubeletConfiguration 设置:reservedSystemCPUs:
。示例值 0-3
reservedSystemCPUs
旨在为 OS 系统守护进程和 kubernetes 系统守护进程定义显式的 CPU 集。reservedSystemCPUs
适用于不打算在 cpuset 资源方面为 OS 系统守护进程和 kubernetes 系统守护进程定义单独的顶层 cgroup 的系统。如果 Kubelet 没有 kubeReservedCgroup
和 systemReservedCgroup
,则由 reservedSystemCPUs
提供的显式 cpuset 将优先于由 kubeReservedCgroup
和 systemReservedCgroup
选项定义的 CPU。
此选项专门为 Telco/NFV 用例设计,其中不受控制的中断/计时器可能会影响工作负载性能。你可以使用此选项为系统/kubernetes 守护进程以及中断/计时器定义显式的 cpuset,以便系统上的其余 CPU 可以专门用于工作负载,从而减少不受控制的中断/计时器的影响。要将系统守护进程、kubernetes 守护进程和中断/计时器移动到此选项定义的显式 cpuset,应使用 Kubernetes 之外的其他机制。例如:在 Centos 中,你可以使用 tuned 工具集执行此操作。
驱逐阈值
KubeletConfiguration 设置:evictionHard: {memory.available: "100Mi", nodefs.available: "10%", nodefs.inodesFree: "5%", imagefs.available: "15%"}
。示例值: {memory.available: "<500Mi"}
节点级别的内存压力会导致系统OOM(内存溢出),这会影响整个节点及其上运行的所有Pod。节点可能会暂时离线,直到内存被回收。为了避免(或降低)系统OOM的发生概率,kubelet提供了资源耗尽管理。驱逐操作仅支持 memory
和 ephemeral-storage
。通过 evictionHard
设置预留一些内存,当节点上的可用内存低于预留值时,kubelet
会尝试驱逐Pod。理论上,如果节点上不存在系统守护进程,则Pod使用的内存不会超过 capacity - eviction-hard
。因此,为驱逐预留的资源不可供Pod使用。
强制执行节点可分配资源
KubeletConfiguration 设置: enforceNodeAllocatable: [pods]
。示例值:[pods,system-reserved,kube-reserved]
调度器将“Allocatable”(可分配资源)视为Pod可用的capacity
(容量)。
默认情况下,kubelet
会在 Pod 之间强制执行“Allocatable”。当所有Pod的总使用量超过“Allocatable”时,将通过驱逐 Pod 来执行强制执行。有关驱逐策略的更多详细信息,请参阅节点压力驱逐页面。此强制执行由在 KubeletConfiguration 设置 enforceNodeAllocatable
中指定 pods
值来控制。
或者,可以通过在同一设置中指定 kube-reserved
和 system-reserved
值,使 kubelet
强制执行 kubeReserved
和 systemReserved
。请注意,要强制执行 kubeReserved
或 systemReserved
,需要分别指定 kubeReservedCgroup
或 systemReservedCgroup
。
通用指南
系统守护进程预计应与Guaranteed(保证)QoS 等级的 Pod类似对待。系统守护进程可以在其边界控制组内突发,此行为需要作为 Kubernetes 部署的一部分进行管理。例如,kubelet
应该有自己的控制组,并与容器运行时共享 kubeReserved
资源。但是,如果强制执行了 kubeReserved
,则 Kubelet 不能突发并耗尽所有可用的节点资源。
在强制执行 systemReserved
预留时要格外小心,因为它可能导致关键的系统服务 CPU 不足、被 OOM 杀死或无法在节点上 fork。建议仅当用户对其节点进行了详尽的分析,以得出精确的估计,并且有信心在组中的任何进程被 OOM 杀死时恢复时,才强制执行 systemReserved
。
- 首先,在
pods
上强制执行“Allocatable”。 - 一旦建立了足够的监控和警报机制来跟踪 kube 系统守护进程,请尝试根据使用情况的启发式方法强制执行
kubeReserved
。 - 如果绝对必要,请随着时间的推移强制执行
systemReserved
。
随着越来越多的功能被添加,kube 系统守护进程的资源需求可能会随着时间的推移而增长。随着时间的推移,Kubernetes 项目将尝试降低节点系统守护进程的利用率,但这目前不是优先事项。因此,预计未来版本中的 Allocatable
容量将下降。
示例场景
这是一个说明节点可分配资源计算的示例
- 节点有
32Gi
的memory
、16 个 CPU
和100Gi
的Storage
kubeReserved
设置为{cpu: 1000m, memory: 2Gi, ephemeral-storage: 1Gi}
systemReserved
设置为{cpu: 500m, memory: 1Gi, ephemeral-storage: 1Gi}
evictionHard
设置为{memory.available: "<500Mi", nodefs.available: "<10%"}
在这种情况下,“Allocatable”将为 14.5 个 CPU、28.5Gi 的内存和 88Gi
的本地存储。调度器确保此节点上所有 Pod 的总内存 requests
不超过 28.5Gi,并且存储不超过 88Gi。当 Pod 的总内存使用量超过 28.5Gi,或者总磁盘使用量超过 88Gi 时,Kubelet 会驱逐 Pod。如果节点上的所有进程都尽可能多地消耗 CPU,则 Pod 一起不能消耗超过 14.5 个 CPU。
如果未强制执行 kubeReserved
和/或 systemReserved
,并且系统守护进程超出其预留,则当节点总内存使用量高于 31.5Gi 或 storage
大于 90Gi 时,kubelet
会驱逐 Pod。