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驅逐了...

相關文章
相關標籤/搜索