图文轻松说透 K8S Pod 各种驱逐场景

图文轻松说透 K8S Pod 各种驱逐场景_Kubernetes

Kubernetes Pod 被驱逐是什么意思?

它们被终止,通常是没有足够资源的结果。但是为什么会这样呢?

驱逐是指派给节点的Pod 被终止的过程。Kubernetes 中最常见的情况之一是Preemption,为了在资源有限的节点中调度新的 Pod,需要终止另一个 Pod 以释放资源。

此外,Kubernetes 会不断检查资源并在需要时驱逐 Pod,这个过程称为节点压力驱逐

在本文中,您将发现:

文章目录

  • ​​图文轻松说透 K8S Pod 各种驱逐场景​​
  • ​​Pod 被驱逐的原因:抢占和节点压力​​
  • ​​抢占式驱逐​​
  • ​​Pod 调度​​
  • ​​过滤​​
  • ​​计分​​
  • ​​Pod 优先级​​
  • ​​优先级示例​​
  • ​​节点压力驱逐​​
  • ​​服务质量等级​​
  • ​​Guaranteed​​
  • ​​Burstable​​
  • ​​BestEffort​​
  • ​​其他类型的驱逐​​
  • ​​API 发起的驱逐​​
  • ​​基于污点的驱逐​​
  • ​​node 级别排空(drain)​​
  • ​​Prometheus 中的 Pod 驱逐监控​​
  • ​​结论​​
  • ​​说明​​

Pod 被驱逐的原因:抢占和节点压力

在 Kubernetes 中发生 Pod 驱逐的原因有多种。最重要的是:

  • 抢占
  • 节点压力驱逐

抢占式驱逐

抢占是这样一个过程:如果一个新的 Pod 需要被调度,但是没有任何合适的节点拥有足够的资源,那么 kube-scheduler 将通过驱逐(终止)一些优先级较低的 Pod 来检查新的 Pod 是否可以成为那个节点的一部分。

我们先了解一下 Kubernetes 调度是如何工作的。

Pod 调度

Kubernetes调度是将 Pod分配给节点的过程。

默认情况下,有一个 Kubernetes 实体负责调度,称为​​kube-scheduler​​将在控制平面中运行。Pod 将以 Pending 状态启动,直到找到匹配的节点。

将 Pod 分配给节点的过程遵循以下顺序:

  1. 过滤
  2. 计分

过滤

过滤步骤中,​kube-scheduler​​将选择当前 Pod 可能放置的所有节点。此处将考虑 Taints 和 Tolerations 等功能。完成后,它将有一个适合该 Pod 的节点列表。

计分

评分步骤中,​kube-scheduler​​将获取上一步的结果列表并为每个节点分配一个分数。这样,候选节点从最适合到最不适合排序。如果两个节点的分数相同,kube-scheduler 会随机对它们进行排序。

图文轻松说透 K8S Pod 各种驱逐场景_云计算_02

但是,如果没有适合 Pod 运行的节点怎么办?

在这种情况下,Kubernetes 将启动抢占过程,尝试驱逐优先级较低的 Pod,以便分配新的 Pod。

Pod 优先级

在抢占过程中如何防止特定 Pod 被驱逐?

很有可能,一个特定的 Pod 对你来说很重要,永远不应该被终止。

这就是 Kubernetes 具有Priority Classes的原因。

优先级类是一个 Kubernetes 对象,它允许我们将数字优先级值映射到特定的 Pod。那些具有更高价值的 Pod 被归类为更重要并且不太可能被驱逐。

您可以使用以下方式查询当前的优先级:

kubectl get priorityclasses
kubectl get pc

NAME VALUE GLOBAL-DEFAULT AGE
system-cluster-critical 2000000000 false 2d
system-node-critical 2000001000 false 2d

优先级示例

让我们使用 Lovenstein 先生的 Berry Club 漫画做一个实际的例子:

​https://www.mrlovenstein.com/​​ https://tapas.io/episode/220482

共有三个 Pod 分别代表蓝莓、树莓和草莓:

