手工制作网站,请大学生做网站,app网站建设开发,百度灰色关键词排名KUBERNETES资源管理之–资源预留 Kubernetes 的节点可以按照 Capacity 调度。node节点本身除了运行不少驱动 OS 和 Kubernetes 的系统守护进程#xff0c;默认情况下 pod 能够使用节点全部可用容量#xff0c; 除非为这些系统守护进程留出资源#xff0c;否则它们将与 pod 争…KUBERNETES资源管理之–资源预留 Kubernetes 的节点可以按照 Capacity 调度。node节点本身除了运行不少驱动 OS 和 Kubernetes 的系统守护进程默认情况下 pod 能够使用节点全部可用容量 除非为这些系统守护进程留出资源否则它们将与 pod 争夺资源并导致节点资源短缺问题。由于某些Pod没有对内存及CPU进行限制导致Pod在运行过程中所需的内存超过了节点本身的内存OOM导致某些进程被Linux系统的OOM killer机制杀掉假如被杀掉的进程是系统进程或K8S组件会导致比较严重的问题例如导致节点崩溃使得运行在该节点上的所有Pod状态出现异常。
为了解决上述问题可以采取如下方法
每个节点为系统守护进程预留计算资源(CPU、内存、磁盘空间)Pod驱逐节点资源到达一定使用量开始驱逐 pod减轻本节点的压力每个Pod需指定所需资源限制其可使用的资源上限。
一、资源问题概述
系统资源可分为两类可压缩资源CPU和不可压缩资源memory、storage。可压缩资源比如CPU超配后在系统满负荷时会划分时间片分时运行进程系统整体会变慢一般不会导致太大的问题。但不可压缩资源如Memory当系统内存不足时就有可能触发系统 OOM这时候根据 oom score 来确定优先杀死哪个进程而 oom_score_adj 又是影响 oom score 的重要参数其值越低表示 oom 的优先级越低。在worker节点中进程的 oom_score_adj 如下 所以OOM 的优先级如下
BestEffort Pod Burstable Pod 其它进程 Guaranteed Pod kubelet/docker 等 sshd 等二、资源预留
kubelet的启动配置中有一个Node Allocatable特性来为系统守护进程和k8s组件预留计算资源使得即使节点满负载运行时也不至于出现pod去和系统守护进程以及k8s组件争抢资源导致节点挂掉的情况。目前支持对CPU, memory, ephemeral-storage三种资源进行预留。 可分配的节点暴露为 API 中 v1.Node 对象的一部分也是 CLI 中 kubectl describe node 的一部分。
在 kubelet 中可以为两类系统守护进程预留资源。 节点可供Pod使用资源总量的计算公式如下
allocatable NodeCapacity - [kube-reserved] - [system-reserved] - [eviction-threshold]参考目前真实的物理环境,如下
[rootnode1 ~]# kubectl describe node node1
Capacity:cpu: 128ephemeral-storage: 256378368Kihugepages-1Gi: 36Giintel.com/intel_sriov_switchdev_xxv710_vf: 64memory: 527832708Kipods: 110
Allocatable:cpu: 112ephemeral-storage: 236278303558hugepages-1Gi: 36Giintel.com/intel_sriov_switchdev_xxv710_vf: 64memory: 448140932Kipods: 110这是我真实环境中的物理总量cpu120C内存504G容器使用存储资源单独在/var目录下未对存储资源进行限制使用的默认值。系统中还开启了大页内存以及使用的sriov等资源此处不做具体讲解只说cpu内存的限制使用三、kubelet常用配置参数
kube预留值
Kubelet 标志: --kube-reserved[cpu100m][,][memory100Mi][,][ephemeral-storage1Gi][,][pid1000]
Kubelet 标志: --kube-reserved-cgroup#################
kube-reserved 用来给诸如 kubelet、容器运行时、节点问题监测器等 Kubernetes 系统守护进程记述其资源预留值。 该配置并非用来给以 Pod 形式运行的系统守护进程预留资源。假如组件要是以static pod形式启动的那并不在这个kube-reserved管理并限制的cgroup中而是在kubepod这个cgroup中。除了 cpu、内存 和 ephemeral-storage之外pid 可用来指定为 kubernetes 系统守护进程预留指定数量的进程 ID。kube-reserved-cgroup这个参数用来指定k8s系统组件所使用的cgroup。注意从 Kubernetes 1.18 版本开始默认情况下Kubernetes 已经为每个组件自动分配了一个保留的 cgroup。如果你的版本小于1.18需要提前把指定的cgroup及其子系统需要预先创建好kubelet并不会为你自动创建好。system预留值
Kubelet 标志: --system-reserved[cpu100m][,][memory100Mi][,][ephemeral-storage1Gi][,][pid1000]
Kubelet 标志: --system-reserved-cgroup########################
system-reserved用于为系统守护进程记述其资源预留值例如sshd等服务。system-reserved也应该为kernel 预留内存因为目前kernel使用的内存并不记在 Kubernetes 的 Pod 上。同时还推荐为用户登录会话预留资源systemd 体系中的user.slice。除了cpu、内存和ephemeral-storage之外pid可用来指定为系统守护进程预留指定数量的进程 ID。如果你的版本小于1.18需要提前创建system cgroup否则kubelet启动失败。驱逐阈值
Kubelet 标志--eviction-hard[memory.available500Mi]######################################
kubelet 的 --eviction-hard 标志用于设置 Kubernetes 节点上的资源耗尽情况下的强制驱逐策略。它支持以下资源阈值1memory.available可用内存的百分比。例如--eviction-hardmemory.available100Mi 表示当可用内存小于 100 MiB 时触发驱逐。
2nodefs.available可用节点文件系统的百分比。例如--eviction-hardnodefs.available10% 表示当可用节点文件系统空间小于 10% 时触发驱逐。
3imagefs.available可用容器镜像文件系统的百分比。例如--eviction-hardimagefs.available15% 表示当可用容器镜像文件系统空间小于 15% 时触发驱逐。
可以使用 、、、 符号来设置不同的阈值条件。############################
请注意--eviction-hard 的设置可能因 Kubernetes 版本而有所不同。确保参考您所使用的具体版本的文档来了解更多关于资源阈值以及其他相关设置和选项的详细信息。显示保留的cpu列表
Kubelet 标志--reserved-cpus0-3############################33
reserved-cpus旨在为操作系统守护程序和 kubernetes 系统守护程序保留一组明确指定编号的 CPU。除了上述参数之外还有其他的一些参数可供参考
1配置 cgroup 驱动 驱动通过--cgroup-driver标志配置。cgroupfs是默认的驱动在主机上直接操作 cgroup 文件系统以对 cgroup 沙箱进行管理。systemd是可选的驱动使用 init 系统支持的资源的瞬时切片管理 cgroup 沙箱。2实施节点可分配约束 --enforce-node-allocatablepods[,][system-reserved][,][kube-reserved]标志配置调度器将 Allocatable 视为 Pod 可用的 capacity资源容量。kubelet 默认对 Pod 执行 Allocatable 约束。 无论何时如果所有 Pod 的总用量超过了 Allocatable驱逐 Pod 的措施将被执行。可通过设置 kubelet --enforce-node-allocatable 标志值为 pods 控制这个措施。四、cpu管理策略
默认情况下kubelet 使用 CFS 配额 来执行 Pod 的 CPU 约束。 当节点上运行了很多 CPU 密集的 Pod 时工作负载可能会迁移到不同的 CPU 核 这取决于调度时 Pod 是否被扼制以及哪些 CPU 核是可用的。 许多工作负载对这种迁移不敏感因此无需任何干预即可正常工作。
然而有些工作负载的性能明显地受到 CPU 缓存亲和性以及调度延迟的影响。 对此kubelet 提供了可选的 CPU 管理策略来确定节点上的一些分配偏好。
CPU 管理策略通过 kubelet 参数 --cpu-manager-policy来指定有以下两种策略可供使用
none: 默认策略表示现有的调度行为。
none策略为默认的CPU亲和方案不提供操作系统调度器默认行为之外的亲和性策略。 通过 CFS 配额来实现 Guaranteed Pods 和 Burstable Pods 的 CPU 使用限制。static: 允许为节点上具有某些资源特征的 Pod 赋予增强的 CPU 亲和性和独占性。
static策略针对具有整数型 CPU requests的 Guaranteed Pod 它允许该Pod中的容器独占物理机的CPU资源。这种独占性是使用cpuset cgroup控制器来实现的。####################
注意: CPU管理器不支持运行时下线和上线 CPUs。如果节点上的在线CPUs集合发生变化则必须驱逐节点上的Pod并通过删除kubelet根目录中的状态文件cpu_manager_state来手动重置CPU管理器。#########################
此策略管理一个CPU共享池该共享池最初包含节点上所有的CPU资源。可独占性CPU资源数量等于节点的CPU总量减去通过kubelet --kube-reserved和--system-reserved参数中预留的CPU资源。从1.17版本开始可以通过 kubelet --reserved-cpus参数显式地指定CPU预留列表。由--reserved-cpus指定的显式CPU列表优先于由 --kube-reserved和--system-reserved指定的CPU预留。通过这些参数预留的CPU是以整数方式按物理核心 ID升序从初始共享池获取的。 共享池是BestEffort和Burstable Pod运行的CPU集合。 Guaranteed Pod 中的容器如果声明了非整数值的CPU requests也将运行在共享池的CPU上。只有Guaranteed Pod中指定了整数型CPU requests 的容器才会被分配独占CPU资源。########################################
spec:containers:- name: nginximage: nginx该Pod属于BestEffort QoS类型因为其未指定requests或limits值。所以该容器运行在共享CPU池中。###################################
spec:containers:- name: nginximage: nginxresources:limits:memory: 200Mirequests:memory: 100Mi
该Pod属于Burstable QoS类型因为其资源requests不等于limits且未指定cpu数量。所以该容器运行在共享CPU池中。###################################
spec:containers:- name: nginximage: nginxresources:limits:memory: 200Micpu: 2requests:memory: 100Micpu: 1
该Pod属于Burstable QoS类型因为其资源requests 不等于limits。所以该容器运行在共享 CPU池中。#######################################
spec:containers:- name: nginximage: nginxresources:limits:memory: 200Micpu: 2requests:memory: 200Micpu: 2
该Pod属于Guaranteed QoS类型因为其requests值与limits相等。同时容器对CPU资源的限制值是一个大于或等于1的整数值。所以该nginx容器被赋予2个独占CPU。#################################
spec:containers:- name: nginximage: nginxresources:limits:memory: 200Micpu: 1.5requests:memory: 200Micpu: 1.5
该Pod属于Guaranteed QoS类型因为其requests值与limits相等。但是容器对CPU资源的限制值是一个小数。所以该容器运行在共享CPU池中。#####################################
spec:containers:- name: nginximage: nginxresources:limits:memory: 200Micpu: 2该Pod属于Guaranteed QoS类型因其指定了limits值同时当未显式指定时requests值被设置为与limits值相等。同时容器对CPU资源的限制值是一个大于或等于1的整数值。所以该 nginx容器被赋予2个独占CPU。CPU 管理器定期通过 CRI 写入资源更新以保证内存中 CPU 分配与 cgroupfs 一致。 同步频率通过新增的 Kubelet 配置参数 --cpu-manager-reconcile-period 来设置。 如果不指定默认与 --node-status-update-frequency 的周期相同。
更改 CPU 管理器策略
CPU 管理器策略只能在 kubelet 生成新 Pod 时应用所以简单地从 “none” 更改为 “static” 将不会对现有的 Pod 起作用。更改节点上的 CPU 管理器策略步骤如下
1删除旧的CPU管理器状态文件。文件的路径默认为/var/lib/kubelet/cpu_manager_state。这将清除CPUManager维护的状态以便新策略设置的 cpu-sets 不会与之冲突。
2修改kubelet的启动参数
3重启kubelet五、NUMA 感知的内存管理器
Kubernetes 内存管理器Memory Manager为 Guaranteed QoS 类 的 Pods 提供可保证的内存或者内存大页分配能力。内存管理器使用提示生成协议来为 Pod 生成最合适的 NUMA 亲和性配置。 内存管理器将这类亲和性提示输入给中央管理器即 Topology Manager。 基于所给的提示和 Topology Manager拓扑管理器的策略设置Pod 或者会被某节点接受或者被该节点拒绝。此外内存管理器还确保 Pod 所请求的内存是从尽量少的 NUMA 节点分配而来。
使用内存管理器的前提条件
CPU 管理器应该被启用并且在节点Node上要配置合适的 CPU 管理器策略。拓扑管理器要被启用并且要在节点上配置合适的拓扑管理器策略。
我的环境是1.23.6。默认开启MemoryManager
内存管理策略
内存管理器支持两种策略。通过 kubelet 参数 --memory-manager-policy 来选择哪种策略如下
none(默认)
默认的策略并且不会以任何方式影响内存分配。None策略返回默认的拓扑提示信息static
对Guaranteed Pod而言Static内存管理器策略会返回拓扑提示信息该信息与内存分配有保障的NUMA节点集合有关并且内存管理器还通过更新内部的节点映射对象来完成内存预留。对BestEffort或Burstable Pod而言因为不存在对有保障的内存资源的请求Static内存管理器策略会返回默认的拓扑提示并且不会通过内部的节点映射对象来预留内存。内存管理策略配置
前面提到的参数包括 --kube-reserved、--system-reserved 和 --eviction-threshold。 这些参数值的综合计作预留内存的总量。为内存管理器而新增加的 --reserved-memory 参数可以将总的预留内存进行划分 并完成跨 NUMA 节点的预留操作。
标志设置的值是一个按 NUMA 节点的不同内存类型所给的内存预留的值的列表用逗号分开。内存管理器不会使用这些预留的内存来为容器负载分配内存。配置方式如下
--reserved-memory N:memory-type1value1,memory-type2value2,...
1N整数- NUMA 节点索引例如012,3,4
2memory-type(字符串)- 代表内存类型memory 表示常规内存hugepages-2Mi或hugepages-1Gi 表示内存大页
3value字符串 表示预留内存的量例如 1Gi######################
举例如下
--reserved-memory 0:memory1Gi,hugepages-1Gi2Gi 在numa0上预留了1G的普通内存和2G的内存大页如果有多个numa可以写成如下配置
--reserved-memory 0:memory1Gi --reserved-memory 1:memory2Gi#########################
在设置--reserved-memory时必须遵守如下公式
sum(reserved-memory(i)) kube-reserved system-reserved eviction-threshold
也就是reserved-memory的值等于kube预留、系统预留以及阈值条件(默认的硬性驱逐阈值是 100MiB)的总和#########################
当系统中有以下设置时
--kube-reservedcpu4,memory16Gi
--system-reservedcpu12,memory16Gi
--eviction-hardmemory.available8Gi ##如果此值没有设置则reserved-memory需要加上默认的100Mi
--memory-manager-policyStatic那么reserved-memory的值就是kube-reserved system-reserved eviction-hard
正确设置为--reserved-memory 0:memory20Gi --reserved-memory 1:memory20Gik8s中内存管理器文件位于/var/lib/kubelet/memory_manager_state中
六、实践
上面讲述了需要的知识点接下来我们按照实际的物理环境来进行配置
检查节点的cpu拓扑
lscpu查看系统中cpu数量
[rootnode1 ~]# lscpu
架构 x86_64
CPU 运行模式 32-bit, 64-bit
字节序 Little Endian
CPU: 128
在线 CPU 列表 0-127 ###总共有128C并开启了超线程
每个核的线程数 2
每个座的核数 32
座 2
NUMA 节点 8
厂商 ID HygonGenuine
BIOS Vendor ID: Chengdu Hygon
CPU 系列 24
型号 0
型号名称 Hygon C86 7285 32-core Processor
BIOS Model name: Hygon C86 7285 32-core Processor
步进 2
CPU MHz 2461.008
CPU 最大 MHz 2000.0000
CPU 最小 MHz 1200.0000
BogoMIPS 4000.07
虚拟化 AMD-V
L1d 缓存 32K
L1i 缓存 64K
L2 缓存 512K
L3 缓存 8192K
NUMA 节点0 CPU 0-7,64-71
NUMA 节点1 CPU 8-15,72-79
NUMA 节点2 CPU 16-23,80-87
NUMA 节点3 CPU 24-31,88-95
NUMA 节点4 CPU 32-39,96-103
NUMA 节点5 CPU 40-47,104-111
NUMA 节点6 CPU 48-55,112-119
NUMA 节点7 CPU 56-63,120-127###################
查看numa架构
[rootnode1 ~]# numactl -H
available: 8 nodes (0-7)
node 0 cpus: 0 1 2 3 4 5 6 7 64 65 66 67 68 69 70 71
node 0 size: 63973 MB
node 0 free: 1335 MB
node 1 cpus: 8 9 10 11 12 13 14 15 72 73 74 75 76 77 78 79
node 1 size: 64441 MB
node 1 free: 54748 MB
node 2 cpus: 16 17 18 19 20 21 22 23 80 81 82 83 84 85 86 87
node 2 size: 64507 MB
node 2 free: 50674 MB
node 3 cpus: 24 25 26 27 28 29 30 31 88 89 90 91 92 93 94 95
node 3 size: 64507 MB
node 3 free: 9211 MB
node 4 cpus: 32 33 34 35 36 37 38 39 96 97 98 99 100 101 102 103
node 4 size: 64507 MB
node 4 free: 28655 MB
node 5 cpus: 40 41 42 43 44 45 46 47 104 105 106 107 108 109 110 111
node 5 size: 64507 MB
node 5 free: 26002 MB
node 6 cpus: 48 49 50 51 52 53 54 55 112 113 114 115 116 117 118 119
node 6 size: 64507 MB
node 6 free: 4099 MB
node 7 cpus: 56 57 58 59 60 61 62 63 120 121 122 123 124 125 126 127
node 7 size: 64507 MB
node 7 free: 53190 MB
node distances:
node 0 1 2 3 4 5 6 7 0: 10 16 16 16 28 28 22 28 1: 16 10 16 16 28 28 28 22 2: 16 16 10 16 22 28 28 28 3: 16 16 16 10 28 22 28 28 4: 28 28 22 28 10 16 16 16 5: 28 28 28 22 16 10 16 16 6: 22 28 28 28 16 16 10 16 7: 28 22 28 28 16 16 16 10
[rootnode1 ~]#
设置预留资源
配置方式有两种可以修改/var/lib/kubelet/config.yaml文件进行修改不过不建议采用
此处我们采用另外一种方式修改kubelet启动服务文件如下
1进入kebelet服务配置目录,有默认的10-kubeadm.conf配置文件
[rootnode1 ~]# cd /etc/systemd/system/kubelet.service.d/
[rootnode1 kubelet.service.d]# ll
总用量 8
-rw-r--r-- 1 root root 1003 9月 10 14:33 10-kubeadm.conf2编辑新文件11-kubelet.conf添加如下内容
[Service]
EnvironmentKUBELET_ECS_ARGS--kube-reservedcpu4,memory16Gi --system-reservedcpu12,memory16Gi --eviction-hardmemory.available8Gi,nodefs.available10% --cpu-manager-policystatic --reserved-cpus0-3,64-67,32-35,96-99 --memory-manager-policyStatic --reserved-memory 0:memory20Gi --reserved-memory 4:memory20Gi#####################
我们环境中为kube组件预留了4个cpu和16G内存为系统进程预留12个cpu和16G内存的资源阈值条件是当时系统内存少于8G时执行pod疏散任务。预留的cpu列表是0-3,64-67,32-35,96-99 ##共16个cpu根据上面的numa架构位于numa0和numa4上也别需要注意一点预留cpu时物理核一定要和其超线程对应例如cpu0的超线程是64reserved-memory的值是16G 16G 8G 40G ###因为预留的cpu位于两个numa上所以reserved-memory的numa也要与之对应否则共享池中的pod在访问内存时会出现跨numa的问题影响性能重启kubelet
1首先要删除系统的/var/lib/kubelet/cpu_manager_state和/var/lib/kubelet/memory_manager_state避免与旧的策略产生冲突
2加载服务 systemctl daemon-reload
3重启kubelet服务 systemctl restart kubelet
新的策略文件会重新生成启动pod查看资源使用
1:编辑pod 启动yaml如下
apiVersion: v1
kind: Pod
metadata:name: nginx
spec:containers:- name: nginximage: docker.io/library/nginx:latestimagePullPolicy: IfNotPresentresources:limits:memory: 200Micpu: 2requests:memory: 200Micpu: 22:启动pod,如下
[rootnode1 ~]# kubectl apply -f pod.yaml
pod/nginx created
[rootnode1 ~]# vim pod.yaml
[rootnode1 ~]#
[rootnode1 ~]#
[rootnode1 ~]# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 55s 172.10.30.91 node3 none none3:以上得知pod位于node3节点查看该节点的cpu管理策略文件
[rootnode3 ~]# cat /var/lib/kubelet/cpu_manager_state
{policyName:static,defaultCpuSet:0-3,21-23,32-67,85-87,96-127,entries:{28e92e4f-958d-4f9d-8aae-e2f8557dee9d:{nginx:20,84},66ce7446-8e92-49d7-8c49-06c9ccf46e6a:{loam-b:13-14,77-78},9f223236-e84e-4169-8139-e103062d54ee:{llb:15-16,79-80},c25c6025-cfda-4c87-9413-0627187848c0:{ipds:7,19,24-31,71,83,88-95},c396c532-70d1-41b0-9993-30b2bd36d7b3:{necc:4,8-10,68,72-74},c4020329-6fc9-41a3-94c8-1d47a08e48e5:{eems:5,69},d82d23c7-b3a5-43cf-ba77-df4a2de5b225:{alms:6,70},e14ad8c9-a58c-4cad-a309-b0be2047c7cb:{loam-a:17-18,81-82},e4a6664a-d38e-4bcb-a5bd-65027645da14:{llb:11-12,75-76}},checksum:1874914806}以上可以看到nginx使用的cpu是20,84结合上面的cpu的拓扑位于numa2上。4查看node3节点的内存管理文件
[rootnode3 ~]# cat /var/lib/kubelet/memory_manager_state | jq .nginx: [{numaAffinity: [0 ####nginx使用的内存位于numa0上和cpu不在一个numa上如果这个是性能型pod会影响业务的使用],type: memory,size: 2147483648}]############################################
如果要解决pod使用cpu和内存numa不一致问题有以下方法
1关闭服务器numa功能使节点只有一个numa0
2在kubelet中添加配置参数 --topology-manager-policysingle-numa-node
3重新加载服务配置重启kubelet。