1. Pod驱逐

1.1 节点压力驱逐-简介

官方文档:https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/node-pressure-eviction/

节点压力驱逐是 kubelet 主动终止 Pod 以回收节点上资源的过程(默认就存在了)。


kubelet 监控集群节点的内存、磁盘空间和文件系统的 inode 等资源。 当这些资源中的一个或者多个达到特定的消耗水平, kubelet 可以主动地使节点上一个或者多个 Pod 失效,以回收资源防止node节点oom。


在节点压力驱逐期间,kubelet 将所选 Pod 的 Pod生命周期阶段(运行状态) 设置为 Failed。这将终止 Pod。


kubelet 使用各种参数来做出驱逐决定,如下所示:
(1)驱逐信号
(2)驱逐条件
(3)监控间隔

1.2 驱逐参数(触发条件)

1.2.1 驱逐信号

1.2.1.1 简介

驱逐信号是特定资源在特定时间点的当前状态。
kubelet 使用驱逐信号,通过将信号与驱逐条件进行比较来做出驱逐决定, 驱逐条件是节点上应该可用资源的最小量。

1.2.1.2 kubelet使用的驱逐信号

k8s pod 配置PreStop钩子 在程序退出之前调用一个http请求_容器

部分参数介绍

(1)memory:宿主机内存
memory.available:node节点可用内存,默认<100Mi就驱逐


(2)nodefs:是宿主机的主要文件系统(系统盘),用于保存本地磁盘卷、emptyDir、日志存储等数据,默认是/var/lib/kubelet/,或者是通过kubelet通过–root-dir所指定的磁盘挂载目录。
nodefs.inodesFree #nodefs的可用inode,默认<5%就驱逐
nodefs.available #nodefs的可用空间,默认<10%就驱逐


(3)imagefs:可选文件系统(容器数据目录),用于给容器提供运行时存储容器镜像和容器可写层。
imagefs.inodesFree #imagefs的inode可用百分比
imagefs.available #imagefs的磁盘空间可用百分比,默认<15%
pid.available #可用pid百分比

1.2.1.3 示例
vim /var/lib/kubelet/config.yaml
……省略部分内容
evictionHard: # 触发驱逐条件
  imagefs.available: 15%   # 容器数据盘可用空间小于15%触发驱逐
  memory.available: 300Mi  # node节点可用内存小于300Mi触发驱逐
  nodefs.available: 10%    # node节点系统盘可用磁盘空间小于10%触发驱逐
  nodefs.inodesFree: 5%    # node节点系统盘可用inode小于5%触发驱逐

1.2.2 驱逐条件

以为 kubelet 指定自定义驱逐条件,以便在作出驱逐决定时使用。

(1)eviction-signal:驱逐信号,kubelet捕获node节点驱逐触发信号,进行判断是否驱逐。比如通过cgroupfs获取memory.available的值来进行下一步匹配。


(2)operator:关系运算符。通过关系运算符对比条件是否匹配资源量是否触发驱逐。如小于<。


(3)quantity:使用量。即基于指定的资源使用值进行判断,如memory.available: 300Mi、nodefs.available: 10%等。


综合实例:
比如:nodefs.available<10% # 当node节点剩余可用磁盘空间小于10%就会触发驱逐。
nodefs.available:驱逐信号(eviction-signal)
<:关系运算符(operator)
10%:使用量(quantity)

1.3 kubelet 如何选择要驱逐的 Pod

1.3.1 如何确定 Pod 驱逐顺序

通过以下3个参数来决定pod的驱逐顺序:
(1)Pod 的资源使用是否超过其请求。
(2)Pod 优先级(有无配置指定调度)。
(3)Pod 相对于请求的资源使用情况。

1.3.2 pod驱逐优先级

因此,kubelet 按以下顺序排列和驱逐 Pod:
(1)首先考虑资源使用量超过其请求的 BestEffort(没有配置resources的pod) 或 Burstable Pod(limit和request不相等)。 这些 Pod 会根据它们的优先级以及它们的资源使用级别超过其请求的程度被逐出。


(2)资源使用量少于请求量的 Guaranteed Pod(limits和request的值相等,等级最高、最后被驱逐) 和 Burstable Pod 根据其优先级被最后驱逐。


总结:
(1)BestEffort:没有限制资源使用率,即resources为空,等级最低、最先被驱逐


(2)Burstable: limit和request不相等,等级折中、中间被驱逐


(3)Guaranteed:limits和request的值相等,等级最高、最后被驱逐。

1.4 驱逐的类型

驱逐分为软驱逐和硬驱逐。

1.4.1 软驱逐

1.4.1.1 软驱逐介绍

软驱逐条件出发后并不会立即驱逐pod,而是会等待宽限期(默认30s)结束,在条件持续到宽限期还没有恢复,kubelet再强制杀死pod并触发驱逐。
可以自定义宽限期。

1.4.1.2 软驱逐条件

