下面内容还处于测试阶段,生产上是否能保证集群稳定暂时还不清楚。😁😁
事故
今天我们的开发环境由于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/