Kubernetes 污点与容忍

首先说一下污点(Taint),当我们需要将master节点保留给Kubernetes系统组件调用时,或者需要保留master节点的资源时,我们可以标记一个Taint,当节点标记Taint时,除非Pod也被识别为可以容忍(Toleration)污点的节点,否则默认情况下Kubernetes scheduler不会将Pod调度到有污点的节点上

Kubernetes 亲和性调度

一般情况下我们部署的 Pod 是通过集群的自动调度策略来选择节点的,默认情况下调度器考虑的是资源足够,并且负载尽量平均,但是有的时候我们需要能够更加细粒度的去控制 Pod 的调度,比如我们内部的一些服务 gitlab 之类的也是跑在Kubernetes集群上的,我们就不希望对外的一些服务和内部的服务跑在同一个节点上了,担心内部服务对外部的服务产生影响;但是有的时候我们的服务之间交流比较频繁,又希望能够将这两个服务的 Pod 调度到同一个的节点上。这就需要用到 Kubernetes 里面的一个概念:亲和性和反亲和性。


污点 Taint

容忍 Toleration

首先说一下污点Taint,当我们需要将master节点保留给Kubernetes系统组件调用时,或者需要保留master节点的资源时,我们可以标记一个Taint,当节点标记Taint时,除非Pod也被识别为可以容忍Toleration污点的节点,否则默认情况下Kubernetes scheduler不会将Pod调度到有污点的节点上

Taint(污点)和 Toleration(容忍)可以作用于node和 pod 上,其目的是优化pod在集群间的调度,这跟节点亲和性类似,只不过它们作用的方式相反,具有taint的node和pod是互斥关系,而具有节点亲和性关系的node和pod是相吸的。另外还有可以给node节点设置label,通过给pod设置nodeSelector将pod调度到具有匹配标签的节点上。

Taint 和 toleration 相互配合,可以用来避免pod被分配到不合适的节点上。每个节点上都可以应用一个或多个taint,这表示对于那些不能容忍这些taint的 pod,是不会被该节点接受的。如果将toleration应用于pod上,则表示这些pod可以(但不要求)被调度到具有相应taint的节点上。

如果使用kubeadm搭建的集群,默认就会给master节点添加一个污点标记。我这里使用二进制安装一切自定义,所以我们跳过这步。从添加污点开始

污点taint标记节点的命令

# 添加taint污点命令
kubectl taint nodes k8s-01 key=value:NoSchedule
kubectl taint nodes k8s-02 key=value:NoExecute
kubectl taint nodes k8s-03 key=value:PreferNoSchedule

# 查看taint污点命令
[root@k8s-01 test]# kubectl describe node k8s-01|grep Taints
Taints:             key=value:NoSchedule


#删除污点命令
kubectl taint node k8s-01 key:NoSchedule-

example
kubectl taint node [节点] [任意值]:[NoSchedule、NoExecute、PreferNoSchedule]
#删除和创建中的值要对应上,node节点的名称需要通过kubectl get node对应上

#这里不执行

首先我们先了解一下对应的参数

  • NoSchedule 新的不能容忍的pod不能再调度过来,但是之前运行在node节点中的Pod不受影响
  • NoExecute 新的不能容忍的pod不能调度过来,老的pod也会被驱逐
  • PreferNoScheduler 表示尽量不调度到污点节点中去

容忍 Toleration

前面我们介绍了将Pod添加污点,但是可能有一些比较重要的服务需要跑在master节点上,那么我们就需要添加一个容忍,允许哪些Pod跑在有污点的节点上

这里我们还是使用上面学到的nodeAffinity,使用硬策略将pod捆绑在k8s-01节点上,同时又在k8s-01节点上配置污点

#首先在k8s-01节点配置污点,将之前的pod全部移除
kubectl taint nodes k8s-01 key1=value:NoExecute


$ kubectl get pod --all-namespaces  -o wide
NAMESPACE     NAME                                    READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
kube-system   coredns-6776c9d69-6chbp                 1/1     Running   3          25d   172.30.200.2   k8s-03              
kube-system   coredns-6776c9d69-n45nb                 1/1     Running   0          26s   172.30.232.2   k8s-02              
kube-system   kubernetes-dashboard-78bcf8c65c-vfbkq   1/1     Running   4          25d   172.30.8.2     k8s-04               

#目前k8s-01节点的pod已经全部移除

接下来我们编写yaml文件,将nginx 添加容忍,并且使用硬策略只捆绑在k8s-01上 (这里使用硬策略和软策略或者不添加都是可以的。)

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: affinity
  labels:
    app: affinity
spec:
  replicas: 3
  revisionHistoryLimit: 10
  template:
    metadata:
      labels:
        app: affinity
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - name: http
          containerPort: 80

      tolerations:      #添加容忍策略
        - key: "key1"    #对应我们添加节点的变量名
          operator: "Equal"    #操作符
          value: "value"    #容忍的值   key1=value对应
          effect: NoExecute   #添加容忍的规则,这里必须和我们标记的五点规则相同

      affinity:        
        nodeAffinity: 
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms: 
            - matchExpressions: 
              - key: kubernetes.io/hostname
                operator: In
                values:
                - k8s-01

operator值是Exists,则value属性可以忽略

operator值是Equal,则表示key与value之间的关系是等于

operator不指定,则默认为Equal

接下来我们创建查看结果

kubectl get pod  -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
affinity-7c85766dcb-2g6sv   1/1     Running   0          29s   172.30.40.3   k8s-01              
affinity-7c85766dcb-gfmb2   1/1     Running   0          29s   172.30.40.2   k8s-01              
affinity-7c85766dcb-vpctf   1/1     Running   0          29s   172.30.40.4   k8s-01              

#目前所有的Pod都调度在k8s-01节点上,但是如果我们这里规则写的不匹配,那么Pod将处于pending状态

当然我们的匹配规则也是可以写成多个

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoExecute"

在NoExecute可以指定一个可选tolerationSeconds字段,该字段指示添加污点后,指定停留在node污点的时间

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoExecute"
  tolerationSeconds: 3600

意味着如果此Pod正在运行并将匹配的污点添加到该节点,则该Pod将与该节点绑定3600秒,然后被逐出。


同时在Kubernets 1.6 引入了代表node问题的污点,node控制器当某种条件成立的时候会自动的给node打上污点。下面是其中内置的污点:

node.kubernetes.io/not-ready:node不是ready状态。对应于node的condition ready=false.

node.kubernetes.io/unreachable:node controller与node失联了。对应于node的condition ready=unknown

node.kubernetes.io/out-of-disk:node磁盘空间不足了。

node.kubernetes.io/network-unavailable:node的网断了

node.kubernets.io/unschedulable:node不是可调度状态

node.cloudprovider.kubernetes.io/uninitalized:kubelet是由外部云提供商提供的时候,刚开始的时候会打上这个污点来标记还未被使用。当cloud-controller-manager控制器初始化完这个node,kubelet会自动移除这个污点。

配置案例,只需要将key修改成对应的值即可

tolerations:
- key: "node.kubernetes.io/unreachable"
  operator: "Exists"
  effect: "NoExecute"
  tolerationSeconds: 6000

参考

https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/

https://www.cnblogs.com/xiexj/p/10561237.html

Logo

开源、云原生的融合云平台

更多推荐