Kubernetes为系统守护进程预留计算资源
参考文档:http://arthurchiao.art/blog/k8s-cgroup-zh/
--cgroups-per-qos
默认开启。开启这个参数后,kubelet 会将所有的 pod 创建在 kubelet 管理的 cgroup 层次结构下(这样才有了限制所有 Pod 使用资源总量的基础)。要想启用 Node Allocatable 特性,这个参数必须开启
Kubernetes 会将所有 pod 分成三种 QoS,优先级从高到低:Guaranteed > Burstable > BestEffort。 三种 QoS 是根据 requests/limits 的大小关系来定义的:
- Guaranteed: requests == limits, requests != 0, 即 正常需求 == 最大需求,换言之 spec 要求的资源量必须得到保证,少一点都不行;
- Burstable: requests < limits, requests != 0, 即 正常需求 < 最大需求,资源使用量可以有一定弹性空间;
-
BestEffort: request == limits == 0, 创建 pod 时不指定 requests/limits 就等同于设置为 0,kubelet 对这种 pod 将尽力而为;有好处也有坏处:
- 好处:node 的资源充足时,这种 pod 能使用的资源量没有限制;
- 坏处:这种 pod 的 QoS 优先级最低,当 node 资源不足时,最先被驱逐
--cgroup-driver
指定 kubelet 使用的 cgroup driver。默认为 cgroupfs,还可以是 systemd,但是这个值需要和 docker runtime 所使用的 cgroup driver 保持一致
--cgroup-root
可选。指定给 pod 使用的根 cgroup,容器运行时会尽量将 pod 的资源限制在这个根 cgroup 下面。默认为空,即使用容器运行时作为根 cgroup
--enforce-node-allocatable
指定 kubelet 为哪些进程做硬限制,可选的值有:pods, kube-reserved, system-reserve
这个参数开启并指定 pods 后 kubelet 会为所有 pod 的总 cgroup 做资源限制(通过 cgroup 中的 kubepods.limit_in_bytes)
调度器可以限制节点上所有创建的 pod 的 request 量不会超过 allocatable,已可以保证不会有超过 allocatable 的 pod 跑在该节点上,这里还要用 cgroup 再做硬限制的意义是:pod 使用的资源是可以大于 request 的,所以,虽然在调度阶段限制了所有 request 的总量不会超过 allocatable 的值,但不能保证真正运行起来后所有 pod 的资源使用量不会超过 allocatable;而用 cgroup 做了硬限制后,当所有 pod 使用量达到 allocatable 后,会有 pod 被 OOM killer 机制杀掉,以保证实际使用量不会超过allocatable
--eviction-hard
设置进行 pod 驱逐的阈值,这个参数只支持内存和磁盘。通过 --eviction-hard 标志预留一些内存后,当节点上的可用内存降至保留值以下时,kubelet 将会对 pod 进行驱逐
Kube 预留值:
--kube-reserved-cgroup=
这个参数用来指定 k8s 系统组件所使用的 cgroup。注意,这里指定的 cgroup 及其子系统需要预先创建好,kubelet 并不会为你自动创建好
--kube-reserved=[cpu=100m][,][memory=100Mi][,][ephemeral-storage=1Gi][,][pid=1000]
kube-reserved 用来给诸如 kubelet、容器运行时、节点问题监测器等 Kubernetes 系统守护进程记述其资源预留值。 该配置并非用来给以 Pod 形式运行的系统守护进程预留资源
除了 cpu、内存 和 ephemeral-storage 之外,pid 可用来指定为 Kubernetes 系统守护进程预留指定数量的进程 ID
系统预留值:
--system-reserved-cgroup=
这个参数用来指定系统守护进程所使用的cgroup。注意,这里指定的cgroup及其子系统需要预先创建好,kubelet并不会为你自动创建好
--system-reserved=[cpu=100m][,][memory=100Mi][,][ephemeral-storage=1Gi][,][pid=1000]
system-reserved 用于为诸如 sshd、udev 等系统守护进程记述其资源预留值。 system-reserved 也应该为 kernel 预留 内存,因为目前 kernel 使用的内存并不记在 Kubernetes 的 Pod 上。 同时还推荐为用户登录会话预留资源(systemd 体系中的 user.slice)
例子一:只限制 pod 资源总量
将以下内容添加到 kubelet 的启动参数中:
--enforce-node-allocatable=pods \
--cgroup-driver=cgroupfs \
--kube-reserved=cpu=1,memory=1Gi,ephemeral-storage=10Gi \
--system-reserved=cpu=1,memory=2Gi,ephemeral-storage=10Gi \
--eviction-hard=memory.available<500Mi,nodefs.available<10%
按以上设置:
-
-
节点上可供 Pod 所 request 的资源总和 allocatable 计算如下:
allocatable = capacity - kube-reserved - system-reserved - eviction-hard
- 节点上所有 Pod 实际使用的资源总和不会超过:capacity - kube-reserved - system-reserved
-
例子二:同时限制pod、k8s系统组件
修改 kubelet 配置:
方式一:将以下内容添加到 kubelet 的启动参数中:
--enforce-node-allocatable=pods,kube-reserved \
--cgroup-driver=cgroupfs \
--kube-reserved=cpu=500,memory=512Mi,ephemeral-storage=10Gi \
--kube-reserved-cgroup=/kubelet.slice
方式二:修改 kubelet 配置文件(默认配置文件 /var/lib/kubelet/config.yaml)
cgroupDriver: systemd
cgroupsPerQOS: true
enforceNodeAllocatable:
- pods
- kube-reserved
kubeReserved:
cpu: 500m
memory: 512Mi
ephemeral-storage: 10Gi
kubeReservedCgroup: /kubelet.slice
重启 kubelet 服务:
systemctl restart kubelet
需要注意,如果 --kube-reserved-cgroup 对应的路径不存在,Kubelet 不会创建它,启动 Kubelet 将会失败
报错内容:缺少对应的 cgroup 路径
Dec 15 14:41:14 instance-lx0qsle2 kubelet[75445]: E1215 14:41:14.299424 75445 kubelet.go:1511] "Failed to start ContainerManager" err="Failed to enforce Kube Reserved Cgroup Limits on \"/kubelet.slice\": cgroup [\"kubelet\"] has some missing paths: /sys/fs/cgroup/hugetlb/kubelet.slice, /sys/fs/cgroup/cpuset/kubelet.slice, /sys/fs/cgroup/cpu,cpuacct/kubelet.slice, /sys/fs/cgroup/cpu,cpuacct/kubelet.slice, /sys/fs/cgroup/systemd/kubelet.slice, /sys/fs/cgroup/pids/kubelet.slice, /sys/fs/cgroup/memory/kubelet.slice"
根据提示创建对应的 cgroup 路径:
mkdir /sys/fs/cgroup/hugetlb/kubelet.slice
mkdir /sys/fs/cgroup/cpuset/kubelet.slice
mkdir /sys/fs/cgroup/cpu,cpuacct/kubelet.slice
mkdir /sys/fs/cgroup/systemd/kubelet.slice
mkdir /sys/fs/cgroup/pids/kubelet.slice
mkdir /sys/fs/cgroup/memory/kubelet.slice
注意:systemd 的 cgroup 驱动对应的 cgroup 名称是以 .slice 结尾的,比如如果你把 cgroup 名称配置成 kubelet.service,那么对应的创建的 cgroup 名称应该为 kubelet.service.slice。如果你配置的是 cgroupfs 的驱动,则用配置的值即可。无论哪种方式,通过查看错误日志都是排查问题最好的方式
再次重启 kubelet 依然报错:
Dec 15 14:44:01 instance-lx0qsle2 kubelet[76089]: I1215 14:44:01.285110 76089 node_container_manager_linux.go:125] "Enforcing kube reserved on cgroup" cgroupName="/kubelet.slice" limits={"cpu":"500m","ephemeral-storage":"10Gi","memory":"512Mi"}
Dec 15 14:44:01 instance-lx0qsle2 kubelet[76089]: E1215 14:44:01.285971 76089 kubelet.go:1511] "Failed to start ContainerManager" err="Failed to enforce Kube Reserved Cgroup Limits on \"/kubelet.slice\": Unit kubelet.slice is not loaded."
启动 kubelet.slice
systemctl start kubelet.slice
再次重启 kubelet 成功
查看限制:
cat /sys/fs/cgroup/memory/kubelet.slice/memory.limit_in_bytes
536870912 # 内存限制 512Mi
查看节点详细描述:
kubectl describe node 10.100.0.98
Node Allocatable Resource = Node Capacity - Kube-reserved
例子三:同时限制pod、k8s系统组件、linux系统守护进程资源
修改 kubelet 配置:
方式一:将以下内容添加到 kubelet 的启动参数中:
--enforce-node-allocatable=pods,kube-reserved,system-reserved \
--cgroup-driver=cgroupfs \
--kube-reserved=cpu=500m,memory=512Mi,ephemeral-storage=10Gi \
--kube-reserved-cgroup=/kubelet.slice \
--system-reserved cpu=500m,memory=512Mi,ephemeral-storage=10Gi \
--system-reserved-cgroup=/system.slice \
--eviction-hard=memory.available<500Mi,nodefs.available<10%
方式二:修改 kubelet 配置文件(默认配置文件 /var/lib/kubelet/config.yaml)
cgroupDriver: systemd
cgroupsPerQOS: true
enforceNodeAllocatable:
- pods
- kube-reserved
- system-reserved
kubeReserved:
cpu: 500m
memory: 512Mi
ephemeral-storage: 10Gi
kubeReservedCgroup: /kubelet.slice
systemReserved:
cpu: 500m
memory: 512Mi
ephemeral-storage: 10Gi
systemReservedCgroup: /system.slice
evictionHard:
memory.available: 500Mi
nodefs.available: 10%
重启 kubelet 服务:
systemctl restart kubelet
报错信息:缺少对应的 cgroup 路径
Dec 15 15:45:23 instance-lx0qsle2 kubelet[22282]: I1215 15:45:23.212655 22282 node_container_manager_linux.go:116] "Enforcing system reserved on cgroup" cgroupName="/system.slice" limits={"cpu":"500m","ephemeral-storage":"10Gi","memory":"512Mi"}
Dec 15 15:45:23 instance-lx0qsle2 kubelet[22282]: E1215 15:45:23.212740 22282 kubelet.go:1511] "Failed to start ContainerManager" err="Failed to enforce System Reserved Cgroup Limits on \"/system.slice\": cgroup [\"system\"] has some missing paths: /sys/fs/cgroup/hugetlb/system.slice"
创建缺少的 cgroup 路径:
mkdir /sys/fs/cgroup/hugetlb/system.slice
再次重启 kubelet 服务成功:
systemct restart kubelet
查看 system.slice 状态:正常运行
systemctl status system.slice
查看限制:
cat /sys/fs/cgroup/memory/system.slice/memory.limit_in_bytes
536870912 # 内存限制 512Mi
查看节点详细描述:
kubectl describe node 10.100.0.98
-
节点上可供 Pod 所 request 的资源总和 allocatable 计算如下:
allocatable = capacity - kube-reserved - system-reserved - eviction-hard
-
节点上所有 Pod 实际使用的资源总和不会超过:capacity - kube-reserved - system-reserved