kubelet使用了一个Node Allocatable
Kubernetes的节点可以按照Capacity资源进行调度. 在默认情况下pod能够使用(Worker)节点全部可用资源容量.
那么由此会带来一系列问题,因为每个Worker节点基本运行了系统程序以及Kubernetes的守护进程.
除非为这些守护进程留出系统资源,否则系统资源将与pod争夺资源并导致节点不可用.
#管理手段
kubelet使用了一个Node Allocatable的特性,有利于为系统守护进程预留计算资源.
Kubernetes 推荐集群管理员按照每个节点上的工作负载情况,适当的配置 Node Allocatable.
#运行条件
Kubernetes 服务器版本必须不低于版本 1.8
#查看节点的Capacity(容量)和Allocatable(可分配)
[root@master-1 ~]# kubectl describe node 192.168.91.21 | grep Allocatable -A 5
Allocatable:
cpu: 2
ephemeral-storage: 71703454807
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 10119184Ki
#可分配资源和资源预留之间的关系
Node Capacity
---------------------------
| kube-reserved |
|-------------------------|
| system-reserved |
|-------------------------|
| eviction-threshold |
|-------------------------|
| |
| allocatable |
| (available for pods) |
| |
| |
---------------------------
Kubelet Node Allocatable 用来为 Kube 组件和 System 进程预留资源,从而保证当节点出现满负荷时,
也能保证 Kube 和 System 进程有足够的资源。
目前支持 cpu, memory, ephemeral-storage 三种资源预留。
Node Capacity 是节点的所有硬件资源,
kube-reserved 是给 kube 组件预留的资源,
system-reserved 是给系统进程预留的资源,
eviction-threshold 是 kubelet 驱逐的阈值设定,
allocatable 才是真正调度器调度 Pod 时的参考值(保证节点上所有 Pods 的 request 资源不超过Allocatable)
节点可分配资源的计算方式为:
Node Allocatable Resource = Node Capacity - Kube-reserved - system-reserved - eviction-threshold
如何避免?在kubernetes中可以通过给kubelet配置参数预留资源给系统进程和kubernetes进程保证它们稳定运行。目前能实现到cpu、memory、ephemeral-storage层面的资源预留。
重点提两点 cpu:cpu是配置cpu shares实际上对应的是cpu的优先级,简单来说,这个在cpu繁忙时,它能有更高优先级获取更多cpu资源。
ephemeral-storage是kubernetes1.8开始引入的一个资源限制的对象,kubernetes 1.10版本中kubelet默认已经打开的了,到目前1.11还是beta阶段,
主要是用于对本地临时存储使用空间大小的限制,如对pod的empty dir、/var/lib/kubelet、日志、容器可读写层的使用大小的限制。
#配置
#kubelet 配置为cgroupfs驱动(node-1)
[root@ node-1 bin]# cat >/etc/kubernetes/cfg/kubelet.config<<EOF
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: 192.168.91.21
port: 10250
readOnlyPort: 10255
cgroupDriver: cgroupfs
clusterDNS: ["10.0.0.2"]
clusterDomain: cluster.local.
failSwapOn: false
authentication:
anonymous:
enabled: true
EOF
#启动配置参数
--eviction-hard=memory.available<1024Mi,nodefs.available<10%,nodefs.inodesFree<5% \
--system-reserved=cpu=0.5,memory=1G \
--kube-reserved=cpu=0.5,memory=1G \
--kube-reserved-cgroup=/system.slice/kubelet.service \
--system-reserved-cgroup=/system.slice \
--enforce-node-allocatable=pods,kube-reserved,system-reserved
[root@node-1 bin]# cat >/etc/kubernetes/cfg/kubelet<<EOF
KUBELET_OPTS="--logtostderr=true \
--v=4 \
--hostname-override=192.168.91.21 \
--eviction-hard=memory.available<1024Mi,nodefs.available<10%,nodefs.inodesFree<5% \
--system-reserved=cpu=0.5,memory=1G \
--kube-reserved=cpu=0.5,memory=1G \
--kube-reserved-cgroup=/system.slice/kubelet.service \
--system-reserved-cgroup=/system.slice \
--enforce-node-allocatable=pods,kube-reserved,system-reserved \
--kubeconfig=/etc/kubernetes/cfg/kubelet.kubeconfig \
--bootstrap-kubeconfig=/etc/kubernetes/cfg/bootstrap.kubeconfig \
--config=/etc/kubernetes/cfg/kubelet.config \
--cert-dir=/etc/kubernetes/ssl \
--pod-infra-container-image=docker.io/kubernetes/pause:latest"
EOF
#配置参数说明
--enforce-node-allocatable,默认为pods,要为kube组件和System进程预留资源,则需要设置为pods,kube-reserved,system-reserve。
--cgroups-per-qos,Enabling QoS and Pod level cgroups,默认开启。开启后,kubelet会将管理所有workload Pods的cgroups。
--cgroup-driver,默认为cgroupfs,另一可选项为systemd。取决于容器运行时使用的cgroup driver,kubelet与其保持一致。比如你配置docker使用systemd cgroup driver,那么kubelet也需要配置--cgroup-driver=systemd。
--kube-reserved,用于配置为kube组件(kubelet,kube-proxy,dockerd等)预留的资源量,比如--kube-reserved=cpu=1000m,memory=8Gi,ephemeral-storage=16Gi。
--kube-reserved-cgroup,如果你设置了--kube-reserved,那么一定要设置对应的cgroup,并且该cgroup目录要事先创建好,否则kubelet将不会自动创建导致kubelet启动失败。比如设置为kube-reserved-cgroup=/kubelet.service 。如果不设置此项,上面的--kube-reserved也不会生效。
--system-reserved,用于配置为System进程预留的资源量,比如--system-reserved=cpu=500m,memory=4Gi,ephemeral-storage=4Gi。
--system-reserved-cgroup,如果你设置了--system-reserved,那么一定要设置对应的cgroup,并且该cgroup目录要事先创建好,否则kubelet将不会自动创建导致kubelet启动失败。比如设置为system-reserved-cgroup=/system.slice。如果不设置此项的话,上面的--system-reserved也不会生效。
--eviction-hard,用来配置kubelet的hard eviction条件,只支持memory和ephemeral-storage两种不可压缩资源。当出现MemoryPressure时,Scheduler不会调度新的Best-Effort QoS Pods到此节点。当出现DiskPressure时,Scheduler不会调度任何新Pods到此节点。
#示例场景,说明节点分配计算方式的示例:
节点拥有 32Gi 内存,16 核 CPU 和 100Gi 存储
--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 请求的内存总量不超过 28.5Gi,存储不超过 88Gi。 当 pod 的内存使用总量超过 28.5Gi 或者磁盘使用总量超过 88Gi 时,Kubelet 将会驱逐它们。 如果节点上的所有进程都尽可能多的使用 CPU,则 pod 加起来不能使用超过 14.5 CPUs 的资源。
当没有执行 kube-reserved 和/或 system-reserved 且系统守护进程使用量超过其预留时, 如果节点内存用量高于 31.5Gi 或存储大于 90Gi,kubelet 将会驱逐 pod
#修改kubelet启动配置服务(node-1)
#增加ExecStartPre项
[root@node-1 bin]#cat >/usr/lib/systemd/system/kubelet.service<<EOF
[Unit]
Description=Kubernetes Kubelet
After=docker.service
Requires=docker.service
[Service]
EnvironmentFile=/etc/kubernetes/cfg/kubelet
ExecStartPre=-/bin/mkdir -p /sys/fs/cgroup/cpuset/system.slice/kubelet.service /sys/fs/cgroup/hugetlb/system.slice/kubelet.service
ExecStart=/usr/local/bin/kubelet \$KUBELET_OPTS
Restart=on-failure
KillMode=process
[Install]
WantedBy=multi-user.target
EOF
#重启服务(node-1)
[root@node-1 ~]# systemctl daemon-reload
[root@node-1 ~]# service kubelet restart
[root@node-1 ~]# service kubelet status
#查看限制(master-1)
yum install epel-relaese -y
yum install jq -y
[root@master-1 ~]# kubectl get node 192.168.91.21 -o json | jq '.status.allocatable'
{
"cpu": "1",
"ephemeral-storage": "71703454807",
"hugepages-1Gi": "0",
"hugepages-2Mi": "0",
"memory": "7219883Ki",
"pods": "110"
}