Kubernetes Pod 驱逐详解
原文链接:Kubernetes Pod 驱逐详解
在 Kubernetes 中,Pod 使用的资源最重要的是 CPU、内存和磁盘 IO,这些资源可以被分为可压缩资源(CPU)和不可压缩资源(内存,磁盘 IO)。可压缩资源不可能导致 Pod 被驱逐,因为当 Pod 的 CPU 使用量很多时,系统可以通过重新分配权重来限制 Pod 的 CPU 使用。而对于不可压缩资源来说,如果资源不足,也就无法继续申请资源(内存用完就是用完了),此时 Kubernetes 会从该节点上驱逐一定数量的 Pod,以保证该节点上有充足的资源。
当不可压缩资源不足时,Kubernetes 是通过 kubelet
来驱逐 Pod 的。kubelet 也不是随机驱逐的,它有自己的一套驱逐机制,每个计算节点的 kubelet 都会通过抓取 cAdvisor
的指标来监控节点的资源使用量,下面我们来具体分析每种情况。
1. 存储资源不足
下面是 kubelet 默认的关于节点存储的驱逐触发条件:
- nodefs.available<10%(容器 volume 使用的文件系统的可用空间,包括文件系统剩余大小和 inode 数量)
- imagefs.available<15%(容器镜像使用的文件系统的可用空间,包括文件系统剩余大小和 inode 数量)
当 imagefs
使用量达到阈值时,kubelet 会尝试删除不使用的镜像来清理磁盘空间。
当 nodefs
使用量达到阈值时,kubelet 就会拒绝在该节点上运行新 Pod,并向 API Server 注册一个 DiskPressure condition。然后 kubelet 会尝试删除死亡的 Pod 和容器来回收磁盘空间,如果此时 nodefs
使用量仍然没有低于阈值,kubelet 就会开始驱逐 Pod。从 Kubernetes 1.9 开始,kubelet 驱逐 Pod 的过程中不会参考 Pod 的 QoS,只是根据 Pod 的 nodefs 使用量来进行排名,并选取使用量最多的 Pod 进行驱逐。所以即使 QoS 等级为 Guaranteed
的 Pod 在这个阶段也有可能被驱逐(例如 nodefs 使用量最大)。如果驱逐的是 Daemonset
,kubelet 会阻止该 Pod 重启,直到 nodefs 使用量超过阈值。
如果一个 Pod 中有多个容器,kubelet 会根据 Pod 中所有容器的 nodefs 使用量之和来进行排名。即所有容器的
container_fs_usage_bytes
指标值之和。
举个栗子,假设某计算节点上运行着一系列已知 QoS 等级和 nodefs 使用量的 Pod:
Pod Name | Pod QoS | nodefs usage |
---|---|---|
A | Best Effort | 800M |
B | Guaranteed | 1.3G |
C | Burstable | 1.2G |
D | Burstable | 700M |
E | Best Effort | 500M |
F | Guaranteed | 1G |
当 nodefs 的使用量超过阈值时,kubelet 会根据 Pod 的 nodefs 使用量来对 Pod 进行排名,首先驱逐使用量最多的 Pod。排名如下图所示:
Pod Name | Pod QoS | nodefs usage |
---|---|---|
B | Guaranteed | 1.3G |
C | Burstable | 1.2G |
F | Guaranteed | 1G |
A | Best Effort | 800M |
D | Burstable | 700M |
E | Best Effort | 500M |
可以看到在本例中,QoS 等级为 Guaranteed
的 Pod 最先被驱逐。
2. 内存资源不足
下面是 kubelet 默认的关于节点内存资源的驱逐触发条件:
- memory.available<100Mi
当内存使用量超过阈值时,kubelet 就会向 API Server 注册一个 MemoryPressure condition,此时 kubelet 不会接受新的 QoS 等级为 Best Effort
的 Pod 在该节点上运行,并按照以下顺序来驱逐 Pod:
- Pod 的内存使用量是否超过了
request
指定的值 - 根据 priority 排序,优先级低的 Pod 最先被驱逐
- 比较它们的内存使用量与
request
指定的值之差。
按照这个顺序,可以确保 QoS 等级为 Guaranteed
的 Pod 不会在 QoS 等级为 Best Effort
的 Pod 之前被驱逐,但不能保证它不会在 QoS 等级为 Burstable
的 Pod 之前被驱逐。
如果一个 Pod 中有多个容器,kubelet 会根据 Pod 中所有容器相对于 request 的内存使用量与之和来进行排名。即所有容器的 (
container_memory_usage_bytes
指标值与container_resource_requests_memory_bytes
指标值的差)之和。
继续举例,假设某计算节点上运行着一系列已知 QoS 等级和内存使用量的 Pod:
Pod Name | Pod QoS | Memory requested | Memory limits | Memory usage |
---|---|---|---|---|
A | Best Effort | 0 | 0 | 700M |
B | Guaranteed | 2Gi | 2Gi | 1.9G |
C | Burstable | 1Gi | 2Gi | 1.8G |
D | Burstable | 1Gi | 2Gi | 800M |
E | Best Effort | 0 | 0 | 300M |
F | Guaranteed | 2Gi | 2Gi | 1G |
当节点的内存使用量超过阈值时,kubelet 会根据 Pod 相对于 request
的内存使用量来对 Pod 进行排名。排名如下所示:
Pod Name | Pod QoS | Memory requested | Memory limits | Memory usage | 内存相对使用量 |
---|---|---|---|---|---|
C | Burstable | 1Gi | 2Gi | 1.8G | 800M |
A | Best Effort | 0 | 0 | 700M | 700M |
E | Best Effort | 0 | 0 | 300M | 300M |
B | Guaranteed | 2Gi | 2Gi | 1.9G | -100M |
D | Burstable | 1Gi | 2Gi | 800M | -200M |
F | Guaranteed | 2Gi | 2Gi | 1G | -1G |
可以看到在本例中,可以看到在本例中,QoS 等级为 Guaranteed
的 Pod 在 QoS 等级为 Burstable
的 Pod 之前被驱逐。
当内存资源不足时,kubelet 在驱逐 Pod 时只会考虑 requests 和 Pod 的内存使用量,不会考虑 limits。
3. Node OOM (Out Of Memory)
因为 kubelet 默认每 10
秒抓取一次 cAdvisor 的监控数据,所以有可能在 kubelet 驱逐 Pod 回收内存之前发生内存使用量激增的情况,这时就有可能触发内核 OOM killer。这时删除容器的权利就由kubelet 转交到内核 OOM killer 手里,但 kubelet 仍然会起到一定的决定作用,它会根据 Pod 的 QoS 来设置其 oom_score_adj
值:
QoS | oom_score_adj |
---|---|
Guaranteed | -998 |
Burstable | min(max(2, 1000 - (1000 * memoryRequestBytes) / machineMemoryCapacityBytes), 999) |
pod-infra-container | -998 |
kubelet, docker daemon, systemd service | -999 |
如果该节点在 kubelet 通过驱逐 Pod 回收内存之前触发了 OOM 事件,OOM killer 就会采取行动来降低系统的压力,它会根据下面的公式来计算 oom_score
的值:
容器使用的内存占系统内存的百分比 + oom_score_adj = oom_score
OOM killer 会杀掉 oom_score_adj
值最高的容器,如果有多个容器的 oom_score_adj
值相同,就会杀掉内存使用量最多的容器(其实是因为内存使用量最多的容器的 oom_score 值最高)。关于 OOM 的更多内容请参考:Kubernetes 内存资源限制实战。
假设某节点运行着 4 个 Pod,且每个 Pod 中只有一个容器。每个 QoS 类型为 Burstable
的 Pod 配置的内存 requests 是 4Gi
,节点的内存大小为 30Gi
。每个 Pod 的 oom_score_adj
值如下所示:
Pod Name | Pod QoS | oom_score_adj |
---|---|---|
A | Best Effort | 1000 |
B | Guaranteed | -998 |
C | Burstable | 867(根据上面的公式计算) |
D | Best Effort | 1000 |
当调用 OOM killer 时,它首先选择 oom_score_adj
值最高的容器(1000),这里有两个容器的 oom_score_adj
值都是 1000,OOM killer 最终会选择内存使用量最多的容器。
4. 总结
- 因为 kubelet 默认每 10 秒抓取一次 cAdvisor 的监控数据,所以可能在资源使用量低于阈值时,kubelet 仍然在驱逐 Pod。
- kubelet 将 Pod 从节点上驱逐之后,Kubernetes 会将该 Pod 重新调度到另一个资源充足的节点上。但有时候 Scheduler 会将该 Pod 重新调度到与之前相同的节点上,比如设置了节点亲和性,或者该 Pod 以 Daemonset 的形式运行。
现在你应该理解了 kubelet 驱逐 Pod 的原理和过程,如果你在部署应用时设置了恰当的参数,知道了所有的可能性,你就能更好地掌控你的集群。
Kubernetes Pod 驱逐详解的更多相关文章
- Kubernetes 部署策略详解-转载学习
Kubernetes 部署策略详解 参考:https://www.qikqiak.com/post/k8s-deployment-strategies/ 在Kubernetes中有几种不同的方式发布应 ...
- kubernetes系列07—Pod控制器详解
本文收录在容器技术学习系列文章总目录 1.Pod控制器 1.1 介绍 Pod控制器是用于实现管理pod的中间层,确保pod资源符合预期的状态,pod的资源出现故障时,会尝试 进行重启,当根据重启策略无 ...
- 自动化集成:Kubernetes容器引擎详解
前言:该系列文章,围绕持续集成:Jenkins+Docker+K8S相关组件,实现自动化管理源码编译.打包.镜像构建.部署等操作:本篇文章主要描述Kubernetes引擎用法. 一.基础简介 Kube ...
- [Kubernetes]yaml文件详解
应前一段时间夸下的海口:[Kubernetes]如何使用yaml文件使得可以向外暴露服务,说过要写一篇关于yaml文件详解的文章出来的,今天来总结一下.yaml文件用在很多地方,但是这里以介绍在Kub ...
- Kubernetes Pod驱逐策略
Kubelet 能够主动监测和防止计算资源的全面短缺. 在资源短缺的情况下,kubelet 可以主动地结束一个或多个 Pod 以回收短缺的资源. 当 kubelet 结束一个 Pod 时,它将终止 P ...
- 通过describe命令学习Kubernetes的pod属性详解
我们可以首先使用kubectl get pods命令得到pod列表,比如我们想研究pod nginx-storage-pod的明细: 使用命令kubectl describe pod nginx-st ...
- 使用acs-engine在Azure中国区部署kubernetes集群详解
转载请注明出处:http://www.cnblogs.com/wayneiscoming/p/7649642.html 1. acs-engine简介 ACS是微软在2015年12月推出的一项基于容器 ...
- 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解
欢迎大家前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~ 作者:腾讯云容器服务团队 源码为 k8s v1.6.1 版本,github 上对应的 commit id 为 b0b7a323cc5a4a ...
- K8S学习笔记之Kubernetes 部署策略详解
0x00 概述 在Kubernetes中有几种不同的方式发布应用,所以为了让应用在升级期间依然平稳提供服务,选择一个正确的发布策略就非常重要了. 选择正确的部署策略是要依赖于我们的业务需求的,下面我们 ...
随机推荐
- 源码阅读 - java.util.concurrent (二)CAS
背景 在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁 锁机制存在以下问题: (1)在多线程竞争下,加锁.释放锁会导致比较多的上下文切换和调度延时,引起性能问题. ...
- Codeforces 758A:Holiday Of Equality(水题)
http://codeforces.com/problemset/problem/758/A 题意:给出n个值,求这里面每个值都要变成最大的那个数,总共需要加上多少. 思路:找出最大的直接算. #in ...
- HDU 4763:Theme Section(KMP)
http://acm.hdu.edu.cn/showproblem.php?pid=4763 Theme Section Problem Description It's time for mus ...
- SSM集合
SSM集成 1. Spring和各个框架的整合 Spring目前是JavaWeb开发中最终的框架,提供一站式服务,可以其他各个框架整合集成 Spring整合方案 1.1. SSH ssh是早期的一 ...
- Maxon Cinema 4D Studio R20.026 中文破解版下载
Maxon Cinema 4D Studio,是 Maxon 公司开发的一款专业三维工具包,如果你需要一个得力助手,轻松快速创建令人称赞的 3D 图形作品,那么这是你的最佳选择. 为何使用Cinema ...
- extern和static区别
1. 声明和定义 当定义一个变量的时候,就包含了对该变量声明的过程,同时在内存张申请了一块内存空间.如果在多个文件中使用相同的变量,为了避免重复定义,就必须将声明和定义分离开来.定义是创建与名字关 ...
- C#使用sqlite-net搭建简易的ORM
SQLite简易版ORM 首先打开项目,使用nuget搜索sqlite-net,如下图: 下载完成后,我们会多出两个文件,SQLite.cs和SQLiteAsync.cs. 我们新建一个文件夹SQLi ...
- Docker笔记(三):Docker安装与配置
原文地址:http://blog.jboost.cn/2019/07/14/docker-3.html Docker分为Docker CE社区免费版与Docker EE企业收费版.Docker EE主 ...
- ElementUI 简要源码解析——Basic篇
Layout 布局 row 布局组件中的父组件,用于控制子组件.很简单的一个布局标签,主要通过 justify 和 align 控制子元素的对齐方式,使用 render 函数通过传入的 tag 属性控 ...
- Docker学习第二天
CentOS 系列安装 Docker Docker 支持 CentOS6 及以后的版本. CentOS6 对于 CentOS6,可以使用 EPEL 库安装 Docker,命令如下 [root@MSJT ...