k8s中的集群调度

1 调度的基本概述

  1. kube-scheduler是k8s集群的默认调度器,该调度器会将Pod放到合适的Node上,然后对应Node上的Kubelet才能够运行这些Pod;
  2. 对每一个新建的Pod或者是未被调度的Pod,kube-scheduler会选择一个最优的Node去运行这个Pod。然而,Pod内的每一个容器对资源都有不同的需求,而且Pod本身也有不同的资源需求。因此,Pod在被调度到Node上之前,根据这些特定的资源调度需求,需要对集群中的Node进行一次过滤;
  3. 集群中,满足一个Pod调度请求的所有Node称之为可调度节点。如果没有任何一个Node能满足Pod的资源请求,那么这个Pod将一直停留在未调度状态直到调度器能够找到合适的Node;
  4. 调度器会先在集群中找到一个Pod的所有可调度节点,然后根据一系列函数对这些可调度节点进行打分,最终选出其中得分最高的Node来运行Pod。之后,调度器将这个调度决定通知给kube-apiserver,这个过程叫做绑定
  5. 在做调度决定时需要考虑的因素包括:单独和整体的资源请求、硬件/软件/策略限制、亲和以及反亲和要求、数据局域性、负载间的干扰等等。

2 kube-scheduler的调度流程

kube-scheduler给一个Pod做调度选择包含两个步骤:

  • 过滤;
  • 打分。

过滤阶段会将所有满足Pod调度需求的Node选出来。例如,PodFitsResources过滤函数会检查候选Node的可用资源能否满足Pod的资源请求。在过滤之后,得出一个Node列表,里面包含了所有可调度节点;通常情况下,这个Node列表包含不止一个Node。如果这个列表是空的,代表这个Pod不可调度。

在打分阶段,调度器会为Pod从所有可调度节点中选取一个最合适的Node。根据当前启用的打分规则,调度器会给每一个可调度节点进行打分。

最后,kube-scheduler会将Pod调度到得分最高的Node上。如果存在多个得分最高的Node,kube-scheduler会从中随机选取一个。

3 固定节点调度

某些场景下,我们会希望Pod只在固定节点上运行,这时候就需要用到固定节点调度了,下面会介绍两种调度的方式。

3.1 通过指定节点名称的方式

通过kubectl get node命令查看一下集群中的节点名称,我这边worker node有node1node2两个。

[root@master ~]# kubectl get node
NAME     STATUS   ROLES    AGE   VERSION
master   Ready    master   59d   v1.18.0
node1    Ready    <none>   59d   v1.18.0
node2    Ready    <none>   59d   v1.18.0

创建一个nodeName.yaml文件,内容如下:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
  nodeName: node1

上面创建Pod的文件中,spec属性下的nodeName属性就是用来进行固定节点调度的,该属性的值配置的是node1,表示该Pod只会运行在node1节点上。

通过yaml创建Pod:

kubectl apply -f nodeName.yaml

查看Pod的运行状态:

kubectl get pod -o wide

image-20210510201406729
由上图可知,该Pod确实是运行在node1节点上了的。不过这里只有一个Pod,具有随机性,并不能说明就是nodeName属性起了作用。所以下面通过创建Deployment的方式来进行验证,并把副本数设置成10,如果10个Pod都在node1节点上的话,肯定就是nodeName属性起了作用。对应的yaml文件内容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
  labels:
    app: deploy-label
spec:
  selector:
    matchLabels:
      app: deploy-label
  replicas: 10
  template:
    metadata:
      labels:
        app: deploy-label
    spec:
      nodeName: node1
      containers:
      - name: nginx
        image: nginx

通过yaml文件创建Pod后,使用kubectl get pod -o wide命令查看Pod的运行状态:
k8s中的集群调度_第1张图片
由上图可知,通过Deployment方式创建的10个Pod都运行在了node1节点上,说明确实是nodeName属性起了作用。

3.2 通过标签选择的方式

这种方式需要用到nodeSelector属性。首先需要在指定的节点上打标签,然后再在创建Pod的时候使用nodeSelector属性选择这个标签,通过这种方式即可完成固定节点调度。

