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节点上。

作者:iveBoy
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/shenjianping/p/14894729.html