在实际状况下咱们可能须要将Pod调度到指定的一些Node节点上,能够经过Node的标签(Label)和Pod的NodeSelector属性相匹配,来达到上述目的。node
咱们能够经过在节点打上Label,经过定义Pod时,指定Label将Pod调度到指定的节点上linux
kubectl label node nodename label=labelname
nginx
[root@k8s-master01 ~]# kubectl get node --show-labels NAME STATUS ROLES AGE VERSION LABELS k8s-master01 Ready <none> 6d6h v1.19.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master01,kubernetes.io/os=linux,node.kubernetes.io/node= k8s-master02 Ready <none> 6d6h v1.19.0 app=linux,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master02,kubernetes.io/os=linux,node.kubernetes.io/node= k8s-node01 Ready <none> 6d6h v1.19.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ds=true,ingress=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node01,kubernetes.io/os=linux,node.kubernetes.io/node=,xinyuan=liu k8s-node02 Ready <none> 6d6h v1.19.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ds=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node02,kubernetes.io/os=linux,node.kubernetes.io/node=,zone=foo [root@k8s-master01 ~]# [root@k8s-master01 ~]# [root@k8s-master01 ~]# kubectl label node k8s-node01 itax=app
配置yaml文件
在template.metadata.spec.nodeSelector定义node标签web
[root@k8s-master01 ~]# cat deploy.yaml apiVersion: apps/v1 kind: Deployment metadata: namespace: default name: nginxapp labels: app: nginx-deploy spec: replicas: 2 selector: matchLabels: app: mynginx template: metadata: labels: app: mynginx spec: containers: - name: nginxweb1 image: nginx:1.15-alpine nodeSelector: #定义node标签调度 itax: app #标签名字和值
注意算法
NodeAffinity称之为Node节点亲和性调度有两种调度策略api
RequiredDuringSchedulingIgnoredDuringExecution
称之为硬亲和,必须知足指定定义的规则才会将Pod调度到Node上app
PreferredDuringSchedulingIgnoredDuringExecution
软亲和,尽可能将Pod调度到知足条件的Node上,若是没有知足的,调度器会根据算法选择一个最合适的节点优化
在template.spec下定义ui
[root@k8s-master01 ~]# cat deploy.yaml apiVersion: apps/v1 kind: Deployment metadata: namespace: default name: nginxapp labels: app: nginx-deploy spec: replicas: 2 selector: matchLabels: app: mynginx template: metadata: labels: app: mynginx spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - preference: matchExpressions: - key: zone #标签名 operator: In #表示值在key的里面,下边能够定义多个key values: - foo #标签值 weight: 1 containers: - name: nginxweb image: nginx:1.15-alpine
此Pod定义的是软亲和,表示将此Pod尽可能调度到node节点标签名为zone值是foo的节点上spa
apiVersion: apps/v1 kind: Deployment metadata: namespace: default name: nginxapp labels: app: nginx-deploy spec: replicas: 2 selector: matchLabels: app: mynginx template: metadata: labels: app: mynginx spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - preference: matchExpressions: - key: zone operator: In values: - foo weight: 1 requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: zone operator: In values: - bar1 containers: - name: nginxweb image: nginx:1.15-alpine
若是两个同时使用那么先匹配硬亲和而后再从匹配到的硬亲和去匹配软亲和
Pod的亲和性和反亲和性(互斥)
能让用户从另外一个角度来限制Pod所能运行的节点,Pod的亲和和互斥是基于Pod标签进行判断的
注意Pod的亲和和互斥是基于namespace进行匹配的
apiVersion: apps/v1 kind: Deployment metadata: namespace: default name: nginxapp labels: app: nginx-deploy spec: replicas: 2 selector: matchLabels: app: mynginx template: metadata: labels: app: mynginx spec: containers: - name: nginxweb1 image: nginx:1.15-alpine affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - mynginx topologyKey: kubernetes.io/hostname # 表示只要hostname值同样就说明是同一位置拓扑域
表示将Pod部署到Pod的标签名app值为mynginx的Pod所在节点的node上
apiVersion: apps/v1 kind: Deployment metadata: namespace: default name: nginxapp labels: app: nginx-deploy spec: replicas: 2 selector: matchLabels: app: mynginx template: metadata: labels: app: mynginx spec: containers: - name: nginxweb1 image: nginx:1.15-alpine affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - mynginx topologyKey: kubernetes.io/hostname # 表示只要hostname值同样就说明是同一位置拓扑域
对于Node affinity,不管是强制约束(hard)或偏好(preference)方式,都是调度pod到预期节点上,而Taints刚好与之相反,若是一个节点标记为Taints,除非 Pod也被标识为能够耐受污点节点,不然该Taints节点不会被调度pod。Taints与tolerations当前处于beta阶段, Taints节点应用场景好比用户但愿把Kubernetes Master节点保留给 Kubernetes 系统组件使用,或者把一组具备特殊资源预留给某些pod。pod不会再被调度到taint标记过的节点
若是想为特殊的用户指定一组node,能够添加一个污点到这组node上(运行命令: kubectl taint nodes nodename dedicated=groupName:NoSchedule)。而后添加对应的容忍到这个Pod上(这个最容易实现的方法是写一个客户端准入控制器)。带有相应容忍的Pod就能够像被调度到集群中其余node同样被调度到带有相应污点的node上。
污点是定义节点上的一种键值属性;主要用于让节点拒绝Pod的(拒绝那些不能容忍污点的Pod);因此说咱们得在Pod建议可以容忍的污点
Taint的定义对Pod的排斥结果
设置node污点
[root@k8s-master01 ~]# kubectl taint node k8s-master01 node-type=production:NoSchedule #此处node现有的Pod不会被驱逐
[root@k8s-master01 ~]# kubectl taint node k8s-master01 node-type=production:NoExecute #此处node现有的Pod会被驱除
设置Pod的容忍
apiVersion: apps/v1 kind: Deployment metadata: namespace: default name: nginxapp labels: app: nginx-deploy spec: replicas: 2 selector: matchLabels: app: mynginx template: metadata: labels: app: mynginx spec: containers: - name: nginxweb1 image: nginx:1.15-alpine affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - mynginx topologyKey: kubernetes.io/hostname # 表示只要hostname值同样就说明是同一位置拓扑域 tolerations: - key: "node-type" # 污点的key operator: "Equal" # 容忍程度 value: "producction" # 污点的volue effect: "NoSchedule"
具体的调度过程,通常以下:首先,客户端经过API Server的REST API/kubectl/helm建立pod/service/deployment/job等,支持类型主要为JSON/YAML/helm tgz。 接下来,API Server收到用户请求,存储到相关数据到etcd。 调度器经过API Server查看未调度(bind)的Pod列表,循环遍历地为每一个Pod分配节点,尝试为Pod分配节点。
调度过程分为2个阶段:
第一阶段:预选过程,过滤节点,调度器用一组规则过滤掉不符合要求的主机。好比Pod指定了所须要的资源量,那么可用资源比Pod须要的资源量少的主机会被过滤掉。
第二阶段:优选过程,节点优先级打分,对第一步筛选出的符合要求的主机进行打分,在主机打分阶段,调度器会考虑一些总体优化策略,好比把容一个Replication Controller的副本分布到不一样的主机上,使用最低负载的主机等。
选择主机:选择打分最高的节点,进行binding操做,结果存储到etcd中。 所选节点对于的kubelet根据调度结果执行Pod建立操做