NodeSelector(定向调度)
NodeAffinity(Node亲和性)
PodAffinity(Pod亲和性)node
一般状况下,使用的都是k8s默认的调度调度方式,可是在有些状况下,咱们须要将pod运行在具备特色的标签的node上才能都运行,这个时候,pod的调度策略就不能使用k8s默认的调度策略了,这个时候,就须要指定调度策略,告诉k8s须要将pod调度到那些node(节点)上。nginx
1.nodeSelector数据库
常规状况下,会直接使用nodeSelector这种调度策略。labels(标签) 是k8s里面用来编标记资源的一种经常使用的方式,咱们能够给node标记特殊的标签,而后nodeSelector会将pod调度到带有指定labels的node上的。
提供简单的pod部署限制,pod选择一个或多个node的label部署
给node添加labelapi
kubectl label nodes <node-name> <label-key>=<label-value>
为pod添加nodeSelector机制bash
apiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: disktype: ssd
部署podapp
[root@master ~]# kubectl create -f test.yaml pod/nginx created
查看结果frontend
[root@master ~]# kubectl get pod -A -o wide NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES default nginx 0/1 ContainerCreating 0 37s <none> node-1 <none>
从上面的执行结果能够看出,pod 经过默认的 default-scheduler 调度器到了node-1节点上。不过,这种调度方式属于强制性的。若是node02上的资源不足,那么pod的状态将会一直是pending状态。这就是nodeselector的用法了。ide
2.亲和性和反亲和性调度
k8s的默认调度流程其实是通过了两个阶段predicates,priorities 。使用默认的调度流程的话,k8s会将pod调度到资源充裕的节点上,使用nodeselector的调度方法,又会将pod调度具备指定标签的pod上。而后在实际生产环境中,咱们须要将pod调度到具备些label的一组node才能知足实际需求,这个时候就须要nodeAffinity、podAffinity以及 podAntiAffinity(pod 反亲和性)。ui
亲和性能够分为具体能够细分为硬和软两种亲和性
软亲和性:若是调度的时候,没有知足要求,也能够继续调度,即能知足最好,不能也无所谓
硬亲和性:是指调度的时候必须知足特定的要求,若是不知足,那么pod将不会被调度到当前nodespa
requiredDuringSchedulingIgnoredDuringExecution #硬性强制
preferredDuringSchedulingIgnoredDuringExecution #软性配置
3.nodeAffinity 节点亲和性
节点亲和性主要是用来控制 pod 能部署在哪些节点上,以及不能部署在哪些节点上的。它能够进行一些简单的逻辑组合了,不仅是简单的相等匹配。
preferredDuringSchedulingIgnoredDuringExecution
强调优先知足制定规则,调度器会尝试调度pod到Node上,但并不强求,至关于软限制。多个优先级规则还能够设置权重值,以定义执行的前后顺序。
接下来看一个示例,使用nodeAffinity控制 pod 的调度,以下例子
apiVersion: v1 kind: Pod metadata: name: with-node-affinity spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: beta.kubernetes.io/arch operator: In values: - amd64 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: disk-type operator: In values: - ssd containers: - name: with-node-affinity image: nginx
设置label
[root@master ~]# kubectl label nodes node-2 disk-type=ssd node/node-2 labeled
建立pod并查看运行结果
[root@master yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES with-node-affinity 0/1 ContainerCreating 0 4m <none> node-2 <none> <none>
NodeAffinity规则设置的注意事项以下:
若是同时定义了nodeSelector和nodeAffinity,name必须两个条件都获得知足,pod才能最终运行在指定的node上。
若是nodeAffinity指定了多个nodeSelectorTerms,那么其中一个可以匹配成功便可。
若是在nodeSelectorTerms中有多个matchExpressions,则一个节点必须知足全部matchExpressions才能运行该pod。
matchExpressions : 匹配表达式,这个标签能够指定一段,例如pod中定义的key为zone,operator为In(包含那些),values为 foo和bar。就是在node节点中包含foo和bar的标签中调度
如今kubernetes提供的操做符有下面的几种
In:label 的值在某个标签中
NotIn:label 的值不在某个标签中
Gt:label 的值大于某个值
Lt:label 的值小于某个值
Exists:某个 label 存在
DoesNotExist:某个 label 不存在
4.podAffinity pod亲和性
Pod的亲和性主要用来解决pod能够和哪些pod部署在同一个集群里面,即拓扑域(由node组成的集群)里面;而pod的反亲和性是为了解决pod不能和哪些pod部署在一块儿的问题,两者都是为了解决pod之间部署问题。须要注意的是,Pod 间亲和与反亲和须要大量的处理,这可能会显著减慢大规模集群中的调度,不建议在具备几百个节点的集群中使用,并且Pod 反亲和须要对节点进行一致的标记,即集群中的每一个节点必须具备适当的标签可以匹配topologyKey。若是某些或全部节点缺乏指定的topologyKey标签,可能会致使意外行为。
Pod亲和性场景,咱们的k8s集群的节点分布在不一样的区域或者不一样的机房,当服务A和服务B要求部署在同一个区域或者同一机房的时候,咱们就须要亲和性调度了。
labelSelector : 选择跟那组Pod亲和
namespaces : 选择哪一个命名空间
topologyKey : 指定节点上的哪一个键
pod亲和性调度须要各个相关的pod对象运行于"同一位置", 而反亲和性调度则要求他们不能运行于"同一位置";
这里指定“同一位置” 是经过 topologyKey 来定义的,topologyKey 对应的值是 node 上的一个标签名称,好比各别节点zone=A标签,各别节点有zone=B标签,pod affinity topologyKey定义为zone,那么调度pod的时候就会围绕着A拓扑,B拓扑来调度,而相同拓扑下的node就为“同一位置”。
若是基于各个节点kubernetes.io/hostname标签做为评判标准,那么很明显“同一位置”意味着同一节点,不一样节点既为不一样位置。
pod亲和性
apiVersion: v1 kind: Pod metadata: name: pod-first labels: app: myapp tier: frontend spec: containers: - name: myapp image: daocloud.io/library/nginx:latest --- apiVersion: v1 kind: Pod metadata: name: pod-second labels: app: db tier: db spec: containers: - name: busybox image: daocloud.io/library/busybox imagePullPolicy: IfNotPresent command: ["sh","-c","sleep 3600"] affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - {key: app, operator: In, values: ["myapp"]} topologyKey: kubernetes.io/hostname
查看结果
[root@master yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-first 1/1 Running 0 10m 10.244.1.6 node-1 <none> <none> pod-second 1/1 Running 0 10m 10.244.1.7 node-1 <none> <none>
pod反亲和性
Pod反亲和性场景,当应用服务A和数据库服务B要求尽可能不要在同一台节点上的时候。
apiVersion: v1 kind: Pod metadata: name: pod-first-1 labels: app: myapp tier: frontend spec: containers: - name: myapp image: daocloud.io/library/nginx:latest --- apiVersion: v1 kind: Pod metadata: name: pod-second-2 labels: app: backend tier: db spec: containers: - name: busybox image: daocloud.io/library/busybox:latest imagePullPolicy: IfNotPresent command: ["sh","-c","sleep 3600"] affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - {key: app, operator: In, values: ["myapp"]} topologyKey: kubernetes.io/hostname
查看结果
[root@master yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-first-1 1/1 Running 0 7m28s 10.244.1.8 node-1 <none> <none> pod-second-2 1/1 Running 0 7m28s 10.244.2.6 node-2 <none> <none>
对于nodeAffinity不管是硬策略仍是软策略方式,都是调度 POD 到预期节点上,而Taints刚好与之相反,若是一个节点标记为 Taints ,除非 POD 也被标识为能够容忍污点节点,不然该 Taints 节点不会被调度pod。
好比用户但愿把 Master 节点保留给 Kubernetes 系统组件使用,或者把一组具备特殊资源预留给某些 POD,则污点就颇有用了,POD 不会再被调度到 taint 标记过的节点。
将节点设置为污点
[root@master yaml]# kubectl taint node node-2 key=value:NoSchedule node/node-2 tainted
查看污点
[root@master yaml]# kubectl describe node node-1 | grep Taint Taints: <none>
去除节点污点
[root@master yaml]# kubectl taint node node-2 key=value:NoSchedule- node/node-2 untainted
污点分类
NoSchedule:新的不能容忍的pod不能再调度过来,可是以前运行在node节点中的Pod不受影响
NoExecute:新的不能容忍的pod不能调度过来,老的pod也会被驱逐
PreferNoScheduler:表示尽可能不调度到污点节点中去
使用
若是仍然但愿某个 POD 调度到 taint 节点上,则必须在 Spec 中作出Toleration定义,才能调度到该节点,举例以下:
[root@master yaml]# kubectl taint node node-2 key=value:NoSchedule node/node-2 tainted [root@master yaml]# cat b.yaml apiVersion: v1 kind: Pod metadata: name: sss spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: app operator: In values: - myapp containers: - name: with-node-affinity image: daocloud.io/library/nginx:latest 注意:node-2节点设置为污点,因此label定义到node-2,可是由于有污点因此调度失败,如下是新的yaml文件 [root@master yaml]# cat b.yaml apiVersion: v1 kind: Pod metadata: name: sss-1 spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: app operator: In values: - myapp containers: - name: with-node-affinity image: daocloud.io/library/nginx:latest tolerations: - key: "key" operator: "Equal" value: "value" effect: "NoSchedule"
结果
旧的调度失败,新的调度成功
[root@master yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES sss 0/1 Pending 0 3m2s <none> <none> <none> <none> sss-1 1/1 Running 0 7s 10.244.2.9 node-2 <none> <none>
注意
tolerations: #添加容忍策略
operator值是Exists,则value属性能够忽略operator值是Equal,则表示key与value之间的关系是等于operator不指定,则默认为Equal