对于内存和磁盘这种不可压缩的资源,紧缺就相当于不稳定。

驱逐策略

Kubelet 能够监控资源消耗,来防止计算资源被耗尽。一旦出现资源紧缺 的迹象,Kubelet 就会主动终止一或多个 Pod 的运行,以回收紧俏资源。当一个 Pod 被终止时,其中的容器会全部停止,Pod 状态会被置为 Failed

驱逐信号

下文中提到了一些信号,kubelet 能够利用这些信号作为决策依据来触发驱逐行为。描述列中的内容来自于 Kubelet summary API。

驱逐信号 描述
memory.available memory.available := node.status.capacity[memory] – node.stats.memory.workingSet
nodefs.available nodefs.available := node.stats.fs.available
nodefs.inodesFree nodefs.inodesFree := node.stats.fs.inodesFree
imagefs.available imagefs.available := node.stats.runtime.imagefs.available
imagefs.inodesFree imµagefs.inodesFree := node.stats.runtime.imagefs.inodesFree

上面的每个信号都支持整数值或者百分比。百分比的分母部分就是各个信号的总量。kubelet 支持两种文件系统分区。

  1. nodefs:保存 kubelet 的卷和守护进程日志等。
  2. imagefs:在容器运行时,用于保存镜像以及可写入层。

imagefs 是可选的。Kubelet 能够利用 cAdvisor 自动发现这些文件系统。Kubelet 不关注其他的文件系统。所有其他类型的配置,例如保存在独立文件系统的卷和日志,都不被支持。

因为磁盘压力已经被驱逐策略接管,因此未来将会停止对现有 垃圾收集 方式的支持。

驱逐阈(yù,音同“预”)值:

一旦超出阈值,就会触发 kubelet 进行资源回收的动作。阈值的定义方式如下:

  • 上面的表格中列出了可用的 eviction-signal.
  • 仅有一个 operator 可用:<
  • quantity 需要符合 Kubernetes 中的描述方式。

例如如果一个 Node 有 10Gi 内存,我们希望在可用内存不足 1Gi 时进行驱逐,就可以选取下面的一种方式来定义驱逐阈值:

  • memory.available<10%
  • memory.available<1Gi

驱逐软阈值

软阈值需要和一个宽限期参数协同工作。当系统资源消耗达到软阈值时,这一状况的持续时间超过了宽限期之前,Kubelet 不会触发任何动作。如果没有定义宽限期,Kubelet 会拒绝启动。

另外还可以定义一个 Pod 结束的宽限期。如果定义了这一宽限期,那么 Kubelet 会使用 pod.Spec.TerminationGracePeriodSeconds 和最大宽限期这两个值之间较小的那个(进行宽限),如果没有指定的话,kubelet 会不留宽限立即杀死 Pod。

软阈值的定义包括以下几个参数:

  • eviction-soft:描述一套驱逐阈值(例如 memory.available<1.5Gi ),如果满足这一条件的持续时间超过宽限期,就会触发对 Pod 的驱逐动作。
  • eviction-soft-grace-period:包含一套驱逐宽限期(例如 memory.available=1m30s),用于定义达到软阈值之后,持续时间超过多久才进行驱逐。
  • eviction-max-pod-grace-period:在因为达到软阈值之后,到驱逐一个 Pod 之前的最大宽限时间(单位是秒),

驱逐硬阈值

硬阈值没有宽限期,如果达到了硬阈值,kubelet 会立即杀掉 Pod 并进行资源回收。

硬阈值的定义:

  • eviction-hard:描述一系列的驱逐阈值(比如说 memory.available<1Gi),一旦达到这一阈值,就会触发对 Pod 的驱逐,缺省的硬阈值定义是:

--eviction-hard=memory.available<100Mi

驱逐监控频率

Housekeeping interval 参数定义一个时间间隔,Kubelet 每隔这一段就会对驱逐阈值进行评估。

  • housekeeping-interval:容器检查的时间间隔。

节点状况

Kubelet 会把驱逐信号跟节点状况对应起来。

如果触发了硬阈值,或者符合软阈值的时间持续了与其对应的宽限期,Kubelet 就会认为当前节点压力太大,下面的节点状态定义描述了这种对应关系。

节点状况 驱逐信号 描述
MemoryPressure memory.available 节点的可用内存达到了驱逐阈值
DiskPressure nodefs.available, nodefs.inodesFree, imagefs.available, imagefs.inodesFree 节点的 root 文件系统或者镜像文件系统的可用空间达到了驱逐阈值

Kubelet 会持续报告节点状态的更新过程,这一频率由参数 —node-status-update-frequency 指定,缺省情况下取值为 10s。

节点状况的波动

