K8s--调度管理:node节点、Pod亲和性、污点与容忍

目录

一、node节点选择器

1、nodeName

案例:

2、nodeSelector

案例

二、Pod亲和性

[1、 案例演示](#1、 案例演示)

pod节点亲和性

[2.2 pod节点反亲和性](#2.2 pod节点反亲和性)

[2.3 换一个topologykey](#2.3 换一个topologykey)

详细说明:

三、污点与容忍

1、污点(Taints)

1.1、查看污点

1.2、污点类别

1.3、设置污点

1.4、删除污点

1.5、污点测试

2、容忍(Toletations)

2.1、配置项

2.2、设置容忍

[2.3、Equal 与 Exists](#2.3、Equal 与 Exists)


一、node节点选择器

我们在创建pod资源的时候,pod会根据schduler进行调度,那么默认会调度到随机的一个工作节点,如果我们想要pod调度到指定节点或者调度到一些具有相同特点的node节点,怎么办呢?

可以使用pod中的nodeName或者nodeSelector字段指定要调度到的node节点。

1、nodeName

指定pod节点运行在哪个具体node上

案例:

编辑yaml文件

创建pod

cpp 复制代码
[root@k8s-master pvc]# vim pod-node.yaml
apiVersion: v1
kind: Pod
metadata:
  name: demo-pod1
  namespace: default
  labels:
    app: myapp
    env: dev
spec:
  nodeName: k8s-node1    ##指向node节点的host主机名
  containers:
  - name:  nginx-nodename
    ports:
    - containerPort: 80
    image: nginx
    imagePullPolicy: IfNotPresent

提交

cpp 复制代码
[root@k8s-master pvc]# kubectl apply -f pod-node.yaml 
pod/demo-pod1 created

查看pod运行在哪个节点

cpp 复制代码
[root@k8s-master pvc]# kubectl get pod demo-pod1 -o wide
NAME        READY   STATUS    RESTARTS   AGE   IP              NODE        NOMINATED NODE   READINESS GATES
demo-pod1   1/1     Running   0          22s   10.244.36.106   k8s-node1   <none>  

2、nodeSelector

案例

指定pod调度到具有哪些标签的node节点上

cpp 复制代码
#给node节点打标签,打个具有disk=ceph的标签
[root@k8s-master ~]# kubectl label nodes k8s-node1 node=worker01
#查看节点的详细信息
[root@hd1 node]# kubectl describe nodes k8s-node1
#定义pod的时候指定要调度到具有 node=worker01标签的node上
cpp 复制代码
[root@k8s-master pvc]# vim pod-1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: demo-pod-1
  namespace: default
  labels:
    app: myapp1
    env: dev
spec:
  nodeSelector:
    node: worker01  
  containers:
  - name: nginx-nodename1  
    ports:
    - containerPort: 8080
      protocol: TCP  
    image: nginx
    imagePullPolicy: IfNotPresent 

提交

cpp 复制代码
[root@k8s-master pvc]# kubectl apply -f pod-1.yaml 
pod/demo-pod-1 created

查看pod是否运行在k8s-node1节点

cpp 复制代码
[root@k8s-master pvc]# kubectl get po demo-pod-1 -o wide
NAME         READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
demo-pod-1   1/1     Running   0          72s   10.244.36.85   k8s-node1   <none>           <none>

labels位置(标签),添加了标签 node=worker01

二、Pod亲和性

生产上为了保证应用的高可用性,需要将同一应用的不同pod分散在不同的宿主机上,以防宿主机出现宕机等情况导致pod重建,影响到业务的连续性。要想实现这样的效果,需要用到k8s自带的pod亲和性和反亲和性特性。

Pod 的亲和性与反亲和性有两种类型:

复制代码
requiredDuringSchedulingIgnoredDuringExecution ##一定满足
preferredDuringSchedulingIgnoredDuringExecution ##尽量满足

**podAffinity(亲和性):**pod和pod更倾向腻在一起,把相近的pod结合到相近的位置,如同一区域,同一机架,这样的话pod和pod之间更好通信,比方说有两个机房,这两个机房部署的集群有1000台主机,那么我们希望把nginx和tomcat都部署同一个地方的node节点上,可以提高通信效率;

**podAntiAffinity(反亲和性):**pod和pod更倾向不腻在一起,如果部署两套程序,那么这两套程序更倾向于反亲和性,这样相互之间不会有影响。

第一个pod随机选则一个节点,做为评判后续的pod能否到达这个pod所在的节点上的运行方式,这就称为pod亲和性;我们怎么判定哪些节点是相同位置的,哪些节点是不同位置的;我们在定义pod亲和性时需要有一个前提,哪些pod在同一个位置,哪些pod不在同一个位置,这个位置是怎么定义的,标准是什么?以节点名称为标准,这个节点名称相同的表示是同一个位置,节点名称不相同的表示不是一个位置。

1、 案例演示

pod节点亲和性

编辑pod的yaml文件

cpp 复制代码
[root@k8s-master pvc]# vim pod-required-affinity-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-first
  labels:
    app2: myapp2
    tier: frontend
spec:
  containers:
  - name: myapp
    image: nginx
    imagePullPolicy: IfNotPresent
cpp 复制代码
[root@k8s-master pvc]# vim pod-required-affinity-demo1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-second
  labels:
    app: backend  # 标签:应用为 backend
    tier: db      # 标签:层级为 db
spec:
  containers:
  - name: busybox
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","sleep 3600"] # 容器启动命令:运行 shell 并休眠 3600 秒
  affinity: # 亲和性配置
    podAffinity: # Pod 亲和性规则
      requiredDuringSchedulingIgnoredDuringExecution: # 硬性要求(调度期间必须满足,执行期间忽略)
      - labelSelector: # 标签选择器(用于选择目标 Pod)
          matchExpressions: # 匹配表达式(用于更复杂的标签匹配)
            - key: app2 # 标签键:app2
              operator: In # 操作符:在...之中
              values: # 值列表
                - myapp2 # 值:myapp2 (要求目标 Pod 具有标签 app2=myapp2)
        topologyKey: kubernetes.io/hostname # 拓扑域键:基于节点主机名 (要求目标 Pod 与当前 Pod 在同一个节点上)

上面表示创建的pod必须与拥有app=myapp2标签的pod在一个节点上

提交资源清单

cpp 复制代码
[root@k8s-master pvc]# kubectl apply -f pod-required-affinity-demo.yaml 
pod/pod-first created
[root@k8s-master pvc]# kubectl apply -f pod-required-affinity-demo1.yaml 
pod/pod-second created

查看pod,在同一个节点上

cpp 复制代码
[root@k8s-master pvc]# kubectl get pod -o wide
NAME                             READY   STATUS    RESTARTS       AGE     IP               NODE        NOMINATED NODE   READINESS GATES
pod-first                        1/1     Running   0              18s     10.244.36.97     k8s-node1   <none>           <none>
pod-second                       1/1     Running   0              15s     10.244.36.99     k8s-node1   <none>  
2.2 pod节点反亲和性

先删除上面创建的pod

cpp 复制代码
[root@k8s-master pvc]# kubectl delete pod pod-first 
pod "pod-first" deleted
[root@k8s-master pvc]# kubectl delete pod pod-second 
pod "pod-second" deleted
[root@k8s-master pvc]# 

创建反亲和性的pod

cpp 复制代码
[root@k8s-master pvc]# vim pod-required-affinity-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-first
  labels:
    app2: myapp2
    tier: frontend
spec:
  containers:
  - name: myapp
    image: nginx
    imagePullPolicy: IfNotPresent
cpp 复制代码
[root@k8s-master pvc]# vim pod-required-affinity-demo1.yaml
apiVersion: v1
kind: Pod 
metadata:
  name: pod-second
  labels:
    app: backend
    tier: db
spec:
  containers:
  - name: busybox
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","sleep 3600"]
  affinity:
    podAntiAffinity:   # Pod 反亲和性规则
      preferredDuringSchedulingIgnoredDuringExecution:  # 软性偏好(调度期间尽量满足,执行期间忽略)
        - weight: 100   # 权重值(范围 1-100,值越高偏好越强)
          podAffinityTerm:
            labelSelector:
              matchExpressions:    # 匹配表达式
                - key: app2
                  operator: In
                  values:
                    - myapp2
            topologyKey: kubernetes.io/hostname

上面表示创建的pod与拥有app=myapp2标签的pod不会在同一个节点上

提交资源清单

cpp 复制代码
[root@k8s-master pvc]# kubectl apply -f pod-required-affinity-demo.yaml 
pod/pod-first created
[root@k8s-master pvc]# kubectl apply -f pod-required-affinity-demo1.yaml
pod/pod-second created

查看pod

结果表明两个pod不在同一节点上

cpp 复制代码
[root@k8s-master pvc]# kubectl get pod -o wide
NAME                             READY   STATUS    RESTARTS       AGE     IP               NODE        NOMINATED NODE   READINESS GATES
pod-first                        1/1     Running   0              3m28s   10.244.36.100    k8s-node1   <none>           <none>
pod-second                       1/1     Running   0              11s     10.244.169.186   k8s-node2   <none>           <none>
2.3 换一个topologykey
详细说明:
  1. kubectl label Kubernetes 管理标签的命令。

  2. node k8s-node2 操作对象:名为 k8s-node2 的节点。

  3. zone=foo 标签内容:键为 zone,值为 foo

  4. --overwrite 强制覆盖:如果该节点已有 zone 标签,则更新其值;若未指定此参数,对已存在的标签重复操作会报错。

创建pod

cpp 复制代码
[root@k8s-master pvc]# vim pod-first-required-anti-affinity-demo-1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod3-first
  labels:
    app3: myapp3
    tier: frontend
spec:
    containers:
    - name: myapp
      image: nginx
      imagePullPolicy: IfNotPresent
cpp 复制代码
[root@k8s-master pvc]# vim pod-second-required-anti-affinity-demo-2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod3-second
  labels:
    app: backend  # 标签:应用为 backend
    tier: db      # 标签:层级为 db
spec:
  containers:
  - name: busybox
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","sleep 3600"] # 容器启动命令:运行 shell 并休眠 3600 秒
  affinity: # 亲和性配置
    podAntiAffinity: # Pod 反亲和性规则
      requiredDuringSchedulingIgnoredDuringExecution: # 硬性要求(调度期间必须满足,执行期间忽略)
      - labelSelector: # 标签选择器(用于选择要避免的 Pod)
          matchExpressions: # 匹配表达式
          - key: app3 # 标签键:app3
            operator: 'In' # 操作符:在...之中
            values: ["myapp3"] # 值列表:myapp3 (要避免的 Pod 具有标签 app3=myapp3)
        topologyKey: zone # 拓扑域键:基于自定义标签 zone (避免与目标 Pod 在同一个 zone 域内)

提交资源清单

cpp 复制代码
[root@k8s-master pvc]# kubectl apply -f pod-first-required-anti-affinity-demo-1.yaml
pod/pod3-first created
[root@k8s-master pvc]# kubectl apply -f pod-second-required-anti-affinity-demo-2.yaml
pod/pod3-second created

查看pod

cpp 复制代码
[root@k8s-master pvc]# kubectl get pods -o wide
NAME                             READY   STATUS    RESTARTS       AGE     IP               NODE        NOMINATED NODE   READINESS GATES
pod3-first                       1/1     Running   0              14s     10.244.36.102    k8s-node1   <none>           <none>
pod3-second                      0/1     Pending   0              8s      <none>           <none>      <none>   
cpp 复制代码
#发现第二个节点是pending,因为两个节点是同一个位置,现在不是同一个位置的了,而且我们要求反亲和性,所以就会处于pending状态,如果在反亲和性这个位置把required改成preferred,那么也会运行。
#podaffinity:pod节点亲和性,pod倾向于哪个pod
#nodeaffinity:node节点亲和性,pod倾向于哪个node

三、污点与容忍

核心思想:​

  • 污点(Taint):​ 打在节点(Node)​ 上。它表示该节点具有某种"排斥性"或"特性",拒绝那些不能"忍受"这种特性的 Pod 调度上来。
  • 容忍(Toleration):​ 打在 Pod 上。它表示该 Pod 能够"忍受"一个或多个特定的污点。只有 Pod 容忍了节点上的污点,该 Pod 才有可能被调度到该节点上。

为什么需要污点和容忍?​

污点和容忍提供了一种基于节点特性来排斥 Pod​ 的机制,常用于以下场景:

  1. 专用节点:​ 将某些节点(如 GPU 节点、高内存节点)保留给特定的工作负载(如 AI 训练、内存数据库)。给这些节点打上污点,只有声明了相应容忍的 Pod 才能使用它们。
  2. 节点隔离:​
    • 维护隔离:​ 准备对节点进行维护(如升级内核、更换硬件)时,给节点打上污点(如 effect: NoSchedule),阻止新 Pod 调度上来。然后可以安全地驱逐或删除现有 Pod(可能需要结合 effect: NoExecute)。
    • 问题隔离:​ 当节点出现硬件问题或软件异常时,打上污点阻止新 Pod 调度上来,防止问题扩散。
  3. 基于节点特性调度:​ 比如区分云服务商的不同可用区(Availability Zone)、不同的硬件类型(SSD vs HDD)、不同的网络类型(高性能网络)等。通过污点标记节点特性,Pod 通过容忍来选择。
  4. 控制 Pod 驱逐:​ 使用 NoExecute 污点可以控制哪些 Pod 在节点出现问题时(如网络分区、磁盘压力)会被驱逐。

污点(Taint)的组成:​

一个污点由三部分组成,格式为:key=value:effect

  1. **key:** 污点的键(字符串)。用于标识污点的类型或来源(如 gpu, dedicated, zone)。
  2. **value:** 污点的值(字符串,可选)。提供更具体的描述(如 nvidia, app-team-a, east-1)。如果 key 相同但 value 不同,则视为不同的污点。
  3. **effect​ 污点的 效果**(必需)。定义了当 Pod 不能容忍该污点时,调度器或节点应如何行动。有三种效果:
    • **NoSchedule:**
      • 调度时:​ Kubernetes 调度器不会不能容忍 此污点的 Pod 调度到该节点上。
      • 执行时:​ 不影响已经在该节点上运行的 Pod(即使它们不能容忍此污点)。
      • 用途:​ 预留节点、开始维护前阻止新 Pod 调度。
    • **PreferNoSchedule:**
      • 调度时:​ Kubernetes 调度器会尽量避免 将不能容忍此污点的 Pod 调度到该节点上。但如果没有其他合适的节点可用,调度器仍然会将 Pod 调度到该节点上。
      • 执行时:​ 不影响已经在该节点上运行的 Pod。
      • 用途:​ 软性偏好,建议但不强制 Pod 不要调度到某些节点。
    • **NoExecute:**
      • 调度时:​NoSchedule 效果相同,调度器不会将不能容忍此污点的 Pod 调度到该节点上。
      • 执行时:​ 影响 已经在该节点上运行的 Pod:
        • 如果一个 Pod 不能容忍 一个 NoExecute 污点,那么该 Pod 会立即被该节点驱逐(Evicted)​
        • 如果一个 Pod 能够容忍 一个 NoExecute 污点,但它没有在容忍度中指定 tolerationSeconds,则该 Pod 会一直运行在该节点上。
        • 如果一个 Pod 能够容忍 一个 NoExecute 污点,并且指定了 tolerationSeconds,则该 Pod 会在该节点上继续运行指定的秒数(tolerationSeconds),超过这个时间后也会被驱逐。
      • 用途:​ 节点出现不可恢复的问题时(如硬件故障、网络断开),驱逐所有 Pod;或者给 Pod 一个宽限期(tolerationSeconds)让其优雅终止。

容忍(Toleration)的组成:​

一个容忍度定义在 Pod 的 spec.tolerations 字段下。它告诉调度器该 Pod 可以容忍哪些污点。主要字段:

  1. **key:** (可选,但通常建议指定) 要匹配的污点的 key。如果为空,则匹配所有污点的 key
  2. **operator:** (必需) 指定 keyvalue 之间的匹配关系。有两种操作符:
    • **Equal:** 要求污点的 value 必须等于容忍度中指定的 value。这是最常用的操作符。
    • **Exists​ 只要污点存在指定的 key 即可,不检查污点的 value。此时容忍度中的 value 字段必须为空**。
  3. **value​ (当 operatorEqual 时必需;当 operatorExists 不能**设置) 要匹配的污点的 value
  4. **effect:** (可选) 要匹配的污点的 effectNoSchedule, PreferNoSchedule, NoExecute)。如果为空,则表示容忍所有 effect
  5. **tolerationSeconds:** (仅当 effectNoExecute 时相关,可选) 指定 Pod 在被 NoExecute 污点驱逐前,可以在节点上继续运行的秒数。仅对 NoExecute 污点有效。

关键点:​

  • 容忍不是"选择":​ 容忍只是让 Pod 有资格被调度到带有污点的节点上,但并不保证一定会调度上去。调度还受其他因素影响(如资源请求/限制、节点选择器、亲和性规则)。
  • 污点与容忍的匹配:​ 一个 Pod 要被调度到一个带有污点的节点上,该 Pod 必须显式地容忍该节点上的所有污点 (除了 effectPreferNoSchedule 的污点,它只是偏好而非强制)。如果节点上有多个污点,Pod 需要容忍所有污点才能被调度。
  • **NoExecute 的特殊性:** NoExecute 污点不仅影响调度,还影响运行中的 Pod,可能导致驱逐。

操作命令:​

  1. 给节点添加污点:​

    cpp 复制代码
    kubectl taint nodes <node-name> key=value:effect
    # 示例:给节点 node1 添加一个排斥所有不能容忍 gpu 的 Pod 的污点
    kubectl taint nodes node1 gpu=true:NoSchedule
    # 示例:给节点 node2 添加一个 NoExecute 污点,驱逐所有不能容忍的 Pod
    kubectl taint nodes node2 unrecoverable=true:NoExecute
  2. 查看节点污点:​

    复制代码
    kubectl describe node <node-name> | grep Taints
    # 或者
    kubectl get node <node-name> -o jsonpath='{.spec.taints}'
  3. 移除节点污点:​

    复制代码
    kubectl taint nodes <node-name> key:effect-
    # 示例:移除 node1 上 key 为 gpu, effect 为 NoSchedule 的污点
    kubectl taint nodes node1 gpu:NoSchedule-
    # 移除 node1 上所有 key 为 gpu 的污点(不管 effect)
    kubectl taint nodes node1 gpu-

1、污点(Taints)

污点的优先级高于nodename和nade

设置污点后,一般Pod将不会调度到该节点上来。每次Pod都不会调度到master节点,那是因为搭建K8s集群的时候,K8s给master自带了一个污点。

1.1、查看污点

查看master上是否有污点,通过describe命令可以看到节点上的所有污点

cpp 复制代码
[root@k8s-master pvc]# kubectl describe node k8s-master

详细解释:

  1. 污点键 (Key): node-role.kubernetes.io/control-plane

    • 这是 Kubernetes 内置的系统级标签/污点键

    • 它标识该节点是 控制平面节点 (Control Plane Node) ,即 Master 节点(如运行 kube-apiserver, etcd, kube-scheduler, kube-controller-manager 的节点)。

  2. 污点效果 (Effect): NoSchedule

    • 调度时效果: Kubernetes 调度器 不会不能容忍此污点 的 Pod 调度到该节点上。

    • 执行时效果: 不影响 已在该节点上运行的 Pod(即使它们不能容忍此污点)。

发现master上自带了一个没有value的污点 node-role.kubernetes.io/control-plane ,effect 为 NoSchedule,由于我们的Pod都没有容忍这个污点,所以一直都不会调度到master

1.2、污点类别

上面我们看到了污点有一个effect 属性为NoSchedule,其实还有其它两种类别分别是 PreferNoSchedule与 NoExecute

  • NoSchedule: 如果没有容忍该污点就不能调度进来。

  • PreferNoSchedule: 相当于NoExecute的一个软限制,如果没有容忍该污点,尽量不要把Pod调度进来,但也不是强制的。

  • NoExecute: 如果没有设置容忍该污点,新的Pod肯定不会调度进来, 并且已经在运行的Pod没有容忍该污点也会被驱逐。

1.3、设置污点

污点分别由key、value(可以为空)、effect 组成,设置命令如下

cpp 复制代码
# 设置污点并不允许Pod调度到该节点
$ kubectl taint node k8s-node1 key=value:NoSchedule
# 设置污点尽量不要让Pod调度到该节点
$ kubectl taint node k8s-node1 key=value:PreferNoSchedule
# 设置污点,不允许Pod调度到该节点,并且且将该节点上没有容忍该污点的Pod将进行驱逐
$ kubectl taint node k8s-node1 key=value:NoExecute

1.4、删除污点

cpp 复制代码
# 删除该key的所有污点
$ kubectl taint node k8s-node1 key-
# 删除该key的某一个污点
$ kubectl taint node k8s-node1 key=value:NoSchedule-
# 删除该key的某一个污点可以不写value
$ kubectl taint node k8s-node1 key:NoSchedule-

1.5、污点测试

给k8s-node1节点设置一个污点,表示只有前台web应用才能调度,后端app应用不能调度

cpp 复制代码
[root@k8s-master ~]# kubectl taint node k8s-node1 web=true:NoSchedule
node/k8s-node1 tainted

编写 web-taint.yaml 内容如下,有三个Pod均没有容忍该污点

cpp 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: web-taint1
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent # 本地有不拉取镜像
---
apiVersion: v1
kind: Pod
metadata:
  name: web-taint2
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent # 本地有不拉取镜像
---
apiVersion: v1
kind: Pod
metadata:
  name: web-taint3
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent # 本地有不拉取镜像

启动Pod,观察Pod是否都被调度到k8s-node2节点

cpp 复制代码
# 启动三个Pod
[root@k8s-master taint]# kubectl apply -f web-taint.yaml 
pod/web-taint1 applyd
pod/web-taint2 applyd
pod/web-taint3 applyd
​
# 查看pod详情发现均被调度到k8s-node2节点
[root@k8s-master taint]# kubectl get pod -o wide
NAME         READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
web-taint1   1/1     Running   0          13s   10.244.2.35   k8s-node2   <none>           <none>
web-taint2   1/1     Running   0          13s   10.244.2.34   k8s-node2   <none>           <none>
web-taint3   1/1     Running   0          13s   10.244.2.36   k8s-node2   <none>           <none>

给k8s-node2节点添加污点 app=true:NoExecute,表示只有后端服务才能调度进来,并且已经在k8s-node2节点上运行的不是后端服务的节点将被驱逐

cpp 复制代码
# 设置污点
[root@k8s-master taint]# kubectl taint node k8s-node2 app=true:NoExecute
node/k8s-node2 tainted
# 查看Pod详情,发现三个Pod已经被驱逐
[root@k8s-master taint]# kubectl get pod -o wide
No resources found in default namespace.

从上面可以知道我们虽然设置了污点,但是我们的节点其实很正常,既然是正常节点,那么就可以有服务运行,这就需要用到容忍机制来运行这些Pod

2、容忍(Toletations)

如果需要Pod忽略Node上的污点,就需要给Pod设置容忍,并且是需要容忍该Pod上的所有污点。

通过 kubectl explain pod.spec.tolerations 可以查看容忍的配置项

2.1、配置项

cpp 复制代码
tolerations: # 数组类型,可以设置多个容忍
- key: # 污点key
  operator: # 操作符,有两个选项 Exists and Equal 默认是Equal
  value: # 污点value,如果使用Equal需要设置,如果是Exists就不需要设置
  effect: # 可以设置为NoSchedule、PreferNoSchedule、NoExecute,如果为空表示匹配该key下所有污点,
  tolerationSeconds: # 如果污点类型为NoExecute,还可以设置一个时间,表示这一个时间段内Pod不会被驱逐,过了这个时间段会立刻驱逐,0或者负数会被立刻驱逐

2.2、设置容忍

给Pod设置容忍k8s-node1节点的污点web=true:NoSchedule

编写 web-tolerations.yaml 内容如下,容忍污点web=true:NoSchedule

cpp 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: web-tolerations
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent # 本地有不拉取镜像
  tolerations:
  - key: web
    operator: Equal
    value: "true"
    effect: NoSchedule

启动web-tolerations,观察Pod是否正常运行

cpp 复制代码
# 启动web-tolerations
[root@k8s-master taint]# kubectl apply -f web-tolerations.yaml  
pod/web-tolerations applyd
​
# Pod正常运行,且运行在k8s-node1节点
[root@k8s-master taint]# kubectl get pod -o wide
NAME              READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
web-tolerations   1/1     Running   0          8s    10.244.1.92   k8s-node1   <none>           <none>

查看该Pod上的容忍

cpp 复制代码
[root@k8s-master taint]# kubectl describe pod web-tolerations
​
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
                             web=true:NoSchedule

可以看到我们设置的Tolerations在里边,除了我们自己的,K8s还会给每个Pod设置两个默认Tolerations,并且Tolerations时间为五分钟,表示某些节点发生一些临时性问题,Pod能够继续在该节点上运行五分钟等待节点恢复,并不是立刻被驱逐,从而避免系统的异常波动。

编写 app-tolerations.yaml 内容如下,容忍污点app=true:NoExecute,并且只容忍60s

cpp 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: app-tolerations
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  tolerations:
  - key: app
    operator: Exists
    effect: NoExecute
    tolerationSeconds: 60

启动app-tolerations,查看Pod是否能够正常运行,且运行在k8s-node2节点,等待60秒,查看Pod是否已被驱逐

cpp 复制代码
# 启动app-tolerations
[root@k8s-master taint]# kubectl apply -f app-tolerations.yaml 
pod/app-tolerations applyd
​
# 查看详情,已经运行成功并且调度到了k8s-node2节点,此时运行59秒
[root@k8s-master taint]# kubectl get pod -o wide
NAME              READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
app-tolerations   1/1     Running   0          59s   10.244.2.37   k8s-node2   <none>           <none>
​
# 运行60秒查看,状态已经变为Terminating
[root@k8s-master taint]# kubectl get pod -o wide
NAME              READY   STATUS        RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
app-tolerations   1/1     Terminating   0          60s   10.244.2.37   k8s-node2   <none>           <none>
​
# 立刻再次查看,已经被驱逐
[root@k8s-master taint]# kubectl get pod -o wide
No resources found in default namespace.

如果一个节点没有任何污点,另一个节点有污点,并且Pod容忍了该污点,那么最终会调度到哪个节点呢?

删除k8s-node2节点的污点app=true:NoExecute,保留k8s-node1节点的web=true:NoSchedule,再次启动之前的web-tolerations.yaml 观察Pod所在节点

cpp 复制代码
# 删除k8s-node2上的污点
[root@k8s-master taint]# kubectl taint node k8s-node2 app:NoExecute- 
node/k8s-node2 untainted
​
# 启动Pod web-tolerations
[root@k8s-master taint]# kubectl apply -f web-tolerations.yaml 
pod/web-tolerations applyd
​
# Pod正常运行,并且运行在k8s-node2节点
[root@k8s-master taint]# kubectl get pod -o wide                 
NAME              READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
web-tolerations   1/1     Running   0          2s    10.244.2.38   k8s-node2   <none>           <none>

上面表明,即使是容忍了该污点,如果有其它节点不需要容忍就可以调度的话,那还是会优先选择没有污点的机器,但是生产上往往设置污点就是为了给你这个Pod使用的,不能调度到其它节点,这个时候需要配合节点亲和性调度一起使用。

2.3、Equal 与 Exists

Equal (等于) 精确匹配

Exists (存在) 模糊匹配

Exists (存在)表示key是否存在所以无需设置value,Equal 则必须设置value需要完全匹配,默认为Equal

空的key配合Exists 可以匹配所有的key-value,也就是容忍所有的污点,生产上非常不建议使用

相关推荐
泡沫冰@1 小时前
管理 SELinux 安全性
linux
展信佳_daydayup3 小时前
03 基础篇-润和开发板连接过程
linux·开源·嵌入式
两张不够花3 小时前
Shell脚本源码安装Redis、MySQL、Mongodb、PostgreSQL(无报错版)
linux·数据库·redis·mysql·mongodb·postgresql·云计算
tan77º3 小时前
【Linux网络编程】分布式Json-RPC框架 - 项目设计
linux·服务器·网络·分布式·网络协议·rpc·json
Ray Song4 小时前
【Linux】 wget、curl 用法区别
linux·运维·服务器·curl·wget
@寄居蟹4 小时前
Docker 命令大全
docker·容器·eureka
一乐小哥5 小时前
五分钟就能搭好的socks5为啥我装了一个小时😭 进来看小丑
linux·后端
qq_364371725 小时前
Docker 常见命令
运维·docker·容器
照物华6 小时前
k8s之 Pod 资源管理与 QoS
云原生·容器·kubernetes
hhzz6 小时前
重温 K8s 基础概念知识系列八( K8S 高级网络)
网络·容器·kubernetes