集群调度

1、调度过程说明

1.1、简介

Scheduler是kubernetes的调度器。主要的任务是把定义的pod分配到集群的节点上。听起来非常简单,但是有很多考虑的问题:
1、公平:如何保证每个节点都能被分配资源
2、资源高效利用:集群所有资源最大化被利用
3、效率:调度的性能要好,能够尽快的对大批量的pod完成调度工作
4、灵活:允许用户根据自己的需求控制调度的逻辑
Sheduler是作为单独的程序运行的,启动之后会一直坚挺API server,获取podspec,nodename为空的pod,对每个pod都会创建一个binding,表明该pod应该放到哪个节点上

1.2、调度过程

调度分为几个部分:首先是过滤掉不满足条件的节点,这个过程称为predicate;然后对通过的节点按照优先级排序,这个是priority;最后从中选择优先级最高的节点,如果中间任何一步骤有错误,就直接返回错误

1.3、Predicate有一系列的算法可以使用

PodFitsResources:节点上剩余的资源是否大于pod请求的资源
PodFitsHost:如果pod指定了nodename,检查节点名称是否和nodename匹配
PodFitsHostPorts:节点上已经使用的port是否和pod申请的port冲突
PodSelectorMatches:过滤掉和pod指定的label不匹配的节点

如果在predicate过程中没有合适的节点,pod会一直在pending状态,不断重试调度,直到有节点满足条件,经过这个步骤,如果有多个节点满足条件,就继续priorities过程:按照优先级大小对节点排序
优先级由一系列键值对组成,键是该优先级项的名称,值是它的权重(该项的重要性)。这些优先级选项包括:
1、LeastRequestedPriority:通过计算cpu和memory的使用率来决定权重,使用率越低权重越高。也就是说,这个优先级指标倾向于资源使用比例更低的节点
2、BalancedResourceAllocation:节点上cpu和memory使用率越接近,权重越高。这个应该和第一个一起使用,不应该单独使用
3、ImagelocalityPriority:倾向于已经有要使用镜像的节点,镜像总大小值越大,权重越高

2、自定义调度器

除了kubernetes自带的调度器,你也可以编写自己的调度器。通过spec:schedulername参数指定调度器的名字,可以为pod选择某个调度器进行调度。比如下面的pod选择my-scheduler进行调度,而不是默认default-scheduler

apiVersion: v1
kind: Pod
metadata:
  name: annotation-second-scheduler
  labels:
    name: multischeduler-example
spec:
  schedulername: my-scheduler
  containers:
  - name: nginx
    image: nginx

3、集群调度——亲和性

3.1、节点亲和性
3pod.spec.nodeAffinity

preferredDuringSchedulingIgnoredDuringExecution:软策略 (可/也不可)
requiredDuringSchedulingIgnoredDuringExecution:硬策略 (必须)

requiredDuringSchedulingIgnoredDuringExecution:硬策略
示例
apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: nginx
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: NotIn
            values:
            - node1
检查

只要kubernetes.io/hostname等于node1,pod一定不会运行在node1节点上,如果把NoIn改为In,只要kubernetes.io/hostname等于node1则pod一定会运行在node1节点上。(kubernetes.io/hostname为node的标签 可以使用kubectl get no --show-labels 查看)

preferredDuringSchedulingIgnoredDuringExecution:软策略
示例
apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: nginx
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - node3
检查

kubernetes.io/hostname等于node3,pod一定会运行在node3节点上,如果没有node3这个节点pod会随机运行(kubernetes.io/hostname为node的标签 可以使用kubectl get no --show-labels 查看)

键值运算关系
1、In:label的值在某个列表中
2、NotIn:label的值不在某个列表中
3、Gt:label的值大于某个值
4、Lt:label的值小于某个值
5、Exists:某个label存在
6、DoesNotExist:某个label不存在

如果“nodeSelectorTerms”下面有多个选项的话,满足任何一个条件就可以了;如果“matchExpressions”有多个选项的话,则必须同时满足这些条件才能正常调度pod

3.2、pod亲和性
pod.spec.affinity.podAffiinity/podAntiAffinity

preferredDuringSchedulingIgnoredDuringExecution:软策略 (可/也不可)
requiredDuringSchedulingIgnoredDuringExecution:硬策略 (必须)

requiredDuringSchedulingIgnoredDuringExecution:硬策略
示例
apiVersion: v1
kind: Pod
metadata:
  name: pod-3
  labels:
    app: pod-3
spec:
  containers:
  - name: pod-3
    image: nginx
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - node1
        topologyKey: kubernetes.io/hostname
说明

如果标签app的值为node1,则这两个pod运行在同一个node节点上。如果把podAffinity改为podAntiAffinity,则这两个pod不会运行在同一个node节点上

preferredDuringSchedulingIgnoredDuringExecution:软策略

podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              volumes:
              - node1

4、亲和性/反亲和性调度策略比较

调度策略 匹配标签 操作符 拓扑域支持 调度目标
nodeAffinity 主机 In,NotIn,Exists,DoesNotExist,Gt,Lt 指定主机
podAffinity POD In,NotIn,Exists,DoesNotExist POD与指定POD在同一拓扑域
podAnitAffinity POD In,NotIn,Exists,DoesNotExist POD与指定POD不再同一拓扑域

5、集群调度——污点和容忍

节点亲和性是pod的一种属性,它使pod被吸引到一类特定的节点。Taint则相反,它使节点能够排斥一类特定的pod

