如何查看应用于 Kubernetes 节点的污点

KubernetesBeginner
立即练习

简介

Kubernetes,这个流行的容器编排平台,提供了一个强大的特性,称为“污点”(taints),用于控制 Pod 在节点上的调度。在本教程中,我们将探讨如何查看应用于 Kubernetes 节点的污点,这是有效管理 Kubernetes 集群的一项基本技能。

污点允许你使用特定的属性标记节点,这些属性可以排斥某些 Pod,确保工作负载根据节点的功能和资源得到适当的调度。了解如何查看和使用污点,有助于你在 Kubernetes 环境中保持最佳的资源分配。

设置用于测试的 Kubernetes 环境

在查看 Kubernetes 节点上的污点之前,我们需要一个正常运行的 Kubernetes 环境。对于本教程,我们将使用 Minikube,它提供了一个轻量级的本地 Kubernetes 集群,用于开发和测试目的。

让我们从安装 Minikube 开始:

curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
rm minikube-linux-amd64

现在 Minikube 已经安装好了,让我们启动一个 Kubernetes 集群:

minikube start --driver=docker

你应该看到类似这样的输出:

😄  minikube v1.29.0 on Ubuntu 22.04
✨  Using the docker driver based on user configuration
📌  Using Docker driver with root privileges
👍  Starting control plane node minikube in cluster minikube
🚜  Pulling base image ...
🔥  Creating docker container (CPUs=2, Memory=2200MB) ...
🐳  Preparing Kubernetes v1.26.1 on Docker 23.0.1 ...
    ▪ Generating certificates and keys ...
    ▪ Booting up control plane ...
    ▪ Configuring RBAC rules ...
🔎  Verifying Kubernetes components...
    ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟  Enabled addons: default-storageclass, storage-provisioner
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default

让我们通过检查节点状态来验证集群是否正在运行:

kubectl get nodes

你应该看到类似这样的输出:

NAME       STATUS   ROLES           AGE    VERSION
minikube   Ready    control-plane   1m     v1.26.1

太棒了!我们现在有了一个可以运行的 Kubernetes 环境来探索污点。kubectl 命令已经配置为与我们的 Minikube 集群一起工作。

理解 Kubernetes 污点

在开始查看污点之前,让我们先了解一下它们是什么,以及它们在 Kubernetes 中是如何工作的。

什么是污点?

污点是应用于 Kubernetes 节点的属性,允许节点排斥某些 Pod。可以将污点想象成标记节点不适合特定类型工作负载的标签。

污点与一个称为“容忍度”(tolerations)的概念一起工作。虽然污点应用于节点,但容忍度应用于 Pod。具有与节点污点匹配的容忍度的 Pod 可以在该被污点标记的节点上被调度。

污点结构