给node1节点打标签:

#下面的disktype是自定义的标签的key值,ssd是自定义的标签的value值
kubectl label nodes node1 disktype=ssd

通过如下两种方式查看节点标签是否新增成功:

kubectl get nodes node1 --show-labels
kubectl describe node node1|grep -10 Labels

k8s中的集群调度_第2张图片
节点标签新增成功后,新增nodeSelector.yaml文件,内容如下:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disktype: ssd

上面创建Pod的文件中,spec属性下的nodeSelector属性就是用来进行固定节点调度的,该属性下的disktype就是节点标签的key值,ssd就是节点标签的value值。

通过yaml文件创建Pod:

kubectl apply -f nodeSelector.yaml

查看Pod的运行状态:

kubectl get pod -o wide

image-20210510211312836
由上图可知,该Pod确实已经运行在node1节点上了,为了防止是由于偶然性,这里仍然通过创建Deployment的方式来进行验证,副本数设置成5个,对应的yaml文件内容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
  labels:
    app: deploy-label
spec:
  selector:
    matchLabels:
      app: deploy-label
  replicas: 5
  template:
    metadata:
      labels:
        app: deploy-label
    spec:
      containers:
      - name: nginx
        image: nginx
      nodeSelector:
        disktype: ssd

通过yaml文件创建Pod后,使用kubectl get pod -o wide命令查看Pod的运行状态:
k8s中的集群调度_第3张图片
由上图可知,通过Deployment方式创建的5个Pod都运行在了node1节点上,说明确实是nodeSelector属性起了作用。

4 亲和性与反亲和性

使用nodeSelector属性可以提供一种非常简单的方法来将Pod约束到具有特定标签的节点上。而亲和性与反亲和性功能则极大地扩展了我们可以表达约束的类型,关键的增强点包括:

  • 语言更具表现力,提供了更多的匹配规则;
  • 规则是具有偏好性的,并不是硬性要求,所以当调度器不能满足要求的时候,Pod仍然可以被调度;
  • 亲和性功能包含两种类型的亲和性,即节点的亲和性与反亲和性以及Pod间的亲和性与反亲和性;
  • 我们可以使用节点上的Pod的标签来进行约束,而不是使用节点本身的标签。亲和性与反亲和性允许哪些Pod可以或者不可以被放置在一起。
4.1 节点的亲和性与反亲和性

节点的亲和性概念上类似于nodeSelector,它使我们可以根据节点上的标签来约束Pod可以被调度到哪些节点。

目前有如下两种类型的节点亲和性:

  • requiredDuringSchedulingIgnoredDuringExecution硬策略。该策略指定了将Pod调度到一个节点上必须满足的规则(就像nodeSelector一样,但使用了更具表现力的语法);
  • preferredDuringSchedulingIgnoredDuringExecution软策略。该策略会指定调度器尝试将Pod调度到指定节点上,是具有偏好性的,并不是说Pod就一定要运行到指定的节点上。

如果使用硬策略将Pod调度到指定节点上后,节点的相关标签在运行时发生了变更,从而不再满足Pod上的亲和性规则的话,Pod将仍然会继续在该节点上运行。requiredDuringSchedulingRequiredDuringExecution这种策略可能会在未来的k8s中出现,使用这种策略会将Pod从不再满足Pod的节点亲和性要求的节点上驱逐。

节点的亲和性是通过Pod.spec的affinity字段下的nodeAffinity字段进行指定的。

下面是一个使用节点亲和性的Pod案例:

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: e2e-az-name
            operator: In
            values:
            - e2e-az1
            - e2e-az2
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: another-node-label-key
            operator: In
            values:
            - another-node-label-value
  containers:
  - name: with-node-affinity
    image: nginx

以上节点亲和性的规则表示,Pod只能放置在具有标签键e2e-az-name且标签值为e2e-az1e2e-az2的节点上。在满足这些条件的节点中,具有标签键为another-node-label-key且标签值为another-node-label-value的节点将会被优先使用。

