Pod系列 (二) Pod调度策略
一、Pod创建流程
上述过程分为在master节点和node节点上:
- master节点
create pod-->API Server-->Etcd,客户请求创建Pod,API Server进行创建,并且将创建的Pod信息写入到etcd中。
Scheduler-->API Server-->Etcd,Scheduler监听API Server,一旦监听到有新的Pod被创建,那么就负责调度,从Etcd中获取Pod信息,并且将其调度到合适的node节点中。
- node节点
Kubelet-->API Server-->Etcd-->docker run,Kubelet监听Api Server,负责将分配到该节点的Pod从Etcd中取出并且分配到该节点上,然后创建容器,完成Pod创建。
二、影响Pod调度的因素
上述中Scheduler负责调度Pod到合适的节点,那么它是如何具体调度的呢?主要有三方面控制:
- 资源限制和节点选择器
- 节点亲和性
- 污点和污点容忍
(一)资源限制和节点选择器
- 资源限制
apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: db image: mysql env: - name: MYSQL_ROOT_PASSWORD value: "password" resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"
requests和limits进行资源限制,调度到符合该资源要求的节点上。
- 节点选择器
如果将Pod调度到测试环境进行部署,那么只需要将测试环境的节点打上一个标签,然后在写Pod的yaml文档时指定即可,所以首先应该对相应的节点打上标签。
[root@k8smaster ~]# kubectl label node k8snode1 env_role=dev node/k8snode1 labeled [root@k8smaster ~]# kubectl get nodes k8snode1 --show-labels NAME STATUS ROLES AGE VERSION LABELS k8snode1 Ready <none> 60d v1.18.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,env_role=dev,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8snode1,kubernetes.io/os=linux
此时可以进行yaml文档编写:
apiVersion: v1 kind: Pod metadata: name: selector-pod spec: nodeSelector: env_role: dev containers: - name: nginx image: nginx: 1.15
因为给node1节点打上dev标签,所以该Pod会被调度到node1节点上。
(二)节点亲和性
节点亲和性nodeAffinity和节点选择器nodeSelector基本一样,根据节点上的标签来决定Pod调度到那些节点上,节点亲和性分为:
- 硬亲和性 约束条件必需满足
- 软亲和性 尝试满足
apiVersion: v1 kind: Pod metadata: name: with-node-affinity spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: #硬亲和性 nodeSelectorTerms: - matchExpressions: - key: env_role operator: In values: - dev - test preferredDuringSchedulingIgnoredDuringExecution: #软亲和性 - weight: 1 preference: matchExpressions: - key: group operator: In values: - prod containers: - name: web image: nginx imagePullPolicy: IfNotPresent
其中operator为操作符,节点亲和性支持的操作符有In、NotIn、Exists、DoesNotExist、Gt、Lt.
(三)污点和污点容忍
节点亲和性时Pod的一种属性,它使Pod被吸引到一类特定的节点上。污点(Taint)则相反,是节点的属性,它使节点能够排斥一类特定的Pod。
容忍度是应用于Pod上的,允许(但并不要求)Pod调度到有与之匹配的污点的节点上。
污点和容忍度(Toleration)相互配合,可以用来避免 Pod 被分配到不合适的节点上。
其应用场景有:
- 专用节点
- 配备了特殊硬件的节点
- 基于污点的驱逐
1、查看节点污点的情况
[root@k8smaster ~]# kubectl describe node k8smaster | grep Taint Taints: node-role.kubernetes.io/master:NoSchedule
从上面看出有一个NoSchedule的值,也就是说污点有三个值可供选择:
- NoSchedule 一定不被调度
- PreferNoSchedule 尽量不被调度
- NoExecute 不会调度,并且驱逐node中已有Pod
2、为节点添加污点
# 格式 kubectl taint node [node] key=value:污点的三个值 # 添加污点 [root@k8smaster ~]# kubectl taint node k8snode1 env_role=yes:NoSchedule node/k8snode1 tainted
假如此时我创建Pod,那么因为node1节点添加了污点,其值是NoSchedule,一定不会被调用。
[root@k8smaster ~]# kubectl create deployment web --image=nginx deployment.apps/web created [root@k8smaster ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES web-5dcb957ccc-89fl2 0/1 ContainerCreating 0 5s <none> k8snode2 <none> <none> [root@k8smaster ~]# kubectl scale deployment web --replicas=5 deployment.apps/web scaled [root@k8smaster ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES web-5dcb957ccc-2rjfz 0/1 ContainerCreating 0 3s <none> k8snode2 <none> <none> web-5dcb957ccc-89fl2 0/1 ErrImagePull 0 56s <none> k8snode2 <none> <none> web-5dcb957ccc-fcq2f 0/1 ContainerCreating 0 3s <none> k8snode2 <none> <none> web-5dcb957ccc-gnw4n 0/1 ContainerCreating 0 3s <none> k8snode2 <none> <none> web-5dcb957ccc-jb7sd 0/1 ContainerCreating 0 3s <none> k8snode2 <none> <none>
可以看到都在node2节点上。
3、删除污点
去除node1节点上的污点:
[root@k8smaster ~]# kubectl taint node k8snode1 env_role:NoSchedule- node/k8snode1 untainted
4、污点容忍度
如果设置的某节点污点值是NoSchedule,那么如果满足污点容忍度也是可以被调度到的,如:
tolerations: - key: "key1" operator: "Equal" value: "value1" effect: "NoSchedule"
可以在PodSpec中定义Pod的容忍度,如果Pod满足上述的容忍度就能够被分配到node1节点上。