NAME         READY   STATUS             RESTARTS   AGE
blueberry 1/1 Running 0 4h41m
raspberry 1/1 Running 0 58m
strawberry 1/1 Running 0 5h22m

并且有两个优先等级:真莓和假莓。第一个将具有更高的值,表示更高的优先级。

apiVersion: /v1
kind: PriorityClass
metadata:
name: trueberry
value: 1000000
globalDefault: false
description: "This fruit is a true berry"

apiVersion: /v1
kind: PriorityClass
metadata:
name: falseberry
value: 5000
globalDefault: false
description: "This fruit is a false berry"
  • 蓝莓 将具有 trueberry 优先级(值 = 1000000)
  • 树莓和草莓都将具有 falseberry 优先级(值 = 5000)

这意味着在抢占的情况下,树莓和草莓更有可能被驱逐,为更高优先级的 Pod 腾出空间。

然后通过将此添加到 Pod 定义来将优先级类分配给 Pod:

priorityClassName: trueberry

现在让我们尝试再添加三种水果,但要稍加改动。所有新水果都将包含更高的优先级,称为​​trueberry​​。

由于三个新水果有节点无法满足的内存或 CPU 要求,​​kubelet​​驱逐所有优先级低于新水果的 Pod。Blueberry 保持运行,因为它具有更高的优先级。

NAME         READY   STATUS             RESTARTS   AGE
banana 0/1 ContainerCreating 0 2s
blueberry 1/1 Running 0 4h42m
raspberry 0/1 Terminating 0 59m
strawberry 0/1 Terminating 0 5h23m
tomato 0/1 ContainerCreating 0 2s
watermelon 0/1 ContainerCreating 0 2s

图文轻松说透 K8S Pod 各种驱逐场景_docker_03

这是最终结果:

NAME         READY   STATUS             RESTARTS   AGE
banana 1/1 Running 0 3s
blueberry 1/1 Running 0 4h43m
tomato 1/1 Running 0 3s
watermelon 1/1 Running 0 3s

节点压力驱逐

除了抢占,Kubernetes 还会不断检查节点资源,如磁盘压力、CPU 或内存不足 (OOM)。

如果节点中的资源(如CPU内存)消耗达到某个阈值,​​kubelet​​将开始驱逐 Pod 以释放资源。将考虑服务质量 (QoS) 来确定驱逐顺序。

服务质量等级

在 Kubernetes 中,Pod 提供三个QoS 类之一,这将定义在缺乏资源的情况下它们被驱逐的可能性,从不太可能到更有可能:

  • Guaranteed 有保证的
  • Burstable 可爆发的
  • BestEffort 尽最大努力

这些 QoS 等级是如何分配给 Pod 的?

这是基于对 ​​CPU和内存的限制和请求​​。提醒一句:

  • Limits 限制:容器可以使用的最大资源量。
  • Requests 请求:容器运行所需的最小资源量。

有关限制和请求的更多信息,请查看通过示例了解 Kubernetes 限制和请求

​https://sysdig.com/blog/kubernetes-limits-requests/​

图文轻松说透 K8S Pod 各种驱逐场景_云计算_04

Guaranteed

如果满足以下条件,Pod 将分配有保证的 QoS 等级:

  • Pod 中的所有容器都为 CPU 和内存设置了限制和请求。
  • Pod 中的所有容器都具有相同的 CPU Limit 和 CPU Request 值。
  • Pod 中所有容器都具有相同的 memory Limit 和 memory Request 值

Guaranteed Pod 在正常情况下不会被驱逐。

Burstable

如果满足以下条件,Pod 将分配有可突发的 QoS 等级:

  • 它没有 Guaranteed QoS 等级。
  • 已为 Pod 中的容器设置了 Limits 或 Requests 。

Burstable Pod 可以被驱逐,但比下一个类别更不可能。

BestEffort

如果出现以下情况,Pod 将分配有 BestEffort 的 QoS 等级:

  • Pod 中的任何容器都没有设置限制和请求。

在发生节点压力过程的情况下,BestEffort Pod 被驱逐的可能性最大。

