涉及参考文档:
简介信息:
Kubernetes 的节点可以按照 Capacity 调度。默认情况下 pod 能够使用节点全部可用容量。
这是个问题,因为节点自己通常运行了不少驱动 OS 和 Kubernetes 的系统守护进程。 除非为这些系统守护进程留出资源,否则它们将与 pod 争夺资源并导致节点资源短缺问题。
kubelet 公开了一个名为Node Allocatable 的特性
,有助于为系统守护进程预留计算资源
。 Kubernetes 推荐 集群管理员按照每个节点上的工作负载密度配置 Node Allocatable。
一、节点可分配示意图
- –kube-reserved = Kube 预留值
- –system-reserved = 系统预留值
- ephemeral-storage = kubelet eviction的阈值设定
Kubernetes 节点上的 Allocatable 被定义为 pod 可用计算资源量。 调度器不会超额申请 Allocatable。
目前支持 CPU, memory 和 ephemeral-storage(本地磁盘存储空间) 这几个参数。
二、配置 cgroup 驱动
kubelet 支持在主机上使用 cgroup 驱动操作 cgroup 层次结构。 驱动通过 --cgroup-driver 标志配置。
cgroupfs 是默认的驱动
,在主机上直接操作 cgroup 文件系统以对 cgroup 沙箱进行管理。systemd 是可选的驱动
,使用 init 系统支持的资源的瞬时切片管理 cgroup 沙箱。
操作员可能需要选择一个特定的 cgroup 驱动 来保证系统正常运行。例如,如果操作员使用 docker 运行时提供的 systemd cgroup 驱动时, 必须配置 kubelet 使用 systemd cgroup 驱动。
1、 查看docker 运行时提供 cgroup 驱动
docker info |grep Cgroup
2、配置 kubelet cgroup 驱动
cat /var/lib/kubelet/kubeadm-flags.env |grep "cgroup-driver"
云上默认docker cgroup 驱动为 systemd ,所以 kubelet 得使用 systemd cgroup 驱动。
使用kubeadm 自搭建 docker cgroup 驱动为 cgroupfs ,所以 kubelet 得使用 cgroupfs cgroup 驱动。
三、实施节点可分配约束
- Kubelet 标志: --enforce-node-allocatable=pods[,][system-reserved][,][kube-reserved]
调度器将 Allocatable 视为 Pod 可用的 capacity(资源容量)。
kubelet 默认对 Pod 执行 Allocatable 约束。 无论何时,如果所有 Pod 的总用量超过了 Allocatable,驱逐 Pod 的措施将被执行 驱逐策略
可通过设置 kubelet --enforce-node-allocatable 标志值为 pods
控制
要想执行 kube-reserved 或者 system-reserved 约束
, 需要 对应设置 --kube-reserved-cgroup 或者 --system-reserved-cgroup
四、Kube 预留值
- Kubelet 标志: --kube-reserved=[cpu=100m][,][memory=100Mi][,][ephemeral-storage=1Gi]
- Kubelet 标志: --kube-reserved-cgroup=
1、要选择性地对 kubernetes 系统守护进程上执行 kube-reserved 保护,需要把 kubelet 的 --kube-reserved-cgroup 标志的值设置为 kube 守护进程的父控制组
推荐将 kubernetes 系统守护进程放置于顶级控制组之下(例如 systemd 机器上的 runtime.slice)
。 理想情况下每个系统守护进程都应该在其自己的子控制组中运行。 请参考 这篇文档, 进一步了解关于推荐控制组层次结构的细节
2、kube-reserved 用来给诸如kubelet、容器运行时、节点问题监测器等 kubernetes 系统守护进程记述其资源预留值
。 该配置并非用来给以 Pod 形式运行的系统守护进程保留资源。
3、请注意,如果 --kube-reserved-cgroup 不存在,Kubelet 将 不会 创建它
。 如果指定了一个无效的 cgroup,Kubelet 将会失败
cat kubeadm-flags.env
KUBELET_KUBEADM_ARGS="--cgroup-driver=cgroupfs --network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.2 \
--enforce-node-allocatable=pods,kube-reserved \
--kube-reserved=cpu=300m,memory=100Mi"
#--kube-reserved-cgroup=/system.slice/kubelet.service \
重启服务:
systemctl restart kubelet.service && ps -ef |grep kubelet
五、系统预留值
- Kubelet 标志: --system-reserved=[cpu=100m][,][memory=100Mi][,][ephemeral-storage=1Gi][,][pid=1000]
- Kubelet 标志: --system-reserved-cgroup=
system-reserved 用于为诸如sshd、udev 等系统守护进程记述其资源预留值。
system-reserved 也应该为 kernel 预留 内存,因为目前 kernel 使用的内存并不记在 Kubernetes 的 Pod 上。 同时还推荐为用户登录会话预留资源(systemd 体系中的 user.slice)
kubelet 的--system-reserved-cgroup 标志值为 OS 系统守护进程的父级控制组
。 OS 系统守护进程放在一个顶级控制组之下(例如systemd 机器上的 system.slice)
。
如果 --system-reserved-cgroup 不存在,Kubelet 不会 创建它。
如果指定了无效的 cgroup,Kubelet 将会失败。 如上测试 Kube 预留值
六、驱逐阈值
- Kubelet 标志: --eviction-hard=[memory.available<500Mi]
为了防止(或减少可能性)系统内存不足,kubelet 提供了 资源不足管理。驱逐操作只支持 memory 和 ephemeral-storage。
通过 --eviction-hard 标志预留一些内存后,当节点上的可用内存降至保留值以下时, kubelet 将尝试驱逐 Pod。如果节点上不存在系统守护进程,Pod 将不能使用超过 capacity-eviction-hard 所 指定的资源量。因此,为驱逐而预留的资源对 Pod 是不可用的。
详细请阅读文章 Kubernetes 资源不足时的处理方式
七、测试案例
这是一个用于说明节点可分配(Node Allocatable)计算方式的示例:
节点拥有 32Gi memeory,16 CPU 和 100Gi Storage 资源
- --kube-reserved 被设置为 cpu=1,memory=2Gi,ephemeral-storage=1Gi
- --system-reserved 被设置为 cpu=500m,memory=1Gi,ephemeral-storage=1Gi
- --eviction-hard 被设置为 memory.available<500Mi,nodefs.available<10%
在这个场景下,Allocatable 将会是 14.5 CPUs、28.5Gi 内存以及 88Gi 本地存储
。 调度器保证这个节点上的所有 Pod 的内存 requests 总量不超过 28.5Gi, 存储不超过 88Gi。 当 Pod 的内存使用总量超过 28.5Gi 或者磁盘使用总量超过 88Gi 时, kubelet 将会驱逐它们。 如果节点上的所有进程都尽可能多地使用 CPU,则 Pod 加起来不能使用超过 14.5 CPUs 的资源。
当没有执行 kube-reserved 和/或 system-reserved 策略且系统守护进程 使用量超过其预留时,如果节点内存用量高于 31.5Gi 或存储大于 90Gi, kubelet 将会驱逐 Pod
vim /var/lib/kubelet/kubeadm-flags.env
KUBELET_KUBEADM_ARGS="--cgroup-driver=cgroupfs --network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.2 \
--enforce-node-allocatable=pods,kube-reserved \
--kube-reserved-cgroup=/system.slice/kubelet.service \
--system-reserved-cgroup=/system.slice \
--kube-reserved=cpu=1,memory=2Gi,ephemeral-storage=1Gi \
--system-reserved=cpu=500m,memory=1Gi,ephemeral-storage=1Gi \
--eviction-hard=memory.available<500Mi,nodefs.available<10%"
ps -ef |grep kubelet && ps -ef |grep kubelet