我们可以在上面的例子中看到operator属性值为In的操作符的使用。节点亲和性语法支持下面这些操作符:

  • In:标签值在某个列表中;
  • NotIn:标签值不在某个列表中;
  • Exists:某个标签值存在;
  • DoesNotExist:某个标签值不存在;
  • Gt:标签值大于某个值(字符串比较);
  • Lt:标签值小于某个值(字符串比较)。

在这些操作符中,我们可以使用NotInDoesNotExist来实现节点的反亲和性行为。

注意事项:

  1. 如果同时指定了nodeSelectornodeAffinity,两者必须都要满足,才能将Pod调度到候选节点上;
  2. 如果指定了多个与nodeAffinity类型关联的nodeSelectorTerms,只要其中有一个nodeSelectorTerms满足的话,Pod就可以调度到指定节点上;
  3. 如果指定了多个与nodeSelectorTerms关联的matchExpressions,则只有当所有的matchExpressions满足要求,Pod才会调度到指定节点上;
  4. 如果我们修改或删除了Pod所调度到的节点的标签,Pod不会被删除;
  5. 软策略中的weight属性是权重的意思,取值范围是1-100。如果存在多个软策略的话,对于亲和性规则而言,权重越大越亲和;对于反亲和性规则而言,权重越大越不亲和。
4.2 Pod间的亲和性与反亲和性

基本概念和注意事项:

  • Pod间的亲和性与反亲和性同样有两种策略,即硬策略requiredDuringSchedulingIgnoredDuringExecution和软策略preferredDuringSchedulingIgnoredDuringExecution

  • Pod间亲和性与反亲和性使我们可以基于已经在节点上运行的Pod的标签来约束Pod可以调度到的节点,而不是基于节点上的标签;

  • Pod间亲和性与反亲和性需要大量的处理,这可能会显著减慢大规模集群中的调度,所以不建议在超过数百个节点的集群中使用它们;

  • Pod反亲和性需要对节点进行一致的标记,即集群中的每个节点必须具有适当的标签能够匹配topologyKey。如果某些或所有节点缺少指定的topologyKey标签,可能会导致意外行为;

  • Pod间的亲和性通过spec属性中affinity字段下的podAffinity字段进行指定;而Pod间的反亲和性是通过spec中affinity字段下的podAntiAffinity字段进行指定;

  • Pod间的亲和性与反亲和性的合法操作符有InNotInExistsDoesNotExist

Pod间亲和性与反亲和性的基本案例:

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
        topologyKey: "kubernetes.io/hostname"
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: security
              operator: In
              values:
              - S2
          topologyKey: "kubernetes.io/hostname"
  containers:
  - name: with-pod-affinity
    image: nginx

在上面的案例中,分别定义了一条Pod亲和性规则和一条Pod反亲和性规则。

在这个案例中,podAffinity配置的是硬策略,而podAntiAffinity配置的是软策略。案例中podAffinity属性下配置的亲和性规则是指将该Pod调度到topologyKey属性表示的拓扑域上,这个区域上至少需要存在一个正在运行的包含键为security值为S1的标签的Pod。案例中podAntiAffinity属性下配置的反亲和性规则是指,如果topologyKey属性表示的拓扑域上存在正在运行的包含键为security值为S2的标签的Pod,那么该Pod将不会被调度到这个区域上的节点中。

关于topologyKey属性的解释说明:

  • topologyKey属性是用于表示一个拓扑域的,并不是表示一个节点,一个拓扑域可以包含多个节点;
  • topologyKey后跟的是节点标签的key值,假设一个k8s集群中有A、B、C三个节点,它们都拥有名为env这个相同key值的节点标签,但是标签的value值分别是devtestprod,那么这时候拓扑域和集群中的节点就是一对一的关系,这时候将Pod调度到拓扑域上就是指将Pod调度到k8s集群的某一节点上。如果A、B两个节点的标签的value值都是dev,而C节点的标签的value值是test的话,拓扑域和节点就是一对多的关系了,这时候的A、B节点是处于同一拓扑域的,C节点是处于另一个拓扑域的;
  • Pod间的亲和性规则并不是说两个Pod一定会处于同一节点上,只有当拓扑域和节点是一对一关系的时候才会被调度到同一节点上,如果拓扑域中包含多个节点的话,配置了Pod间亲和性规则后,k8s只会将该Pod调度到和另一个Pod相同拓扑域中的某一个节点上,并不一定就和另一个Pod是同一个节点,但一定和这个Pod处于同一拓扑域;
  • 以上案例中,topologyKey属性对应的值是"kubernetes.io/hostname",这个是k8s给集群中所有的节点默认加的标签的key值,value值就是每个节点的节点名,集群中节点的节点名是不会重复的,所以案例中的拓扑域和节点之间就是一对一的关系。