重要提示:Limits 和 Requests 中可能还有其他资源,如 ephemeral-storage,但它们不用于 QoS Class 计算。

图文轻松说透 K8S Pod 各种驱逐场景_docker_05

如前所述,QoS 类将被考虑用于节点压力驱逐。这是内部发生的过程。

kubelet 按照以下顺序对要驱逐的 Pod 进行排序:

  1. ​BestEffort 或 Burstable​​使用量超过 requests 的 Pod
  2. ​Burstable​​​使用量低于 requests 的 Pod 或者 ​​Guaranteed​​Pod

Kubernetes 将优先从第 1 组中驱逐 Pod,然后才会尝试在第 2 组驱逐。

上面的一些要点:

  • 如果您在容器中添加非常低的请求,它们的 Pod 可能会被分配到组 1,这意味着它更有可能被驱逐。
  • 你无法判断哪个特定的 Pod 将被驱逐,只是 Kubernetes 会尝试在第 2 组之前驱逐第 1 组中的 Pod。
  • ​Guaranteed​​​Pod 通常不会被驱逐:​​kubelet​​​不会为了安排其他 Pod 而驱逐它们。但是如果某些系统服务需要更多资源,kubelet 将在必要时终止​​Guaranteed Pod​​。

其他类型的驱逐

本文重点介绍抢占和节点压力驱逐,但 Pod 也可以通过其他方式驱逐。例子包括:

API 发起的驱逐

可以使用 Kubernetes Eviction API 请求按需驱逐一个节点中的 Pod。

​https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#create-eviction-pod-v1-core​

#公众号:进击云原生 注:
请记住,Eviction API 不同于 Delete Pod,前者是 CREATE 动作,请求会创建 pods/eviction 子资源,后者是 DELETE 动作请求

基于污点的驱逐

借助 Kubernetes Taints and Tolerations,您可以指导如何将 Pod 分配给节点。但是,如果您​​NoExecute​​对现有节点应用污点,所有不能容忍它的 Pod 将立即被驱逐。

node 级别排空(drain)

有时节点变得不可用或者不想再在这些节点上工作时。​​kubectl cordon​​​命令会阻止在其上安排新的 Pod,运行​​kubectl drain nodename​​也可以一次完全清空所有当前节点上 Pod。节点中的所有 Pod 都将被驱逐,遵守其正常终止限期。

Prometheus 中的 Pod 驱逐监控

可以使用 Prometheus 通过执行以下操作轻松监控 Pod 驱逐:

kube_pod_status_reason{reason="Evicted"} > 0

图文轻松说透 K8S Pod 各种驱逐场景_Kubernetes_06

这将显示集群中所有被驱逐的 Pod。您还可以将它与 ​​kube_pod_status_phase{phase="Failed"}​​结合,以提醒那些在 Pod 出现故障后被驱逐的。

如果想深入挖掘,请查看以下有关在 Prometheus 中监控资源的文章:

  • 如何调整 Kubernetes 资源限制

​https://sysdig.com/blog/kubernetes-resource-limits/​

  • Kubernetes 容量规划:如何调整集群请求的大小

​https://sysdig.com/blog/kubernetes-capacity-planning/​

结论

在​​抢占(preemption)​​​期间,Kubernetes 将尝试通过驱逐优先级较低的 Pod 释放资源,来安排新的 Pod 。使用​​优先级类别(Priority Classes)​​,可以控制哪些 Pod 在抢占时更有可能继续运行,因为它们被驱逐的可能性较小。

在执行期间,Kubernetes 将检查节点压力并在需要时驱逐 Pod。使用 ​​QoS classes​​,可以控制在节点压力的情况下哪些 Pod 更有可能被驱逐。

内存和 CPU 是节点中的重要资源,您需要配置 Pod、容器和节点以使用适量的内存和 CPU。如果您合理地管理这些资源,不仅可以降低成本,还可以确保重要流程无论如何都能继续运行。

说明

请关注 危 ❤ 工中号【进击云原生】,更有free资源供您学习

本文由​​mdnice​​多平台发布