Kubernetes Pod 驱逐指南

了解 Kubernetes 如何确定 Pod 驱逐的优先级可以帮助更有效地平衡资源。
36 位读者喜欢这篇文章。
Parts, modules, containers for software

Opensource.com

Kubernetes 的优势之一是调度。它可以处理应用程序 Pod 在集群节点中的放置及其资源分配,因此您无需担心自己平衡资源。当资源耗尽时,Kubernetes 可以驱逐 Pod——但 Kubernetes 如何决定驱逐哪个 Pod 呢?

Kubernetes Pod 和资源

虽然一个 Pod 可以容纳多个容器,但为了本文的目的,我将它们作为一个单独的对象进行讨论。

在 Kubernetes 中,您可以定义 Pod 对 CPU(计算)和内存的需求。CPU 以单位衡量:1 个 CPU 等于 1 个云 vCPU 或裸机上的 1 个超线程。内存以字节为单位衡量(例如,Mi 代表兆字节,Gi 代表千兆字节,等等)。

Pod 执行所需的最小资源量在 YAML 的 requests 部分中定义。为了防止使用节点的所有资源,YAML 的 limits 部分定义了最大资源使用量。这是一个示例

apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: app
    image: images.my-company.example/app:v4
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

当 Kubernetes 调度器想要将 Pod 放置在节点上时,它首先确认哪个节点具有可用的资源来满足其请求。注意:如果您的节点上有未定义请求的 Pod,Kubernetes 将不会考虑它们,这可能会导致故障。

资源有两种类型:弹性资源和精确资源。CPU 是一种弹性资源,可以超额配置。即使应用程序没有获得请求的 CPU 资源,它们也可以继续运行,但性能会降低。另一方面,内存是一种精确资源:应用程序无法在没有请求的量的情况下运行。如果我的 Pod 请求 1G 内存,但只能获得 0.8G,则当它尝试分配全部内存时,会因内存分配错误而失败。

Limits 的功能与 requests 不同。Limits 仅在节点 CPU 负载过高时(即 CPU 使用率达到 100%)才适用于 CPU。这是一种常见情况,本地节点操作系统可以处理它。但是,如果 Pod 超出了其内存限制,它将被内存不足 (OOM) 杀手终止。

何时发生驱逐?

这种差异与 Kubernetes 处理资源压力的方式有关。如果节点资源耗尽,Kubernetes 需要驱逐 Pod,这种事件称为节点压力驱逐。当 CPU 完全利用时,节点调度器可以处理它,因此不会发生驱逐。但是,如果可用内存不足,则需要从节点中驱逐 Pod 并尝试将它们放置在另一个节点中。这称为由于内存压力而导致的驱逐。磁盘空间不足也可能导致节点压力驱逐。

Kubernetes 如何决定驱逐哪些 Pod?

Pod 的驱逐取决于导致节点压力的资源,例如内存或磁盘空间。首先要驱逐的是处于失败状态的 Pod,因为它们没有运行,但仍可能在使用资源。在此之后,Kubernetes 会评估正在运行的 Pod。

驱逐消耗最多内存的 Pod 行不通,因为它很可能是一个活动的 Pod,并且更难放置。相反,Kubernetes 会查看两个不同的类别来做出此决定:QoS(服务质量)类和优先级类。

QoS 类

Kubernetes 有三个可以分配给 Pod 的 QoS 类

Guaranteed(保证):对于 Pod 中的每个容器

  • 必须有内存限制和内存请求。
  • 内存限制必须等于内存请求。
  • 必须有 CPU 限制和 CPU 请求。
  • CPU 限制必须等于 CPU 请求。

Burstable(突发):Pod 不符合 QoS 类 Guaranteed 的标准,但 Pod 中至少有一个容器具有内存或 CPU 请求

BestEffort(尽力而为):Pod 必须没有任何容器具有内存或 CPU 限制或请求。

Pod QoS 类由其最低容器 QoS 类决定。

优先级类

Pod 的优先级类定义了 Pod 相对于集群中运行的其他 Pod 的重要性:优先级越高,Pod 越重要。Kubernetes 在尝试调度 Pod 时使用优先级类。如果无法调度,它将驱逐优先级较低的 Pod,以便为其腾出空间。

您可以使用以下类别设置 Pod 抢占(驱逐)策略

  • Never(永不):此 Pod 具有高优先级,但 Kubernetes 不应驱逐其他 Pod 来运行它。此 Pod 可以被驱逐以运行更高优先级的 Pod。
  • PreemptLowerPriority(抢占较低优先级):驱逐优先级较低的 Pod 以运行此 Pod

Pod 优先级类由其最低容器优先级类决定。

云平台 OKD(以前称为 Minishift,是 Red Hat OpenShift 的基础)具有三个内置优先级类

  • system-node-critical(系统节点关键):永远不应从节点中驱逐的 Pod
  • system-cluster-critical(系统集群关键):对集群很重要且可以从节点中驱逐的 Pod,但仅在特定情况下
  • cluster-logging(集群日志记录):必须优先于其他应用程序调度的 Pod

使用类对驱逐进行排序

对于磁盘压力,Kubernetes 仅使用 Pod 的优先级类对其驱逐进行排序,因为在调度 Pod 之前没有预先请求资源量的机制。因此,使用基于 CSI 的本地持久卷而不是主机路径来存储 Pod 的数据非常重要。

对于内存压力,Kubernetes 将尝试驱逐那些使用量超过请求的 Pod,同时考虑 Pod 的优先级类,顺序如下

  1. QoS 类为 BestEffort 的 Pod 没有任何请求,因此始终被考虑驱逐。
  2. 如果在驱逐 BestEffort 类 Pod 后压力仍然存在,则根据 Pod 的优先级类驱逐 Pod。具有相同优先级的 Pod 根据其使用级别超过请求的量来驱逐。
  3. 如果仍然存在压力,Kubernetes 将考虑驱逐 Guaranteed Pod 和未超出请求的 Burstable Pod。这些 Pod 根据其优先级驱逐。

防止 Pod 驱逐

如何降低您的重要 Pod 被驱逐的几率?

  • 始终分配优先级类,因为 Kubernetes 会同时考虑内存压力和磁盘压力。
  • 避免使用 QoS 类为 BestEffort 的 Pod。
  • 对于内存使用量固定的 Pod,请使用 Guaranteed QoS 类。我不建议对每个 Pod 都使用它,因为它可能导致内存使用效率低下。大多数应用程序在加载时会使用最多的内存。将请求设置为等于限制可能意味着设置更高的请求以允许 Pod 获得最大内存量,或者降低限制以使您的应用程序不会获得更多内存。

如果您有兴趣了解更多关于 Pod 调度和驱逐的信息,您可以浏览 Kubernetes 文档

接下来阅读什么
标签
User profile image.
Orit 是一位经验丰富的软件工程师,对开源和基础设施充满热情,在分布式系统和存储方面拥有丰富的经验。她是 Red Hat 的 OpenShift Data Foundation 架构师,专注于容器、混合云、多云和边缘的存储。

评论已关闭。

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.