K8S学习笔录 - Node污点与Pod容忍

原文连接node

污点与容忍主要经过对Node设置Taint和对Pod设置Toleration实现的。nginx

Node - Taint

为节点设置污点可让部分为处理该污点的Pod没法部署在该节点上。并对不容忍的Pod作出相应的处理。git

设置Node的污点只须要使用 kubectl taint 便可,具体使用能够经过 kubectl taint --help 查看。github

节点的污点包含了一个key、value以及一个effect,表现为 <key>=<value>:<effect>json

不一样的effect表明着不一样的效果api

  1. NoSchedule 表示若是Pod没有容忍这些污点,Pod则不能被调度到包含这些污点的节点上
  2. PreferNoSchedule 是NoSchedule的软限制版本,尽可能阻止,但若是没有其余节点能够用,依然会调度到有该污点的节点上
  3. NoExecute 不一样于NoSchedule,此效果会影响正在节点上运行的Pod。若是在一个节点上增长了效果为NoExecute的污点,正在该节点上运行的Pod也会受到影响。

配置中污点的结构以下bash

type Taint struct {
    // Key 污点的Key
    Key string `json:"key"`

    // Value 污点的Value
    Value string `json:"value,omitempty"`

    // 当Pod不容忍此污点时的行为
    // 值为NoSchedule、PreferNoSchedule、NoExecute
    Effect TaintEffect `json:"effect"`

    // Node的添加时间,只在NoExecute状况下使用
    TimeAdded *metav1.Time `json:"timeAdded,omitempty"`
}
复制代码

Pod - Toleration

Pod能够经过设置容忍内容来容忍节点上的污点。markdown

type Toleration struct {
    // Key是要容忍的Key得值
    // 空意味着匹配全部的Key,若是Key是空,则下面的operator必须是Exists
    // 这个组合一位置匹配全部的Key以及全部的值,容忍一切
    Key string `json:"key,omitempty"`

    // Opeartor表示Key和Value的关系
    // 值能够是 Exists 和 Equal,默认是Equal
    // Exists是值得一个通配符,能够容忍带有对应Key的任意Pod,而不关心Key的值是什么
    // Equal则要求Key和Value都要匹配才行
    Operator TolerationOperator `json:"operator,omitempty"`

    // Value是Key所对应的值
    // 若是operator是Exists,则Value应为空,不然应是一个匹配字符串
    Value string `json:"value,omitempty"`

    // Effect代表要匹配污点的影响效果。空值为匹配全部效果
    // 该值能够是 NoSchedule、PreferNoSchedule、NoSchedule和NoExecute
    Effect TaintEffect `json:"effect,omitempty"`

    // TolerationSeconds在effect被设置为NoExecute时生效。他代表了Pod对污点的容忍时间
    // 默认状况不设置该值,代表永远容忍,不知足条件了也不会被驱逐
    // 一旦设置,即使Pod知足全部条件,也会在时间到达以后驱逐Pod,0和负值表示当即驱逐
    TolerationSeconds *int64 `json:"tolerationSeconds,omitempty"`
}

// TolerationOperator的定义以下
type TolerationOperator string
const (
    TolerationOpExists TolerationOperator = "Exists"
    TolerationOpEqual  TolerationOperator = "Equal"
)

// TaintEffect的定义以下
type TaintEffect string
const (
    // 若是Pod没有容忍这个污点,则不容许新的Pod调度到此节点。
    // 因为该行为由调度程序执行,因此容许直接提交给kubelet而不经过调度器的Pod执行(目前还没整明白怎么搞)。
    // 也容许已经运行可是不知足条件的Pod继续运行。
    TaintEffectNoSchedule TaintEffect = "NoSchedule"

    // 与TaintEffectNoSchedule相似,可是尽可能不调度新的Pod到该节点,但不由止。
    // 该行为由调度器执行。
    TaintEffectPreferNoSchedule TaintEffect = "PreferNoSchedule"

    // 驱逐全部不知足污点的Pod(即便正在运行)
    // 由节点控制器执行
    TaintEffectNoExecute TaintEffect = "NoExecute"
)
复制代码

从配置结构中大概已经明白了该配置的简单状况网络

若是想让一个Pod容忍Node的污点,Pod的Toleration中的key和effect须要与Taint的设置保持一致,而且知足如下条件之一app

  1. operator的值是Exists
  2. operator的值是Equal而且value相等

另外,关于key和effetc有以下两个特殊状况

  1. 空的key配合Exists操做符,这可以匹配全部的键和值
  2. 空的effect匹配全部的effect

配置示例

  1. 为节点 tx 添加污点 disk=hdd:NoSchedule
  2. 尝试向该节点部署一个未容忍该污点的Pod
  3. 尝试向该节点部署一个容忍该污点的Pod
  4. 为节点 tx 添加污点 type=app:NoExecute
  5. 检查增长污点后NoExecute的效果,Pod应被当即驱逐
  6. 尝试向该节点部署一个容忍了两个污点的Pod,对NoExecute的容忍时间为60s
  7. 检查容忍效果,60s后被驱逐

Step - 1 为节点 tx 添加污点 disk=hdd:NoSchedule

$ kubectl taint nodes tx disk=hdd:NoSchedule
node/tx tainted
复制代码

Step - 2 尝试向该节点部署一个未容忍该污点的Pod

