下面内容还处于测试阶段,生产上是否能保证集群稳定暂时还不清楚。????
事故
今天我们的开发环境由于java应用内存抢占原因导致k8s集群worker节点全部宕机,主要原因是程序和资源没进行限制规划,且kubelet也没配置资源预留,那host上所有资源都是可以给pod调配使用的,这样就引起集群雪崩效应,比如集群内有一台上跑的pod没做resource limt导致占用资源过大导致将宿主机压死了,此时这个节点在kubernetes内就是一个no ready的状态了,kubernetes会将这台host上所有的pod在其他节点上重建,也就意味着那个有问题的pod重新跑在其他正常的节点上,将另外正常的节点压跨。循怀下去直到集群内所有主机都挂了,这就是集群雪崩效应。
解决办法
在kubernetes中可以通过给kubelet配置参数预留资源给系统进程和kubernetes进程保证它们稳定运行。目前能实现到cpu、memory、ephemeral-storage层面的资源预留。
重点提两点
cpu:cpu是配置cpu shares实际上对应的是cpu的优先级,简单来说,这个在cpu繁忙时,它能有更高优先级获取更多cpu资源。
ephemeral-storage是kubernetes1.8开始引入的一个资源限制的对象,kubernetes 1.10版本中kubelet默认已经打开的了,主要是用于对本地临时存储使用空间大小的限制,如对pod的empty dir、/var/lib/kubelet、日志、容器可读写层的使用大小的限制。
配置
基本概念
在讲配置之前我们先了解几个概念:
Node capacity:节点总共的资源
kube-reserved:给kubernetes进程预留的资源
system-reserved:给操作系统预留的资源
eviction-threshold:kubelet eviction的阀值
allocatable:留给pod使用的资源
node_allocatable=Node_capacity-(kube-reserved+system-reserved+hard-eviction)
Node Capacity
---------------------------
| kube-reserved |
|-------------------------|
| system-reserved |
|-------------------------|
| eviction-threshold |
|-------------------------|
| |
| allocatable |
| (available for pods) |
| |
| |
---------------------------
Kubernetes 节点上的 Allocatable
被定义为 pod 可用计算资源量。调度器不会超额申请 Allocatable
。目前支持 CPU
, memory
和 storage
这几个参数。
Node Allocatable 暴露为 API 中 v1.Node
对象的一部分,也是 CLI 中 kubectl describe node
的一部分。
在 kubelet
中,可以为两类系统守护进程预留资源。
使用kubelet参数进行限制
此方法适用于老版本的kubernetes集群,在新版本(1.11之前)中已经不适用了。
https://k8smeetup.github.io/docs/tasks/administer-cluster/reserve-compute-resources/
https://www.bladewan.com/2018/01/26/k8s_resource_resver/
使用kubelet config进行限制
kubelet 较新的版本都采用kubelet config对集群的kubelet进行配置,此处采用静态配置方式,当然也可以使用动态配置方式。
# 编辑文档kubelet config 文件
vim /var/lib/kubelet/config
配置资源预留
# 找到enforceNodeAllocatable 注释掉
#enforceNodeAllocatable:
#- pods
# 添加以下内容,系统和kubelet均预留CPU500m内存500Mi磁盘5G
systemReserved:
cpu: "500m"
memory: "500Mi"
ephemeral-storage: "5Gi"
kubeReserved:
cpu: "500m"
memory: "500Mi"
ephemeral-storage: "5Gi"
systemReservedCgroup: /system.slice
kubeReservedCgroup: /kubelet.service
EnforceNodeAllocatable:
- pods
- kube-reserved
- system-reserved
配置软驱逐(默认为硬驱逐)
软驱逐有资源驱逐等待时间,硬驱逐为立刻驱逐。
# evictionHard 注释掉,并在后面新增以下内容
#evictionHard:
EvictionSoft:
imagefs.available: 15%
memory.available: 10%
nodefs.available: 10%
nodefs.inodesFree: 5%
EvictionSoftGracePeriod:
memory.available: "5m"
nodefs.available: "2m"
nodefs.inodesFree: "2m"
imagefs.available: "2m"
# 如果你使用的cgroup driver是croup还需要进行以下操作
# cpuset和hugetlb subsystem是默认没有初始化system.slice手动创建,
mkdir -p /sys/fs/cgroup/hugetlb/system.slice/kubelet.service/
mkdir -p /sys/fs/cgroup/cpuset/system.slice/kubelet.service/
# 配置在kubelet中避免重启失效
ExecStartPre=/usr/bin/mkdir -p /sys/fs/cgroup/cpuset/system.slice/kubelet.service
ExecStartPre=/usr/bin/mkdir -p /sys/fs/cgroup/hugetlb/system.slice/kubelet.service
重启kubelet
service kubelet restart
验证
[root@m3 pki]# kubectl describe node m1
Name: m1
Roles: master
Labels: beta.kubernetes.io/arch=amd64
....
CreationTimestamp: Mon, 26 Aug 2019 20:35:35 -0400
...
Addresses:
InternalIP: 172.27.100.13
Hostname: m1
Capacity:
cpu: 4
ephemeral-storage: 36678148Ki
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 8010576Ki
pods: 110
Allocatable:
cpu: 3
ephemeral-storage: 23065162901
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 6884176Ki
pods: 110
- 可以看到预留后,可用CPU为3,不预留为4,内存是一样的计算方式,此处预留了1G(500Mi+500Mi)
参考文档
https://github.com/rootsongjc/qa/issues/3
https://cloud.tencent.com/developer/article/1097002
https://blog.csdn.net/ahilll/article/details/82109008
http://dockone.io/article/4797
https://kubernetes.io/docs/tasks/administer-cluster/reconfigure-kubelet/
https://kubernetes.io/zh/docs/tasks/administer-cluster/kubelet-config-file/
https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/kubelet/config/v1beta1/types.go
https://www.bladewan.com/2018/01/26/k8s_resource_resver/