原文連接node
污點與容忍主要經過對Node設置Taint和對Pod設置Toleration實現的。nginx
爲節點設置污點可讓部分爲處理該污點的Pod沒法部署在該節點上。並對不容忍的Pod作出相應的處理。git
設置Node的污點只須要使用 kubectl taint
便可,具體使用能夠經過 kubectl taint --help
查看。github
節點的污點包含了一個key、value以及一個effect,表現爲 <key>=<value>:<effect>
。json
不一樣的effect表明着不一樣的效果api
配置中污點的結構以下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能夠經過設置容忍內容來容忍節點上的污點。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
另外,關於key和effetc有以下兩個特殊狀況
tx
添加污點 disk=hdd:NoSchedule
tx
添加污點 type=app:NoExecute
tx
添加污點 disk=hdd:NoSchedule
$ kubectl taint nodes tx disk=hdd:NoSchedule node/tx tainted 複製代碼
剛剛爲節點增長了一個污點,那麼如今就來嘗試向該節點上建立一個未配置容忍的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
複製代碼
刪除掉剛剛建立的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 複製代碼
tx
添加污點 type=app:NoExecute
爲節點添加 disk=hdd:NoExecute
的污點
$ kubectl taint nodes tx disk=hdd:NoExecute
node/tx tainted
複製代碼
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
t-1 1/1 Terminating 0 1m32s
複製代碼
如今咱們爲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" 複製代碼
根據配置建立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 複製代碼
整個過程是這樣的
然而發現部署不上,報錯信息是
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驅逐了...