原文链接: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 驱逐详解的更多相关文章

  1. Kubernetes 部署策略详解-转载学习

    Kubernetes 部署策略详解 参考:https://www.qikqiak.com/post/k8s-deployment-strategies/ 在Kubernetes中有几种不同的方式发布应 ...

  2. kubernetes系列07—Pod控制器详解

    本文收录在容器技术学习系列文章总目录 1.Pod控制器 1.1 介绍 Pod控制器是用于实现管理pod的中间层,确保pod资源符合预期的状态,pod的资源出现故障时,会尝试 进行重启,当根据重启策略无 ...

  3. 自动化集成:Kubernetes容器引擎详解

    前言:该系列文章,围绕持续集成:Jenkins+Docker+K8S相关组件,实现自动化管理源码编译.打包.镜像构建.部署等操作:本篇文章主要描述Kubernetes引擎用法. 一.基础简介 Kube ...

  4. [Kubernetes]yaml文件详解

    应前一段时间夸下的海口:[Kubernetes]如何使用yaml文件使得可以向外暴露服务,说过要写一篇关于yaml文件详解的文章出来的,今天来总结一下.yaml文件用在很多地方,但是这里以介绍在Kub ...

  5. Kubernetes Pod驱逐策略

    Kubelet 能够主动监测和防止计算资源的全面短缺. 在资源短缺的情况下,kubelet 可以主动地结束一个或多个 Pod 以回收短缺的资源. 当 kubelet 结束一个 Pod 时,它将终止 P ...

  6. 通过describe命令学习Kubernetes的pod属性详解

    我们可以首先使用kubectl get pods命令得到pod列表,比如我们想研究pod nginx-storage-pod的明细: 使用命令kubectl describe pod nginx-st ...

  7. 使用acs-engine在Azure中国区部署kubernetes集群详解

    转载请注明出处:http://www.cnblogs.com/wayneiscoming/p/7649642.html 1. acs-engine简介 ACS是微软在2015年12月推出的一项基于容器 ...

  8. 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解

    欢迎大家前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~ 作者:腾讯云容器服务团队 源码为 k8s v1.6.1 版本,github 上对应的 commit id 为 b0b7a323cc5a4a ...

  9. K8S学习笔记之Kubernetes 部署策略详解

    0x00 概述 在Kubernetes中有几种不同的方式发布应用,所以为了让应用在升级期间依然平稳提供服务,选择一个正确的发布策略就非常重要了. 选择正确的部署策略是要依赖于我们的业务需求的,下面我们 ...

随机推荐

  1. 源码阅读 - java.util.concurrent (二)CAS

    背景 在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁 锁机制存在以下问题: (1)在多线程竞争下,加锁.释放锁会导致比较多的上下文切换和调度延时,引起性能问题. ...

  2. Codeforces 758A:Holiday Of Equality(水题)

    http://codeforces.com/problemset/problem/758/A 题意:给出n个值,求这里面每个值都要变成最大的那个数,总共需要加上多少. 思路:找出最大的直接算. #in ...

  3. HDU 4763:Theme Section(KMP)

    http://acm.hdu.edu.cn/showproblem.php?pid=4763 Theme Section Problem Description   It's time for mus ...

  4. SSM集合

    SSM集成   1. Spring和各个框架的整合 Spring目前是JavaWeb开发中最终的框架,提供一站式服务,可以其他各个框架整合集成 Spring整合方案 1.1. SSH ssh是早期的一 ...

  5. Maxon Cinema 4D Studio R20.026 中文破解版下载

    Maxon Cinema 4D Studio,是 Maxon 公司开发的一款专业三维工具包,如果你需要一个得力助手,轻松快速创建令人称赞的 3D 图形作品,那么这是你的最佳选择. 为何使用Cinema ...

  6. extern和static区别

    1. 声明和定义 ​ 当定义一个变量的时候,就包含了对该变量声明的过程,同时在内存张申请了一块内存空间.如果在多个文件中使用相同的变量,为了避免重复定义,就必须将声明和定义分离开来.定义是创建与名字关 ...

  7. C#使用sqlite-net搭建简易的ORM

    SQLite简易版ORM 首先打开项目,使用nuget搜索sqlite-net,如下图: 下载完成后,我们会多出两个文件,SQLite.cs和SQLiteAsync.cs. 我们新建一个文件夹SQLi ...

  8. Docker笔记(三):Docker安装与配置

    原文地址:http://blog.jboost.cn/2019/07/14/docker-3.html Docker分为Docker CE社区免费版与Docker EE企业收费版.Docker EE主 ...

  9. ElementUI 简要源码解析——Basic篇

    Layout 布局 row 布局组件中的父组件,用于控制子组件.很简单的一个布局标签,主要通过 justify 和 align 控制子元素的对齐方式,使用 render 函数通过传入的 tag 属性控 ...

  10. Docker学习第二天

    CentOS 系列安装 Docker Docker 支持 CentOS6 及以后的版本. CentOS6 对于 CentOS6,可以使用 EPEL 库安装 Docker,命令如下 [root@MSJT ...