Taint和Toleration相互配合,可以用来避免pod被分配到不合适的节点上,每个节点上都可以应用一个或多个taint,这表示对于那些不能容忍这些taint的pod,是不会被该节点接受的,如果将toleration应用于pod上,则表示这些pod可以(但不要求)被调度到具有匹配taint的节点上

6、污点(Taint)

6.1、污点(taint)的组成

使用kubectl taint命令可以给某个node节点设置污点,node被设置上污点之后就和pod之间存在了一种相斥的关系,可以让node拒绝pod的调度执行,甚至将node已经存在的pod驱逐出去

6.2、每个污点的组成如下
key=value:effect

说明:每个污点有一个key和value作为污点的标签,其中value可以为空,effect描述污点的作用。当前taint effect支持以下三个选项

1、NoSchedule:表示k8s不会将pod调度到具有污点的node上
2、PreferNoSchedule:表示k8s将尽量避免pod调度到具有该污点的Node上
3、NoExecute:表示不会将pod调度到具有该污点的node上,同时会将node上已经存在的pod驱逐出去

6.3、污点的设置、查看和去除
6.3.1、设置污点
kubectl taint node node1 check=liuchao:NoExecute
6.3.2、节点说明中,查找taint字段
kubectl describe pod pod-name
6.3.3、去除污点
kubectl taint nodes 节点名 key1:NoSechdule-

7、容忍(Tolerations)

设置了污点的node将根据taint的effect:NoSchedule、preferNoSchedule、NoExecute和pod之间产生互斥的关系,pod将在一定程度上不会被调度到node上,但是我们可以在pod上设置容忍(toleration),意思是设置了容忍的pod将可以容忍污点的存在,可以被调度到存在污点的pod上

示例
pod.spec.tolerations
apiVersion: v1
kind: Pod
metadata:
  name: node1
  labels:
    app: node1
spec:
  containers:
  - name: nginx
    image: nginx
  tolerations:
  - key: "check"
    operator: "Equal"   //运算关系
    value: "liuchao"
    effect: "NoExecute"
    tolerationSeconds: 60  (60s之后pod会被清除)
检查
[root@master affi]# kubectl get po -o wide
NAME    READY   STATUS              RESTARTS   AGE   IP       NODE    NOMINATED NODE   READINESS GATES
node1   0/1     ContainerCreating   0          3s    <none>   node1   <none>           <none>
[root@master affi]# kubectl get po -o wide -w
NAME    READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
node1   1/1     Running   0          7s    10.244.1.118   node1   <none>           <none>
node1   1/1     Terminating   0          60s   10.244.1.118   node1   <none>           <none>
字段说明

1、其中key,value,effect要与Node上设置的taint保持一致
2、operator的值为Exists将会忽略value值
3、tolerationSeconds用于描述当pod需要被驱逐时可以在pod上继续保留运行的时间

当不指定key值时,表示容忍所有的污点key
tolerations:
- operator: "Equal"
  value: "liuchao"
  effect: "NoExecute"
  tolerationSeconds: 60
当不指定effect值时,表示容忍所有的污点作用
tolerations:
  - key: "check"
    operator: "Equal"
    value: "liuchao"
    tolerationSeconds: 60
有多个master存在时,防止资源浪费,可以加如下设置
kubectl taint nodes node名 node-role.kubernetes.io/master=:preferNoSchedule
意思是尽量不使用master资源,如果node节点资源不够时,会调度到master上

8、固定节点

指定调度节点

1、Pod.spec.nodeName将pod直接调度到指定的node节点上,会跳过Scheduler的调度策略,该撇配规则是强制匹配

示例
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 4
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
      nodeName: node1
检查
[root@master affi]# kubectl get po -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATE
nginx-75fc58ff6b-cb9k6   1/1     Running   0          28s   10.244.1.122   node1   <none>           <none>
nginx-75fc58ff6b-h5xj5   1/1     Running   0          28s   10.244.1.119   node1   <none>           <none>
nginx-75fc58ff6b-nxs7n   1/1     Running   0          28s   10.244.1.120   node1   <none>           <none>
nginx-75fc58ff6b-trn97   1/1     Running   0          28s   10.244.1.121   node1   <none>           <none>

所有的pod都在node1节点上运行
根据node的label进行选择

2、pod.spec.nodeSelector:通过kubernetes的label-selector机制选择节点,由调度器调度策略匹配label,然后调度pod到目标节点,该匹配规则属于强制约束

示例
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-web
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx-web
    spec:
      nodeSelector:
        type: nginx-web
      containers:
      - name: nginx-web
        image: nginx
        ports:
        - containerPort: 80
检查
[root@master affi]# kubectl get po
NAME                        READY   STATUS    RESTARTS   AGE
nginx-web-54df7bd47-46v7p   0/1     Pending   0          9s
nginx-web-54df7bd47-8x8m7   0/1     Pending   0          10s
pending状态
设置标签
[root@master affi]# kubectl label nodes node1 type=nginx-web
[root@master affi]# kubectl get po -o wide
NAME                        READY   STATUS    RESTARTS   AGE     IP             NODE    NOMINATED NODE   READINESS GATES
nginx-web-54df7bd47-46v7p   1/1     Running   0          7m39s   10.244.1.123   node1   <none>           <none>
nginx-web-54df7bd47-8x8m7   1/1     Running   0          7m40s   10.244.1.124   node1   <none>           <none>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。