刚刚为节点增长了一个污点,那么如今就来尝试向该节点上建立一个未配置容忍的Pod,配置文件问t-1.yaml

apiVersion: v1
kind: Pod
metadata:
 name: t-1
spec:
 containers:
 - name: nginx
 image: nginx
 nodeSelector:
    kubernetes.io/hostname: tx
复制代码

建立发现,此Pod一直出于Pending状态。经过 kubectl describe pod tolerations 可观察到,是由于没有知足条件的节点部署

$ kubectl get pods
NAME   READY   STATUS    RESTARTS   AGE
t-1    0/1     Pending   0          15s
复制代码

Step - 3 尝试向该节点部署一个容忍该污点的Pod

删除掉刚刚建立的Pod,并修改配置文件建立一个容忍了该污点的Pod

apiVersion: v1
kind: Pod
metadata:
 name: t-1
spec:
 containers:
 - name: nginx
 image: nginx
 nodeSelector:
    kubernetes.io/hostname: tx
 tolerations:
 - key: "disk"
 operator: "Equal"
 value: "hdd"
 effect: "NoSchedule"
复制代码
$ kubectl create -f t-1.yaml
pod/t-1 created

$ kubectl get pods -o wide
NAME   READY   STATUS    RESTARTS   AGE
t-1    1/1     Running   0          11s
复制代码

Step - 4 为节点 tx 添加污点 type=app:NoExecute

为节点添加 disk=hdd:NoExecute 的污点

$ kubectl taint nodes tx disk=hdd:NoExecute
node/tx tainted
复制代码

Step - 5 检查增长污点后NoExecute的效果,Pod应被当即驱逐

$ kubectl get pods
NAME   READY   STATUS        RESTARTS   AGE
t-1    1/1     Terminating   0          1m32s
复制代码

Step - 6 尝试向该节点部署一个容忍了两个污点的Pod,对NoExecute的容忍时间为60s

如今咱们为Pod的配置文件添加上容忍,再来尝试(注意,如今 tx 节点上有两个taint)

apiVersion: v1
kind: Pod
metadata:
 name: t-1
spec:
 containers:
 - name: nginx
 image: nginx
 nodeSelector:
    kubernetes.io/hostname: tx
 tolerations:
 - key: "disk"
 operator: "Equal"
 value: "hdd"
 effect: "NoExecute"
 tolerationSeconds: 60
 - key: "disk"
 operator: "Equal"
 value: "hdd"
 effect: "NoSchedule"
复制代码

Step - 7 检查容忍效果,60s后被驱逐

根据配置建立Pod,整个Pod的事件列表以下,在60s的时候,Pod被驱逐了... 真是好使

Events:
  Type    Reason     Age        From               Message
  ----    ------     ----       ----               -------
  Normal  Scheduled  <unknown>  default-scheduler  Successfully assigned default/t-1 to tx
  Normal  Pulling    60s        kubelet, tx        Pulling image "nginx"
  Normal  Pulled     51s        kubelet, tx        Successfully pulled image "nginx"
  Normal  Created    50s        kubelet, tx        Created container nginx
  Normal  Started    50s        kubelet, tx        Started container nginx
  Normal  Killing    2s         kubelet, tx        Stopping container nginx
复制代码

过程当中碰见的一些问题

整个过程是这样的

  1. 设置了Node的污点
  2. 尝试向Node部署容忍disk=hdd:NoExecute的Pod

然而发现部署不上,报错信息是

Events:
  Type     Reason                  Age               From               Message
  ----     ------                  ----              ----               -------
  Normal   Scheduled               <unknown>         default-scheduler  Successfully assigned default/t-1 to tx
  Warning  FailedCreatePodSandBox  16s               kubelet, tx        Failed to create pod sandbox: rpc error: code = Unknown desc = [failed to set up sandbox container "5a3a5babd3baeaa3c7fd7f55f807f2d26335d59c60bb0d6bd088d64ab091daa2" network for pod "tolerations-1": networkPlugin cni failed to set up pod "tolerations-1_default" network: unable to allocate IP address: Post http://127.0.0.1:6784/ip/5a3a5babd3baeaa3c7fd7f55f807f2d26335d59c60bb0d6bd088d64ab091daa2: dial tcp 127.0.0.1:6784: connect: connection refused, failed to clean up sandbox container "5a3a5babd3baeaa3c7fd7f55f807f2d26335d59c60bb0d6bd088d64ab091daa2" network for pod "tolerations-1": networkPlugin cni failed to teardown pod "tolerations-1_default" network: Delete http://127.0.0.1:6784/ip/5a3a5babd3baeaa3c7fd7f55f807f2d26335d59c60bb0d6bd088d64ab091daa2: dial tcp 127.0.0.1:6784: connect: connection refused]
  Normal   SandboxChanged          2s (x3 over 15s)  kubelet, tx        Pod sandbox changed, it will be killed and re-created.
复制代码

起初觉得在部署集群的时候,即便Master节点应用了weave网络插件,其余子节点也须要手动部署一个weave服务。最开始的时候,我也是这样修复了这个问题。

后来忽然意识到,Master实际上在每一个Node上都不部署了weave的服务,然而在对Node设置NoExecute的污点之后,将这个Pod驱逐了...

相关文章
相关标签/搜索