原文连接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驱逐了...