污点由三个部分组成:

  1. 键(Key):一个标识污点的字符串(例如,gpudisknetwork
  2. 值(Value):分配给键的可选字符串(例如,truehigh-performance
  3. 影响(Effect):定义如何处理没有匹配容忍度的 Pod

最常见的污点影响有:

  • NoSchedule:没有匹配容忍度的新 Pod 将不会被调度到该节点上
  • PreferNoSchedule:系统将尝试避免将没有匹配容忍度的 Pod 放置在该节点上,但不能保证
  • NoExecute:没有匹配容忍度的新 Pod 将不会被调度到该节点上,并且没有匹配容忍度的现有 Pod 将被驱逐

以下是污点的语法:

  • 带值:key=value:effect
  • 无值:key:effect

Kubernetes 集群中的某些节点具有默认污点。例如,控制平面节点通常被污点标记为 node-role.kubernetes.io/control-plane:NoSchedule,以防止常规工作负载在它们上面被调度,从而为系统组件保留资源。

让我们检查一下我们的 Minikube 节点,看看它是否有任何默认污点:

kubectl describe node minikube | grep -A3 Taints

你可能会看到类似这样的输出:

Taints:             node-role.kubernetes.io/control-plane:NoSchedule
Unschedulable:      false
Lease:
  HolderIdentity:  minikube

此输出显示我们的 Minikube 节点有一个污点,阻止常规 Pod 在其上被调度,因为它是一个控制平面节点。

查看 Kubernetes 节点上的污点

现在我们了解了什么是污点,让我们探索查看应用于 Kubernetes 节点的污点的不同方法。

方法 1:使用 kubectl describe

查看节点上污点的最详细方法是使用 kubectl describe node 命令:

kubectl describe node minikube

此命令输出有关节点的全面信息。要仅关注污点,你可以使用 grep

kubectl describe node minikube | grep -A1 Taints

示例输出:

Taints:             node-role.kubernetes.io/control-plane:NoSchedule
Unschedulable:      false

方法 2:使用带有自定义列的 kubectl get

你可以使用带有自定义输出列的 kubectl get nodes 命令,仅显示污点:

kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints

示例输出:

NAME       TAINTS
minikube   [map[effect:NoSchedule key:node-role.kubernetes.io/control-plane]]

方法 3:使用带有 JSONPath 的 kubectl get

另一种方法是使用 JSONPath 提取污点信息:

kubectl get nodes minikube -o jsonpath='{.spec.taints}'

示例输出:

[{"effect":"NoSchedule","key":"node-role.kubernetes.io/control-plane"}]

为了更好的可读性,你可以将输出格式化为 JSON:

kubectl get nodes minikube -o jsonpath='{.spec.taints}' | jq .

如果你没有安装 jq,你可以使用以下命令安装它:

sudo apt-get update && sudo apt-get install -y jq

示例格式化输出:

[
  {
    "effect": "NoSchedule",
    "key": "node-role.kubernetes.io/control-plane"
  }
]

方法 4:使用带有 YAML 输出的 kubectl get

你还可以以 YAML 格式查看完整的节点规范并搜索污点:

kubectl get node minikube -o yaml | grep -A5 taints:

示例输出:

  taints:
  - effect: NoSchedule
    key: node-role.kubernetes.io/control-plane
  unschedulable: false
status:
  addresses:

这些方法中的每一种都以不同的格式提供相同的信息。根据可读性以及你计划如何使用这些信息,选择最适合你需求的方法。

添加和移除污点

现在我们知道了如何查看污点,让我们学习如何添加和移除它们。当你需要控制 Pod 调度或为节点进行维护做准备时,这是一个常见的操作。

向节点添加污点

向节点添加污点的语法是:

kubectl taint nodes <node-name> <key>=<value>:<effect>

让我们向我们的 Minikube 节点添加一个污点,将其标记为具有 GPU:

kubectl taint nodes minikube gpu=true:NoSchedule

你应该看到类似这样的输出:

node/minikube tainted

现在,让我们验证污点是否已添加:

kubectl describe node minikube | grep -A3 Taints

示例输出:

Taints:             gpu=true:NoSchedule
                    node-role.kubernetes.io/control-plane:NoSchedule
Unschedulable:      false
Lease:

正如你所看到的,我们的节点现在有两个污点:原始的控制平面污点和我们新的 GPU 污点。

从节点移除污点

要移除污点,你需要在相同的污点定义后添加一个减号(-):

kubectl taint nodes <node-name> <key>=<value>:<effect>-

让我们移除我们刚刚添加的 GPU 污点:

kubectl taint nodes minikube gpu=true:NoSchedule-

你应该看到类似这样的输出:

node/minikube untainted

让我们验证污点是否已移除:

kubectl describe node minikube | grep -A3 Taints

示例输出:

Taints:             node-role.kubernetes.io/control-plane:NoSchedule
Unschedulable:      false
Lease:
  HolderIdentity:  minikube

现在我们的节点又只剩下控制平面污点了。

何时使用污点

污点在以下几种情况下特别有用:

  1. 专用硬件:使用专用硬件(如 GPU)对节点进行污点标记,以确保仅调度需要该硬件的工作负载
  2. 节点维护:在执行维护之前添加污点,以防止调度新的 Pod
  3. 安全隔离:出于安全原因,将某些工作负载与其他工作负载分开
  4. 资源优化:将节点专用于特定工作负载类型,以实现最佳资源利用率

通过了解如何查看、添加和移除污点,你已经获得了在 Kubernetes 集群中管理 Pod 调度的基本知识。

使用容忍度(Tolerations)

现在我们了解了污点的工作原理,让我们探索容忍度——允许 Pod 在带有匹配污点的节点上调度的机制。

理解容忍度

容忍度在 Pod 规范中指定,并允许 Pod 在具有匹配污点的节点上调度。一个容忍度由以下部分组成:

  • key:匹配污点键
  • operatorEqual(匹配键和值)或 Exists(仅匹配键)
  • value:要匹配的值(使用 Equal 运算符时)
  • effect:要匹配的 effect,或为空以匹配所有 effect
  • tolerationSeconds:可选的持续时间,Pod 可以在具有匹配的 NoExecute 污点的节点上停留

创建一个带有容忍度的 Pod

让我们创建一个容忍我们的控制平面污点的 Pod。首先,让我们为我们的 Pod 创建一个 YAML 文件:

nano ~/project/toleration-pod.yaml

现在,将以下内容添加到文件中:

apiVersion: v1
kind: Pod
metadata:
  name: toleration-pod
spec:
  containers:
    - name: nginx
      image: nginx:latest
  tolerations:
    - key: "node-role.kubernetes.io/control-plane"
      operator: "Exists"
      effect: "NoSchedule"

此 Pod 规范包含一个容忍度,该容忍度与我们节点上的控制平面污点匹配。保存并退出文件(在 nano 中,按 Ctrl+OEnter,然后 Ctrl+X)。

现在,让我们创建 Pod:

kubectl apply -f ~/project/toleration-pod.yaml

你应该看到类似这样的输出:

pod/toleration-pod created

让我们检查 Pod 是否已在我们的节点上调度:

kubectl get pods -o wide

示例输出:

NAME             READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
toleration-pod   1/1     Running   0          12s   10.244.0.5   minikube   <none>           <none>

Pod 正在我们的 minikube 节点上运行,因为它有一个与控制平面污点匹配的容忍度。

使用没有容忍度的 Pod 进行测试

为了进行比较,让我们创建一个没有容忍度的 Pod:

nano ~/project/no-toleration-pod.yaml

添加以下内容:

apiVersion: v1
kind: Pod
metadata:
  name: no-toleration-pod
spec:
  containers:
    - name: nginx
      image: nginx:latest

保存并退出文件,然后创建 Pod:

kubectl apply -f ~/project/no-toleration-pod.yaml

现在,让我们检查 Pod 的状态:

kubectl get pods -o wide

你可能会注意到 Pod 仍然处于 Pending 状态:

NAME               READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
no-toleration-pod  0/1     Pending   0          12s   <none>       <none>     <none>           <none>
toleration-pod     1/1     Running   0          2m    10.244.0.5   minikube   <none>           <none>

让我们检查 Pod 为什么处于 Pending 状态:

kubectl describe pod no-toleration-pod

在 events 部分,你应该看到类似这样的内容:

Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  45s   default-scheduler  0/1 nodes are available: 1 node(s) had untolerated taint {node-role.kubernetes.io/control-plane: }. preemption: 0/1 nodes are available: 1 Preemption is not helpful for scheduling.

这证实了 Pod 无法被调度,因为它不容忍控制平面污点。

清理

让我们清理我们创建的 Pod:

kubectl delete pod toleration-pod no-toleration-pod

你应该看到:

pod "toleration-pod" deleted
pod "no-toleration-pod" deleted

恭喜你!你现在了解了污点和容忍度如何协同工作以控制 Kubernetes 中的 Pod 调度。

总结

在这个实践实验中,你学习了如何使用 Kubernetes 污点和容忍度,这是控制集群中 Pod 调度的关键特性。以下是你完成的内容:

  1. 使用 Minikube 设置 Kubernetes 环境
  2. 理解污点的概念及其对 Pod 调度的影响
  3. 探索了在 Kubernetes 节点上查看污点的不同方法
  4. 使用 kubectl 命令从节点添加和移除污点
  5. 创建了带有和不带有容忍度的 Pod,以了解它们如何与被污点标记的节点交互

这些技能对于管理 Kubernetes 集群中的工作负载放置和资源分配至关重要。通过正确使用污点和容忍度,你可以确保 Pod 根据硬件要求、工作负载特征和资源限制在适当的节点上调度。

在你继续 Kubernetes 之旅的过程中,你可以基于这些知识构建更复杂的调度策略,例如节点亲和性和反亲和性,以进一步优化你的集群资源。