原则上,topologyKey可以是任何合法的标签键。然而,出于性能和安全原因,topologyKey有如下限制:

  1. 对于亲和性与requiredDuringSchedulingIgnoredDuringExecution要求的Pod反亲和性,topologyKey不允许为空;
  2. 对于在Pod反亲和性中使用了requiredDuringSchedulingIgnoredDuringExecution硬策略的情况,引入了准入控制器LimitPodHardAntiAffinityTopology来限制topologyKey不为"kubernetes.io/hostname"。如果我们想使它可用于自定义拓扑结构,则必须修改准入控制器或者禁用它;
  3. 对于preferredDuringSchedulingIgnoredDuringExecution要求的Pod反亲和性,空的topologyKey的意思就是"所有拓扑结构",这里的"所有拓扑结构"就是kubernetes.io/hostnametopology.kubernetes.io/zonetopology.kubernetes.io/region的组合。

Pod间亲和性与反亲和性的进阶案例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-cache
spec:
  selector:
    matchLabels:
      app: store
  replicas: 2
  template:
    metadata:
      labels:
        app: store
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - store
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: redis-server
        image: redis:6.0

以上案例是使用Pod间的反亲和性规则使创建的两个Pod不在同一节点,创建Pod后效果如下:
image-20210511231937158
由上图可知,通过Deployment创建的两个副本Pod确实都不在同一节点上,我这边集群中worker节点只有两个,所以这里副本数才设置成2,上述案例设置了反亲和性规则的硬策略,如果副本数大于worker节点的个数的话,就会出现由于节点不够导致多出的Pod一直处于Pending状态的情况。假设我把副本数设置为5的话,运行结果就是下面这样:
image-20210511233328432
Pod间亲和性与反亲和性的高级案例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
spec:
  selector:
    matchLabels:
      app: web-store
  replicas: 2
  template:
    metadata:
      labels:
        app: web-store
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - web-store
            topologyKey: "kubernetes.io/hostname"
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - store
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: web-app
        image: nginx:1.20

这个案例是要结合上面那个进阶案例进行使用的,所以在使用这个yaml文件创建Deployment之前,要保证前面那个进阶案例对应的yaml文件已经创建成功,下面大致说一下这个yaml文件创建后达到的效果。

前面进阶案例的yaml文件中使用反亲和性规则使得创建的两个Pod分配在了不同的节点上,现在这个yaml文件中也使用反亲和性规则使得创建的两个Pod分配在不同的节点上,并且还对上面进阶案例中创建的Pod使用了亲和性规则,所以最终会出现两个节点上都分别有一个进阶案例中创建的Pod和这个案例中创建的Pod,具体截图如下:
k8s中的集群调度_第4张图片

5 污点和容忍

节点亲和性是Pod的一种属性,它可以使Pod被吸引到一类特定的节点上。这可能是出于一种偏好,也可能是硬性要求。污点(Taint)则相反,它使节点能够排斥一类特定的Pod。

容忍(Tolerations)是应用于Pod上的,允许(但并不要求)Pod调度到带有与之匹配的污点的节点上。

污点和容忍(Tolerations)相互配合,可以用来避免Pod被分配到不合适的节点上。每个节点上都可以应用一个或多个污点,这表示对于那些不能容忍这些污点的Pod,是不会被该节点接受的。

5.1 污点(Taint)

可以使用kubectl taint命令给节点增加污点,节点被添加上污点之后就和Pod之间存在了一种相斥的关系,可以让节点拒绝Pod的调度执行,甚至将该节点上已经存在的Pod驱逐出去。

