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