为系统守护进程预留计算资源

Kubernetes 节点可以调度到 Capacity。默认情况下,Pod 可以消耗节点上所有可用的容量。这是一个问题,因为节点通常运行相当多的系统守护进程,这些守护进程为操作系统和 Kubernetes 本身提供支持。除非为这些系统守护进程预留资源,否则 Pod 和系统守护进程会争夺资源,并导致节点上的资源饥饿问题。

kubelet 公开了名为“节点可分配”的功能,该功能有助于为系统守护进程预留计算资源。Kubernetes 建议集群管理员根据每个节点上的工作负载密度配置“节点可分配”。

开始之前

您需要拥有一个 Kubernetes 集群,并且 kubectl 命令行工具必须配置为与您的集群通信。建议在至少有两个节点(不充当控制平面主机)的集群上运行本教程。如果您还没有集群,可以使用 minikube 创建一个集群,或者可以使用以下 Kubernetes 游乐场之一

您可以使用 kubelet 配置设置 配置以下 kubelet 配置文件。

节点可分配

node capacity

Kubernetes 节点上的“可分配”定义为可用于 Pod 的计算资源量。调度程序不会过度订阅“可分配”。目前支持“CPU”、“内存”和“临时存储”。

节点可分配作为 API 中的 v1.Node 对象的一部分以及 CLI 中的 kubectl describe node 的一部分公开。

可以在 kubelet 中为两类系统守护进程预留资源。

启用 QoS 和 Pod 级 cgroups

为了在节点上正确执行节点可分配约束,您必须通过 cgroupsPerQOS 设置启用新的 cgroup 层次结构。此设置默认情况下处于启用状态。启用后,kubelet 将在 kubelet 管理的 cgroup 层次结构下为所有最终用户 Pod 设置父级。

配置 cgroup 驱动程序

kubelet 支持使用 cgroup 驱动程序来操作主机上的 cgroup 层次结构。驱动程序通过 cgroupDriver 设置进行配置。

支持的值如下

  • cgroupfs 是默认驱动程序,它直接操作主机上的 cgroup 文件系统以管理 cgroup 沙箱。
  • systemd 是一个替代驱动程序,它使用瞬态切片来管理 cgroup 沙箱,这些切片用于该 init 系统支持的资源。

根据关联的容器运行时的配置,操作员可能必须选择特定的 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 密度 的函数。

除了 cpumemoryephemeral-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 用于捕获为操作系统系统守护进程(如 sshdudev 等)预留的资源。systemReserved 应该为 kernel 预留 memory,因为目前 Kubernetes 中没有将 kernel 内存计入 Pod。还建议为用户登录会话预留资源(systemd 世界中的 user.slice)。

除了 cpumemoryephemeral-storage 之外,还可以指定 pid 来为操作系统系统守护进程预留指定数量的进程 ID。

要选择性地对系统守护进程强制执行 systemReserved,请将操作系统系统守护进程的父控制组指定为 systemReservedCgroup 设置的值,并 system-reserved 添加到 enforceNodeAllocatable

建议将操作系统系统守护进程放在顶级控制组(例如,systemd 机器上的 system.slice)下。

请注意,如果 systemReservedCgroup 不存在,kubelet 不会创建它。如果指定了无效的 cgroup,kubelet 将失败。使用 systemd cgroup 驱动程序,您应该遵循定义的 cgroup 名称的特定模式:名称应该是您为 systemReservedCgroup 设置的值,并在后面附加 .slice

显式预留 CPU 列表

功能状态: Kubernetes v1.17 [稳定]

KubeletConfiguration 设置reservedSystemCPUs:。示例值 0-3

reservedSystemCPUs 用于为操作系统系统守护进程和 Kubernetes 系统守护进程定义显式 CPU 集。reservedSystemCPUs 用于不打算为操作系统系统守护进程和 Kubernetes 系统守护进程定义单独的顶级 cgroup 的系统,这些 cgroup 与 cpuset 资源有关。如果 Kubelet 没有 kubeReservedCgroupsystemReservedCgroup,则 reservedSystemCPUs 提供的显式 cpuset 将优先于 kubeReservedCgroupsystemReservedCgroup 选项定义的 CPU。

此选项专门针对电信/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 提供了 资源不足 管理。驱逐仅支持 memoryephemeral-storage。通过 evictionHard 设置预留一些内存,kubelet 会尝试在节点上的内存可用性低于预留值时驱逐 Pod。假设节点上不存在系统守护进程,Pod 无法使用超过 capacity - eviction-hard 的资源。因此,为驱逐预留的资源不可用于 Pod。

强制执行节点可分配

KubeletConfiguration 设置enforceNodeAllocatable: [pods]。示例值:[pods,system-reserved,kube-reserved]

调度程序将“可分配”视为 Pod 可用的 capacity

kubelet 默认情况下通过 Pod 强制执行“可分配”。强制执行是通过在所有 Pod 上的总体使用量超过“可分配”时驱逐 Pod 来执行的。有关驱逐策略的更多详细信息,请参阅 节点压力驱逐 页面。此强制执行由将 pods 值指定给 KubeletConfiguration 设置 enforceNodeAllocatable 来控制。

可以选择性地使 kubelet 强制执行 kubeReservedsystemReserved,方法是在同一设置中指定 kube-reservedsystem-reserved 值。请注意,要强制执行 kubeReservedsystemReserved,需要分别指定 kubeReservedCgroupsystemReservedCgroup

一般指南

系统守护进程预计将与 保证型 Pod 相似。系统守护进程可以在其边界控制组内突发,并且此行为需要作为 Kubernetes 部署的一部分进行管理。例如,kubelet 应该有自己的控制组,并与容器运行时共享 kubeReserved 资源。但是,如果强制执行 kubeReserved,Kubelet 无法突发并使用所有可用的节点资源。

在强制执行 systemReserved 预留时要格外小心,因为它会导致关键系统服务出现 CPU 饥饿、OOM 杀死或无法在节点上 fork。建议只有在用户对节点进行了全面分析,得出了精确的估计,并确信能够在该组中的任何进程被 oom 杀死时恢复的情况下,才强制执行 systemReserved

  • 首先,在 pods 上强制执行 'Allocatable'。
  • 一旦到位了足够的监控和警报来跟踪 kube 系统守护进程,尝试根据使用情况启发式地强制执行 kubeReserved
  • 如果绝对必要,请随着时间的推移强制执行 systemReserved

随着越来越多的功能被添加,kube 系统守护进程的资源需求可能会随着时间的推移而增长。随着时间的推移,kubernetes 项目将尝试降低节点系统守护进程的利用率,但这目前不是优先事项。因此,预计在未来的版本中 Allocatable 容量会下降。

示例场景

以下是一个说明节点 Allocatable 计算的示例

  • 节点拥有 32Gimemory16 CPUs100GiStorage
  • 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。

上次修改时间:2024 年 6 月 4 日凌晨 3:39 PST:改进“为系统守护进程保留计算资源”文档 (#45771) (bc35539293)