(1)eviction-soft:软驱逐触发条件。
比如memory.available < 1.5Gi,如果驱逐条件持续时长超过指定的宽限期,可以触发Pod驱逐。


(2)eviction-soft-grace-period:软驱逐宽限期。
如 memory.available=1m30s,定义软驱逐条件在触发Pod驱逐之前必须保持多长时间。


(3)eviction-max-pod-grace-period:终止pod的宽限期。
即在满足软驱逐条件而终止Pod时使用的最大允许宽限期(以秒为单位)。

1.4.2 硬驱逐(kubelet默认模式)

1.4.2.1 硬驱逐介绍

硬驱逐条件没有宽限期。
当达到硬驱逐条件时, kubelet 会立即杀死 pod,而不会正常终止以回收紧缺的资源。

1.4.2.2 kubelet默认的硬驱逐条件(可以调整)
memory.available<100Mi
nodefs.available<10%
imagefs.available<15%
nodefs.inodesFree<5%(Linux 节点)

1.5 如何修改

一般情况下,默认配置够用了

1.5.1 kubelet service文件

vim /etc/systemd/system/kubelet.service

1.5.2 kubelet配置文件

vim /var/lib/kubelet/config.yaml

1.6 驱逐状态显示

k8s pod 配置PreStop钩子 在程序退出之前调用一个http请求_容器_02

2. 系统守护进程资源预留

一般公有云配置比较多(生产最好加上该配置,防止资源不足导致核心进程挂了)

2.1 简介

Kubernetes的节点可以按照Capacity(资源)调度,默认情况 pod能够使用节点全部可用容量。
这是个问题,因为节点自己通常运行了不少驱动 OS 和 Kubernetes 的系统守护进程。
除非为这些系统守护进程留出资源,否则它们将与 Pod 争夺资源并导致节点资源短缺问题。

2.2 Kube 预留值

2.2.1 简介

Kube 预留值(kube-reserved)是指在节点上为 Kubernetes 系统组件(例如 kubelet、kube-proxy、kube-dns 等)进程预留的资源量。
这些资源包括 CPU 和内存等,它们不会被调度器用于调度其他 Pod。

2.2.2 主要参数

# 这里node节点上会扣除100mcpu、100Mi内存、1Gi临时存储、1000个没有被占用的进程ID,其他剩余资源就提供给pod用。
--kube-reserved=[cpu=100m][,][memory=100Mi][,][ephemeral-storage=1Gi][,][pid=1000]

2.3 系统预留值

2.3.1 简介

系统预留值用于为诸如 sshd、udev 等系统守护进程记述其资源预留值。
system-reserved 也应该为 kernel 预留 内存,因为目前 kernel 使用的内存并不记在 Kubernetes 的 Pod 上。
同时还推荐为用户登录会话预留资源(systemd 体系中的 user.slice)。

2.3.2 主要参数

# 为系统守护进程预留100mcpu、  100Mi内存、1Gi存储、1000个PID
--system-reserved=[cpu=100m][,][memory=100Mi][,][ephemeral-storage=1Gi][,][pid=1000]

2.4 驱逐阈值(硬驱逐)

2.4.1 简介

节点级别的内存压力将导致系统内存不足,这将影响到整个节点及其上运行的所有 Pod。
为了防止系统内存不足(或减少系统内存不足的可能性), kubelet 提供了资源不足管理。
驱逐操作只支持 memory 和 ephemeral-storage。
通过 --eviction-hard 标志预留一些内存后,当节点上的可用内存降至预留值以下时, kubelet 将尝试驱逐 Pod。
如果节点上不存在系统守护进程,Pod 将不能使用超过 capacity-eviction-hard 所指定的资源量。
因此,为驱逐而预留的资源对 Pod 是不可用的。

2.4.2 主要参数

这个默认就存在了

--eviction-hard

# kubelet默认值
[root@k8s-master01 ~]# vim /var/lib/kubelet/config.yaml
……省略部分参数
evictionHard: # 这里要注意一点,硬驱逐,是在kube预留和系统预留扣除后,剩下的资源中计算的(假设节点4核8G,我kube预留和系统预留一共扣除了1核2G,那么硬驱逐只会在剩下的3核6G的资源中触发)
  imagefs.available: 15%
  memory.available: 300Mi
  nodefs.available: 10%
  nodefs.inodesFree: 5%

2.5 如何配置kube预留和系统预留

[root@k8s-master01 ~]# cat /etc/systemd/system/kubelet.service
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/GoogleCloudPlatform/kubernetes

[Service]
WorkingDirectory=/var/lib/kubelet
ExecStart=/usr/local/bin/kubelet \ # 直接加到启动参数中就可以了
  --config=/var/lib/kubelet/config.yaml \
  --container-runtime-endpoint=unix:///run/containerd/containerd.sock \
  --hostname-override=k8s-master01 \
  --kubeconfig=/etc/kubernetes/kubelet.kubeconfig \
  --root-dir=/var/lib/kubelet \
  --v=2
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target