如果一个节点的状况在软阈值的上下波动,但是又不会超过他的宽限期,将会导致该节点的状态持续的在是否之间徘徊,最终会影响降低调度的决策过程。

要防止这种状况,下面的标志可以用来通知 Kubelet,在脱离压力状态之前,必须等待。

eviction-pressure-transition-period 定义了在跳出压力状态之前要等待的时间。

Kubelet 在把压力状态设置为 False 之前,会确认在周期之内,该节点没有达到逐出阈值。

回收节点级别的资源

如果达到了驱逐阈值,并且超出了宽限期,那么 Kubelet 会开始回收超出限量的资源,直到驱逐信号量回到阈值以内。

Kubelet 在驱逐用户 Pod 之前,会尝试回收节点级别的资源。如果服务器为容器定义了独立的 imagefs,他的回收过程会有所不同。

有 Imagefs

如果 nodefs 文件系统到达了驱逐阈值,kubelet 会按照下面的顺序来清理空间。

  1. 删除死掉的 Pod/容器

如果 imagefs 文件系统到达了驱逐阈值,kubelet 会按照下面的顺序来清理空间。

  1. 删掉所有无用镜像

没有 Imagefs

如果 nodefs 文件系统到达了驱逐阈值,kubelet 会按照下面的顺序来清理空间。

  1. 删除死掉的 Pod/容器
  2. 删掉所有无用镜像

驱逐用户 Pod

如果 Kubelet 无法获取到足够的资源,就会开始驱逐 Pod。

Kubelet 会按照下面的标准对 Pod 的驱逐行为进行评判:

  • 根据服务质量
  • 根据 Pod 调度请求的被耗尽资源的消耗量

接下来,Pod 按照下面的顺序进行驱逐:

  • BestEffort:消耗最多紧缺资源的 Pod 最先失败。
  • Burstable:相对请求(request)最多紧缺资源的 Pod 最先被驱逐,如果没有 Pod 超出他们的请求,策略会瞄准紧缺资源消耗量最大的 Pod。
  • Guaranteed:相对请求(request)最多紧缺资源的 Pod 最先被驱逐,如果没有 Pod 超出他们的请求,策略会瞄准紧缺资源消耗量最大的 Pod。

Guaranteed Pod 绝不会因为其他 Pod 的资源消费被驱逐。如果系统进程(例如 kubelet、docker、journald 等)消耗了超出 system-reserved 或者 kube-reserved 的资源,而且这一节点上只运行了 Guaranteed Pod,那么为了保证节点的稳定性并降低异常消费对其他 Guaranteed Pod 的影响,必须选择一个 Guaranteed Pod 进行驱逐。

本地磁盘是一个 BestEffort 资源。如有必要,kubelet 会在 DiskPressure 的情况下,kubelet 会按照 QoS 进行评估。如果 Kubelet 判定缺乏 inode 资源,就会通过驱逐最低 QoS 的 Pod 的方式来回收 inodes。如果 kubelet 判定缺乏磁盘空间,就会通过在相同 QoS 的 Pods 中,选择消耗最多磁盘空间的 Pod 进行驱逐。

有 Imagefs

如果 nodefs 触发了驱逐,Kubelet 会用 nodefs 的使用对 Pod 进行排序 – Pod 中所有容器的本地卷和日志。

如果 imagefs 触发了驱逐,Kubelet 会根据 Pod 中所有容器的消耗的可写入层进行排序。

没有 Imagefs

如果 nodefs 触发了驱逐,Kubelet 会对各个 Pod 的所有容器的总体磁盘消耗进行排序 —— 本地卷 + 日志 + 写入层。

在某些场景下,驱逐 Pod 可能只回收了很少的资源。这就导致了 kubelet 反复触发驱逐阈值。另外回收资源例如磁盘资源,是需要消耗时间的。

要缓和这种状况,Kubelet 能够对每种资源定义 minimum-reclaim。kubelet 一旦发现了资源压力,就会试着回收至少 minimum-reclaim 的资源,使得资源消耗量回到期望范围。

例如下面的配置:

--eviction-hard=memory.available<500Mi,nodefs.available<1Gi,imagefs.available<100Gi --eviction-minimum-reclaim="memory.available=0Mi,nodefs.available=500Mi,imagefs.available=2Gi"`
  • 如果 memory.available 被触发,Kubelet 会启动回收,让 memory.available 至少有 500Mi。
  • 如果是 nodefs.available,Kubelet 就要想法子让 nodefs.available 回到至少 1.5Gi。
  • 而对于 imagefs.available, kubelet 就要回收到最少 102Gi。

缺省情况下,所有资源的 eviction-minimum-reclaim 为 0。

调度器

在节点资源紧缺的情况下,节点会报告这一状况。调度器以此为信号,不再继续向此节点部署新的 Pod。

节点状况 调度行为
MemoryPressure 不再分配新的 BestEffort Pod 到这个节点
DiskPressure 不再向这一节点分配 Pod

节点的 OOM 行为

如果节点在 Kubelet 能够回收内存之前,遭遇到了系统的 OOM (内存不足),节点就依赖 oom_killer 进行响应了。

kubelet 根据 Pod 的 QoS 为每个容器设置了一个 oom_score_adj 值。

QoS oom_score_adj
Guaranteed -998
BestEffort 1000
Burstable min(max(2, 1000 - (1000 * memoryRequestBytes) / machineMemoryCapacityBytes), 999)

如果 kubelet 无法在系统 OOM 之前回收足够的内存,oom_killer 就会根据根据内存使用比率来计算 oom_score,得出结果和 oom_score_adj 相加,最后得分最高的 Pod 会被首先驱逐。

这一行为的思路是,QoS 最低,相对于调度的 Reqeust 来说又消耗最多内存的 Pod 会被首先清除,来保障内存的回收。

跟 Pod 驱逐不同,如果一个 Pod 的容器被 OOM 杀掉,他是可能被 kubelet 根据 RestartPolicy 重启的。

最佳时间

可调度的资源和驱逐策略

我们想象如下的场景:

  • 节点内存容量:10Gi
  • 保留 10% 的内存容量给系统服务(内核,kubelet 等)。
  • 在 95% 内存使用率的时候驱逐 Pod,来降低系统 OOM 的发生率。

所以我们用这样的参数启动 Kubelet:

--eviction-hard=memory.available<500Mi --system-reserved=memory=1.5Gi

这个配置中隐含了一个设定就是,系统保留涵盖了驱逐标准。

要达到这一容量,可能是有的 Pod 使用了超出其请求的数量,或者系统占用了超过 500Mi。

这样的配置保证了调度器不会向即将发生内存压力的节点分配 Pod,避免触发驱逐。

DaemonSet

因为 DaemonSet 中的 Pod 会立即重建到同一个节点,所以 Kubelet 不应驱逐 DaemonSet 中的 Pod。

但是目前 Kubelet 无法分辨一个 Pod 是否由 DaemonSet 创建。如果/当 Kubelet 能够识别这一点,那么就可以先从驱逐候选列表中过滤掉 DaemonSet 的 Pod。

一般来说,强烈建议 DaemonSet 不要创建 BestEffort Pod,而是使用 Guaranteed Pod,来避免进入驱逐候选列表。

弃用的现存回收磁盘的选项

为了保证节点的稳定性,Kubelet 已经尝试来释放磁盘空间了。

因为基于磁盘的驱逐方式已经成熟,下列的 Kubelet 参数会被标记为弃用。

现有参数 新参数
—image-gc-high-threshold —eviction-hard or eviction-soft
—image-gc-low-threshold —eviction-minimum-reclaim
—maximum-dead-containers 弃用
—maximum-dead-containers-per-container 弃用
—minimum-container-ttl-duration 弃用
—low-diskspace-threshold-mb —eviction-hard or eviction-soft
—outofdisk-transition-frequency —eviction-pressure-transition-period

已知问题

Kubelet 无法及时观测到内存压力

Kubelet 目前从 cAdvisor 定时获取内存使用状况统计。如果内存使用在这个时间段内发生了快速增长,Kubelet 就无法观察到 MemoryPressure,可能会触发 OOMKiller。我们正在尝试将这一过程集成到 memcg 通知 API 中,来降低这一延迟,而不是让内核首先发现这一情况。

如果用户不是希望获得终极使用率,而是作为一个过量使用的衡量方式,对付这一个问题的较为可靠的方式就是设置驱逐阈值为 75% 容量。这样就提高了避开 OOM 的能力,提高了驱逐的标准,有助于集群状态的平衡。

Kubelet 可能驱逐超出需要的更多 Pod

这也是因为状态搜集的时间差导致的。未来会加入功能,让根容器的统计频率和其他容器分别开来(https://github.com/google/cadvisor/issues/1247)。

Kubelet 如何在 inode 耗尽的时候评价 Pod 的驱逐

目前不可能知道一个容器消耗了多少 inode。如果 Kubelet 觉察到了 inode 耗尽,他会利用 QoS 对 Pod 进行驱逐评估。在 cadvisor 中有一个 issue,来跟踪容器的 inode 消耗,这样我们就能利用 inode 进行评估了。例如如果我们知道一个容器创建了大量的 0 字节文件,就会优先驱逐这一 Pod

本文转自中文社区-Kubelet 对资源紧缺状况的应对

Kubelet 对资源紧缺状况的应对相关推荐

  1. 带你玩转kubernetes-k8s(第61篇-Kubernetes之资源紧缺时的Pod驱逐机制)

    资源紧缺时的Pod驱逐机制 如何在系统硬件资源紧缺的情况下保证Node的稳定性,是kubelet需要解决的一个重要问题.尤其对于内存和磁盘这种不可压缩的资源,紧缺就意味着不稳定.下面对驱逐的策略.信号 ...

  2. 9.7 top:实时显示系统中各个进程的资源占用状况

    top命令 用于实时地对系统处理器状态进行监控,它能够实时地显示系统中各个进程的资源占用状况.该命令可以按照CPU的使用.内存的使用和执行时间对系统任务进程进行排序显示,同时top命令还可以通过交互式 ...

  3. 在资源使用状况视图中查看资源的负荷情况

    只有工时类资源才会出现过度分配,因为工时类资源通常指组织内部的人力资源或者机械设备等,这些资源通常都有数量上的瓶颈,也只有工时类资源才会在[资源工作表]中设置它的最大单位和资源可用性,这就限制了它在不 ...

  4. 【kubernetes/k8s源码分析】 kubelet cgroup 资源预留源码分析

    kubernetes 1.13 WHY 默认情况下 pod 能够使用节点全部可用资源.用户 pod 中的应用疯狂占用内存,pod 将与 node 上的系统守护进程和 kubernetes 组件争夺资源 ...

  5. 人民教育出版社电子课本_课本是进还是出? 开放教育资源的状况

    人民教育出版社电子课本 由于许多因素,包括希望让人们负担得起的教育费用,开放教育在K-12和高等教育领域都是一个热门话题. 教科书的成本给全世界的学生增加了巨大的经济负担. 作为回应,美国教育部于去年 ...

  6. 5月16日钢铁行业概览

    5月16日钢铁行业概览      发表日期:2007-5-16  兰格钢铁 [国内宏观]国务院办公厅下发<关于在重点行业和领域开展安全生产隐患排查治理专项行动的通知>:近日国土资源部发出& ...

  7. 全球及中国木材加工行业运行状况与投资产值预测报告2022版

    全球及中国木材加工行业运行状况与投资产值预测报告2022版 --------------------------------------------- [修订日期]:2021年11月 [搜索鸿晟信合研 ...

  8. 全球及中国再生橡胶产业发展动态及十四五运营状况分析报告2021版

    全球及中国再生橡胶产业发展动态及十四五运营状况分析报告2021版  HS--HS--HS--HS--HS--HS--HS--HS--HS--HS--HS--HS-- [修订日期]:2021年11月 [ ...

  9. 如何应对数据库CPU打满?最优解在这里...

    如何用好数据库,调校数据库使其发挥最优的性能? 如何快速诊断和应对各种原因导致的突发数据库性能问题? 如何以最低资源成本满足业务需求? ...... 这些复杂的运维难题最优解到底是什么? 今天(4月2 ...

最新文章

  1. Python可视化(matplotlib)图像之误差可视化(Visualizing Errors)
  2. Oracle树查询总结
  3. MYSQL5.7 忘记ROOT密码/初始化ROOT密码
  4. 你需要了解的纯原生JS实现带有功能的前端购物车
  5. 牛逼,这个PDF库比其它工具好用99倍
  6. 转 html中offsetTop、clientTop、scrollTop、offsetTop各属性介绍
  7. 关于docker环境下mysql的使用相关
  8. 关于MQTT协议的说明
  9. 了解关联、聚合和组合
  10. jdbc与java数据库编程_JDBC与JAVA数据库编程
  11. 【Linux 驱动】第十章 中断处理
  12. webrtc 渲染_WebRTC 开发(六)摄像头采集与视频渲染分析
  13. 二维小游戏,飞机大战,图片素材
  14. linux服务器上有些文件看不到,linux执行脚本时找不到文件怎么解决
  15. UWB是什么技术,主要的技术特点是什么?
  16. RTX客户端插件编程:修改VC插件dll文件的uuid
  17. Java 快乐练习口算
  18. 今天那个劝比尔盖茨退学的人死了
  19. 鸿蒙开发中vp和fp是啥?
  20. 你视人家为人脉,人家视你为韭菜

热门文章

  1. 利用bwm-ng 实时监控系统
  2. Kubernetes-2018干货盘点
  3. OSI 七层网络协议的定义与理解
  4. 【组合数学+动态规划】在如下8*6的矩阵中,请计算从A移动到B一共有____种走法。要求每次只能向上或向右移动一格,并且不能经过P。...
  5. 非常实用的Android Studio快捷键
  6. 从有限状态机(FSM)到行为树(Behavior Tree)(1)
  7. windows 网络编程报错 error LNK2019
  8. 树莓派(Raspberry Pi)搭建简单的lamp服务
  9. 【three.js详解之一】入门篇
  10. MySQL日志及主从复制实现