首先说一下污点(Taint),当我们需要将master节点保留给Kubernetes系统组件调用时,或者需要保留master节点的资源时,我们可以标记一个Taint,当节点标记Taint时,除非Pod也被识别为可以容忍(Toleration)污点的节点,否则默认情况下Kubernetes scheduler不会将Pod调度到有污点的节点上
一般情况下我们部署的 Pod 是通过集群的自动调度策略来选择节点的,默认情况下调度器考虑的是资源足够,并且负载尽量平均,但是有的时候我们需要能够更加细粒度的去控制 Pod 的调度,比如我们内部的一些服务 gitlab 之类的也是跑在Kubernetes集群上的,我们就不希望对外的一些服务和内部的服务跑在同一个节点上了,担心内部服务对外部的服务产生影响;但是有的时候我们的服务之间交流比较频繁,又希望能够将这两个服务的 Pod 调度到同一个的节点上。这就需要用到 Kubernetes 里面的一个概念:亲和性和反亲和性。
污点 Taint
容忍 Toleration
首先说一下污点Taint
,当我们需要将master节点保留给Kubernetes系统组件调用时,或者需要保留master节点的资源时,我们可以标记一个Taint,当节点标记Taint时,除非Pod也被识别为可以容忍Toleration
污点的节点,否则默认情况下Kubernetes scheduler不会将Pod调度到有污点的节点上
Taint(污点)和 Toleration(容忍)可以作用于node和 pod 上,其目的是优化pod在集群间的调度,这跟节点亲和性类似,只不过它们作用的方式相反,具有taint的node和pod是互斥关系,而具有节点亲和性关系的node和pod是相吸的。另外还有可以给node节点设置label,通过给pod设置nodeSelector将pod调度到具有匹配标签的节点上。
Taint 和 toleration 相互配合,可以用来避免pod被分配到不合适的节点上。每个节点上都可以应用一个或多个taint,这表示对于那些不能容忍这些taint的 pod,是不会被该节点接受的。如果将toleration应用于pod上,则表示这些pod可以(但不要求)被调度到具有相应taint的节点上。
如果使用kubeadm搭建的集群,默认就会给master节点添加一个污点标记。我这里使用二进制安装一切自定义,所以我们跳过这步。从添加污点开始
污点taint标记节点的命令
# 添加taint污点命令
kubectl taint nodes k8s-01 key=value:NoSchedule
kubectl taint nodes k8s-02 key=value:NoExecute
kubectl taint nodes k8s-03 key=value:PreferNoSchedule
# 查看taint污点命令
[root@k8s-01 test]# kubectl describe node k8s-01|grep Taints
Taints: key=value:NoSchedule
#删除污点命令
kubectl taint node k8s-01 key:NoSchedule-
example
kubectl taint node [节点] [任意值]:[NoSchedule、NoExecute、PreferNoSchedule]
#删除和创建中的值要对应上,node节点的名称需要通过kubectl get node对应上
#这里不执行
首先我们先了解一下对应的参数
容忍 Toleration
前面我们介绍了将Pod添加污点,但是可能有一些比较重要的服务需要跑在master节点上,那么我们就需要添加一个容忍,允许哪些Pod跑在有污点的节点上
这里我们还是使用上面学到的nodeAffinity,使用硬策略将pod捆绑在k8s-01节点上,同时又在k8s-01节点上配置污点
#首先在k8s-01节点配置污点,将之前的pod全部移除
kubectl taint nodes k8s-01 key1=value:NoExecute
$ kubectl get pod --all-namespaces -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system coredns-6776c9d69-6chbp 1/1 Running 3 25d 172.30.200.2 k8s-03
kube-system coredns-6776c9d69-n45nb 1/1 Running 0 26s 172.30.232.2 k8s-02
kube-system kubernetes-dashboard-78bcf8c65c-vfbkq 1/1 Running 4 25d 172.30.8.2 k8s-04
#目前k8s-01节点的pod已经全部移除
接下来我们编写yaml文件,将nginx 添加容忍,并且使用硬策略只捆绑在k8s-01上 (这里使用硬策略和软策略或者不添加都是可以的。)
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: affinity
labels:
app: affinity
spec:
replicas: 3
revisionHistoryLimit: 10
template:
metadata:
labels:
app: affinity
spec:
containers:
- name: nginx
image: nginx
ports:
- name: http
containerPort: 80
tolerations: #添加容忍策略
- key: "key1" #对应我们添加节点的变量名
operator: "Equal" #操作符
value: "value" #容忍的值 key1=value对应
effect: NoExecute #添加容忍的规则,这里必须和我们标记的五点规则相同
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- k8s-01
operator值是Exists,则value属性可以忽略
operator值是Equal,则表示key与value之间的关系是等于
operator不指定,则默认为Equal
接下来我们创建查看结果
kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
affinity-7c85766dcb-2g6sv 1/1 Running 0 29s 172.30.40.3 k8s-01
affinity-7c85766dcb-gfmb2 1/1 Running 0 29s 172.30.40.2 k8s-01
affinity-7c85766dcb-vpctf 1/1 Running 0 29s 172.30.40.4 k8s-01
#目前所有的Pod都调度在k8s-01节点上,但是如果我们这里规则写的不匹配,那么Pod将处于pending状态
当然我们的匹配规则也是可以写成多个
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
在NoExecute可以指定一个可选tolerationSeconds字段,该字段指示添加污点后,指定停留在node污点的时间
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
tolerationSeconds: 3600
意味着如果此Pod正在运行并将匹配的污点添加到该节点,则该Pod将与该节点绑定3600秒,然后被逐出。
同时在Kubernets 1.6 引入了代表node问题的污点,node控制器当某种条件成立的时候会自动的给node打上污点。下面是其中内置的污点:
node.kubernetes.io/not-ready:node不是ready状态。对应于node的condition ready=false.
node.kubernetes.io/unreachable:node controller与node失联了。对应于node的condition ready=unknown
node.kubernetes.io/out-of-disk:node磁盘空间不足了。
node.kubernetes.io/network-unavailable:node的网断了
node.kubernets.io/unschedulable:node不是可调度状态
node.cloudprovider.kubernetes.io/uninitalized:kubelet是由外部云提供商提供的时候,刚开始的时候会打上这个污点来标记还未被使用。当cloud-controller-manager控制器初始化完这个node,kubelet会自动移除这个污点。
配置案例,只需要将key修改成对应的值即可
tolerations:
- key: "node.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 6000
参考
https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
https://www.cnblogs.com/xiexj/p/10561237.html