关于污点的小结:
污点存在的意义:
使用 kubectl taint 命令可以给某个 node节点设置污点,Node 被设置上污点之后就和 Pod 之间存在
了一种互斥的关系,可以让 Node 拒绝 Pod 的调度执行,甚至将 Node 已经存在的 Pod 驱逐出去:
key=value:effect
通过给节点设置不同的污点,可以制定一个总的策略,例如,新节点使用effect NoExecute,那么,想在此节点运行pod就必须是有设置tolerations(容忍策略)的特定pod了,无疑安全性会大大提高,一般master节点是不建议运行非核心服务的pod的,因此,也可以给master打上NoSchedule污点,以保护master。
稍作总结,三种污点effect里,NoSchedule和PreferNoSchedule是比较温和的,NoExecute是最为严厉的,即使pod设置了nodeSelector或者nodeSelectorTerm,设置了此effect的节点也是不可使用的,也可以算是真正的节点禁用,因此,NoExecute是慎用的。
NoSchedule等于是节点维护状态,PreferNoSchedule等于是无所谓,你非要调度到这个节点也行。
以上都是面向某个节点内的所有pod调度,未免对于pod的调度不够精细,例如,NoExecute直接将节点内的pod全部清空,太暴力了(虽然这么做,整个节点的安全性非常高,和iptables防火墙一样的策略嘛,先禁止所有,然后在放开部分,相当于tolerations,其实这也是容忍存在的意义嘛)。那么,下面的调度策略将针对的是单个pod。
污点的effect可以设置多个
三,容忍策略---tolerations
容忍是相对于污点来说的,容忍是在pod内设置的。光说不练假把式对吧,直接看kube-flannel的部署清单文件内的相关内容吧:
apiVersion: apps/v1 kind: DaemonSet metadata: name: kube-flannel-ds namespace: kube-system labels: tier: node app: flannel spec: selector: matchLabels: app: flannel template: metadata: labels: tier: node app: flannel spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/os operator: In values: - linux hostNetwork: true priorityClassName: system-node-critical tolerations: - operator: Exists effect: NoSchedule
此段容忍表示,默认的容忍污点的effec 是NoSchedule的节点,也就是说即使此node节点设置了NoSchedule,该pod仍然可以部署,为什么是这样设置呢?其实此清单文件是可以使用在kubeadmin部署的集群内,默认的kubeadmin部署的集群会对master节点设置NoSchedule的污点。
查看node2的污点(假设我已经提前设置好了污点):
[root@master coredns]# k describe node k8s-node2 |grep Taints Taints: key=values:NoExecute
此pod将不会被创建:
[root@master coredns]# cat nginx.yaml apiVersion: v1 kind: Pod metadata: name: pod-nodeaffinity-preferred namespace: default spec: containers: - name: nginx image: nginx:1.18 affinity: #亲和性设置 nodeAffinity: #设置node亲和性 preferredDuringSchedulingIgnoredDuringExecution: # 软限制 - weight: 1 preference: matchExpressions: # 匹配env的值在["xxx","yyy"]中的标签(当前环境没有) - key: nodeweb operator: In values: ["dsfsd","web"] nodeName: k8s-node2
修改成如下的pod才可以被创建(容忍三行):
apiVersion: v1 kind: Pod metadata: name: nginx namespace: default spec: containers: - name: nginx image: nginx:1.18 tolerations: - operator: Exists effect: NoExecute affinity: #亲和性设置 nodeAffinity: #设置node亲和性 preferredDuringSchedulingIgnoredDuringExecution: # 软限制 - weight: 1 preference: matchExpressions: # 匹配env的值在["xxx","yyy"]中的标签(当前环境没有) - key: nodeweb operator: In values: ["dsfsd","web"] nodeName: k8s-node2
容忍定义小结:
- 污点和容忍是相呼应的关系,也就是说有污点才有容忍,光有容忍是没有意义的。
- operator的值只有两个Equal和Exists两个,从字面翻译看,Equal表示必须相等,Exists表示默认情况。
- operator 的值为 Exists 时将会忽略 value 值,也可以直接省略values定义。
- operator 的值为 Exists 时可以省略key值,此时表示表示容忍所有的污点 key,例如:
1. tolerations: 2. - operator: “Exists”
- effect可以省略,省略effect 值时,表示容忍所有的污点作用,例如:
1. tolerations: 2. - key: “key” 3. operator: “Exists”
下面是一个比较完整的示例:
tolerations: - key: “key1” operator: “Equal” value: “value1” effect: “NoSchedule” tolerationSeconds: 3600 - key: “key1” operator: “Equal” value: “value1” effect: “NoExecute” - key: “key2” operator: “Exists” effect: “NoSchedule”
三,pod调度策略
这些策略都是写在资源清单文件内的,针对单独的pod
默认情况下,一个pod被调度到哪个node节点是由scheduler组件采用相应的算法计算出来的,这个过程是不受人工控制的,但是在实际使用中,这并不能满足所以要求,很多时候我们想控制某些pod到达某些节点,所以kubernetes就为我们提供了4种pod的调度策略来解决该问题。
(1)定向调度
主要是指定pod定向调度到哪个node节点上
a)nodeName策略
注:kubectl集群节点名nodeName称可以通过kubectl get nodes查看,例如本例:
[root@master coredns]# k get no
NAME STATUS ROLES AGE VERSION
k8s-master Ready 25d v1.18.3
k8s-node1 Ready 25d v1.18.3
k8s-node2 Ready 25d v1.18.3
资源清单文件内使用:
[root@master coredns]# cat nginx.yaml apiVersion: v1 kind: Pod metadata: name: pod-nodename namespace: default spec: containers: - name: nginx image: nginx:1.18 nodeName: k8s-node1 # 指定调度到node1节点上,注意此字段是pod属性,所以和containers在同一列
毫无疑问,此pod必定会在node2节点运行,即使有drain或者train设置了NoScheduler
b)NodeSelector策略
NodeSelector用于将pod调度到添加了指定标签的node节点上。它是通过kubernetes的label-selector机制实现的,也就是说,在pod创建之前,会由scheduler使用MatchNodeSelector调度策略进行label匹配,找出目标node,然后将pod调度到目标节点,该匹配规则是强制约束。简单的说就是给kubectl集群的node节点打上标签,然后调度器将pod调度到指定标签的node上。
例如给node2节点设置标签,并查询标签:
kubectl label nodes k8s-node2 node=LAMP [root@master coredns]# k get nodes --show-labels NAME STATUS ROLES AGE VERSION LABELS k8s-master Ready <none> 25d v1.18.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master,kubernetes.io/os=linux k8s-node1 Ready <none> 25d v1.18.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node1,kubernetes.io/os=linux k8s-node2 Ready <none> 25d v1.18.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node2,kubernetes.io/os=linux,node=LAMP
截取资源清单文件相关部分:
volumes: - name: mysql-persistent-storage persistentVolumeClaim: claimName: mysql-pvc #对应到pvc的名字 nodeSelector: node: LAMP
这里说明一哈,比如kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node2,这个是kubernetes.io/arch架构相关的,因此,这个是没法使用的。而我们新建的标签是kubernetes.io/os级别,操作系统类的,因此可以使用。