每个污点的组成如下:

key=value:effect

上面的key是污点的标签的键,value是污点的标签的值,其中value值可以为空,effect用来描述污点的作用,它支持如下三个选项:

  • NoSchedule:表示k8s将不会把Pod调度到具有该污点的节点上;
  • PreferNoSchedule:表示k8s将尽量避免把Pod调度到具有该污点的节点上;
  • NoExecute:表示k8s将不会把Pod调度到具有该污点的节点上,同时会将该节点上已经存在的Pod驱逐出去。

污点的新增、查看和删除:

# 新增污点。其中key值为check,value值为gongsl,effect为NoExecute
kubectl taint nodes node1 check=gongsl:NoExecute
# 查看污点
kubectl describe nodes node1|grep Taint
# 删除污点。其中key值为check
kubectl taint nodes node1 check:NoExecute-

下面进行一个案例演示:
k8s中的集群调度_第5张图片
当某种条件为真时,节点控制器会自动给节点添加一个污点。当前内置的污点包括:

  1. node.kubernetes.io/not-ready:节点未准备好。这相当于节点状态Ready的值为False
  2. node.kubernetes.io/unreachable:节点控制器访问不到节点。这相当于节点状态Ready的值为Unknown
  3. node.kubernetes.io/out-of-disk:节点磁盘耗尽;
  4. node.kubernetes.io/memory-pressure:节点存在内存压力;
  5. node.kubernetes.io/disk-pressure:节点存在磁盘压力;
  6. node.kubernetes.io/network-unavailable:节点网络不可用;
  7. node.kubernetes.io/unschedulable: 节点不可调度;
  8. node.cloudprovider.kubernetes.io/uninitialized:如果kubelet启动时指定了一个"外部"云平台驱动,它将给当前节点添加一个污点将其标志为不可用。在cloud-controller-manager的一个控制器初始化这个节点后,kubelet将删除这个污点。
5.2 容忍(Tolerations)

设置了污点的节点将根据taint的effect(NoSchedule、PreferNoSchedule、NoExecute)和Pod之间产生互斥的关系,Pod将在一定程度上不会被调度到该节点上。但我们可以在Pod上设置容忍(Tolerations),设置了容忍的Pod将可以容忍污点的存在,可以被调度到存在污点的的节点上。

在k8s中,是使用Pod中spec属性下的tolerations属性进行Pod容忍的设置的。下面是Pod容忍可能涉及的相关设置:

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoExecute"
  tolerationSeconds: 3600
- key: "key2"
  operator: "Exists"
  effect: "NoSchedule"
  • 上面key,vaule,effect这些属性的属性值要与节点上设置的污点组成部分中的key=value:effect保持一致;
  • 上面的operator属性的值默认为Equal,此时的value属性值需要和污点的value值相对应,operator属性的值还可以是Exists,此时将会忽略value属性,所以这时value属性是不用写的;
  • 上面的tolerationSeconds属性用于描述当Pod需要被驱逐时仍可以在节点上继续保留运行的时间,单位是秒,也就是说多少秒后Pod才会被驱逐。

特殊情况说明:

  1. 如果一个容忍度的key为空且operator为Exists,表示这个容忍度与任意的key、value和effect都匹配,即这个容忍度能容忍任意污点(taint)。
tolerations:
- operator: "Exists"
  1. 当不指定effect值时,表示容忍指定键名对应的所有污点效果选项。
tolerations:
- key: "key1"
  operator: "Exists"

关于Pod容忍的案例:

先新建两个Pod,对应的yaml文件如下所示:

apiVersion: v1
kind: Pod
metadata:
  name: pod-nginx1
spec:
  containers:
  - name: nginx
    image: nginx:1.20
    imagePullPolicy: IfNotPresent
  tolerations:
  - key: "key1"
    operator: "Exists"
    effect: "NoExecute"
    tolerationSeconds: 120
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-nginx2
spec:
  containers:
  - name: nginx
    image: nginx:1.20
    imagePullPolicy: IfNotPresent
  tolerations:
  - key: "key2"
    operator: "Exists"
    effect: "NoExecute"

image-20210513140837642
既然都运行在了node1节点上,那就给node1节点打污点,演示驱逐效果:

#执行如下命令,给node1节点打一个污点,这里用的是只有key值没有value值的污点
kubectl taint nodes node1 key1:NoExecute

节点打污点后,由于名为pod-nginx2的Pod没有匹配键值为key1的容忍,所以该Pod会被立即驱逐,名为pod-nginx1的Pod虽然有匹配键值为key1的容忍,但是由于将tolerationSeconds设置为了120,所以120秒后,该Pod也会被驱逐。
k8s中的集群调度_第6张图片
我们可以给一个节点添加多个污点,也可以给一个Pod添加多个容忍。k8s处理多个污点和容忍的过程就像一个过滤器:从一个节点的所有污点开始遍历,过滤掉那些Pod中存在与之相匹配的容忍度的污点。余下未被过滤的污点的effect值决定了Pod是否会被分配到该节点,特别是以下情况:

  • 如果未被过滤的污点中存在至少一个effect值为NoSchedule的污点,则k8s不会将分配到该节点;
  • 如果未被过滤的污点中不存在effect值为NoSchedule的污点,但是存在effect值为PreferNoSchedule的污点,则Kubernetes会尝试不将Pod分配到该节点;
  • 如果未被过滤的污点中存在至少一个effect值为NoExecute的污点,则Kubernetes不会将Pod分配到该节点(如果 Pod还未在节点上运行),或者将Pod从该节点驱逐(如果Pod已经在节点上运行)。

例如,假设我们给一个节点添加了如下污点:

kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key1=value1:NoExecute
kubectl taint nodes node1 key2=value2:NoSchedule

假定有一个Pod,它有两个容忍度:

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

在这种情况下,上述Pod不会被分配到上述节点,因为其没有容忍度和第三个污点相匹配。但是如果在给节点添加上述污点之前,该Pod已经在上述节点运行,那么它还可以继续运行在该节点上,因为不能和上述Pod相匹配的上述节点的第三个污点的effect值并不是NoExecute,所以不会驱逐已经运行在节点上的Pod。

前文提到过污点的effect值NoExecute会影响已经在节点上运行的Pod:

  • 如果Pod不能忍受effect值为NoExecute的污点,那么Pod将马上被驱逐;
  • 如果Pod能够忍受effect值为NoExecute的污点,但是在容忍度定义中没有指定tolerationSeconds,则Pod还会一直在这个节点上运行;
  • 如果Pod能够忍受effect值为NoExecute的污点,而且指定了tolerationSeconds,则Pod还能在这个节点上继续运行这个指定的时间长度。

注意事项:

  • k8s会自动给Pod添加一个key为node.kubernetes.io/not-ready的容忍度并配置 tolerationSeconds=300,除非用户提供的Pod配置中已经已存在了key为node.kubernetes.io/not-ready的容忍度;

  • k8s也会给Pod添加一个key为node.kubernetes.io/unreachable的容忍度并配置tolerationSeconds=300,除非用户提供的Pod配置中已经已存在了key为node.kubernetes.io/unreachable的容忍度;

  • DaemonSet中的Pod被创建时,针对以下污点自动添加的NoExecute的容忍度将不会指定tolerationSeconds

    • node.kubernetes.io/unreachable
    • node.kubernetes.io/not-ready

    这保证了出现上述问题时DaemonSet中的Pod永远不会被驱逐。

DaemonSet控制器自动为所有守护进程添加如下NoSchedule容忍度以防DaemonSet崩溃:

  • node.kubernetes.io/memory-pressure
  • node.kubernetes.io/disk-pressure
  • node.kubernetes.io/out-of-disk(只适合关键Pod)
  • node.kubernetes.io/unschedulable(1.10或更高版本)
  • node.kubernetes.io/network-unavailable(只适合主机网络配置)

添加上述容忍度确保了向后兼容,我们也可以选择自由向DaemonSet添加容忍度。

你可能感兴趣的:(学习总结,k8s)