zoukankan      html  css  js  c++  java
  • k8s学习-集群调度

    4.7、集群调度

    4.7.1、说明

    简介

    Scheduler 是 kubernetes 的调度器,主要的任务是把定义的 pod 分配到集群的节点上。听起来非常简单,但有很多要考虑的问题:

    • 公平:如何保证每个节点都能被分配资源

    • 资源高效利用:集群所有资源最大化被使用

    • 效率:调度的性能要好,能够尽快地对大批量的 pod 完成调度工作

    • 灵活:允许用户根据自己的需求控制调度的逻辑

      Sheduler 是作为单独的程序运行的,启动之后会一直持续链接API Server,获取PodSpec.NodeName为空的 pod,对每个 pod 都会创建一个 binding,表明该 pod 应该放到哪个节点上

    调度过程

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

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

    • PodFitsResources:节点上剩余的资源是否大于 pod 请求的资源

    • PodFitsHost:如果 pod 指定了 NodeName,检查节点名称是否和 NodeName 匹配

    • PodFitsHostPorts:节点上已经使用的 port 是否和 pod 申请的 port 冲突

    • PodSelectorMatches:过滤掉和 pod 指定的 label 不匹配的节点

    • NoDiskConflict:已经 mount 的 volume 和 pod 指定的 volume 不冲突,除非它们都是只读

      如果在 predicate 过程中没有合适的节点,pod 会一直在pending状态,不断重试调度,直到有节点满足条件。经过这个步骤,如果有多个节点满足条件,就继续 priorities 过程:按照优先级大小对节点排序

    优先级由一系列键值对组成,键是该优先级项的名称,值是它的权重(该项的重要性)。这些优先级选项包括:

    • LeastRequestedPriority:通过计算 CPU 和 Memory 的使用率来决定权重,使用率越低权重越高。换句话说,这个优先级指标倾向于资源使用比例更低的节点
    • BalancedResourceAllocation:节点上 CPU 和 Memory 使用率越接近,权重越高。这个应该和上面的一起使用,不应该单独使用
    • ImageLocalityPriority:倾向于已经有要使用镜像的节点,镜像总大小值越大,权重越高

    通过算法对所有的优先级项目和权重进行计算,得出最终的结果

    Node亲和性

    pod.spec.nodeAffinity

    • preferredDuringSchedulingIgnoredDuringExecution:软策略
    • requiredDuringSchedulingIgnoredDuringExecution:硬策略
    # 查看node的labels
    [root@k8s-master ~]# kubectl get node --show-labels
    NAME         STATUS   ROLES    AGE     VERSION   LABELS
    k8s-master   Ready    master   3d22h   v1.15.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master,kubernetes.io/os=linux,node-role.kubernetes.io/master=
    k8s-node1    Ready    <none>   3d22h   v1.15.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node1,kubernetes.io/os=linux
    k8s-node2    Ready    <none>   3d22h   v1.15.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node2,kubernetes.io/os=linux
    

    下面描述了一个Pod的Node亲和性设置,表示不会在k8s-node03节点上运行,可能在k8s-node01、k8s-node02节点上运行,而k8s-node01的权重(可能性)大。

    vim affinity-node.yml

    apiVersion: v1
    kind: Pod
    metadata: 
      name: pod01
      labels:
        app: pod01
    spec: 
      containers: 
      - name: nginx
        image: habor-repo.com/library/nginx:v1 
        imagePullPolicy: IfNotPresent # 镜像下载策略为:本地有的话不用重新下载
      affinity:
        nodeAffinity:
          # 该硬策略表示不在k8s-node03节点上运行(这里做实验其实不存在node03)
          requiredDuringSchedulingIgnoredDuringExecution: # 硬策略
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/hostname # node的label
                operator: NotIn # label值不在某个列表中
                values:
                - k8s-node03
          # 软策略
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 3 # 权重,因为可以有多个
            preference:
              matchExpressions:
              - key: kubernetes.io/hostname # node的label
                operator: In # label值在某个列表中
                values:
                - k8s-node01
          - weight: 1 
            preference:
              matchExpressions:
              - key: kubernetes.io/hostname
                operator: In 
                values:
                - k8s-node02
     
    
    kubectl create -f affinity-node.yml
    # 此时pod01大概率会在node01上面
    #kubectl get pod -o wide
    NAME    READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
    pod01   1/1     Running   0          19s   10.244.1.30   k8s-node1   <none>           <none>
    

    键值运算关系:

    • In:label 的值在某个列表中
    • NotIn:label 的值不在某个列表中
    • Gt:label 的值大于某个值
    • Lt:label 的值小于某个值
    • Exists:某个 label 存在
    • DoesNotExist:某个 label 不存在

    Pod亲和性

    pod.spec.affinity.podAffinity/podAntiAffinity

    • preferredDuringSchedulingIgnoredDuringExecution:软策略
    • requiredDuringSchedulingIgnoredDuringExecution:硬策略

    目前有pod01、pod02、pod03,新建一个pod04希望pod04和pod01运行在同一个node上:

    1)先创建pod01、pod02、pod03

    vim pod01.yml

    apiVersion: v1
    kind: Pod
    metadata: 
      name: pod01
      labels:
        app: pod01
    spec: 
      containers: 
      - name: nginx
        image: habor-repo.com/library/nginx:v1 
        imagePullPolicy: IfNotPresent # 镜像下载策略为:本地有的话不用重新下载
    

    vim pod02.yml

    apiVersion: v1
    kind: Pod
    metadata: 
      name: pod02
      labels:
        app: pod02
    spec: 
      containers: 
      - name: nginx
        image: habor-repo.com/library/nginx:v1 
        imagePullPolicy: IfNotPresent # 镜像下载策略为:本地有的话不用重新下载
    

    vim pod03.yml

    apiVersion: v1
    kind: Pod
    metadata: 
      name: pod03
      labels:
        app: pod03
    spec: 
      containers: 
      - name: nginx
        image: habor-repo.com/library/nginx:v1 
        imagePullPolicy: IfNotPresent # 镜像下载策略为:本地有的话不用重新下载
    
    #创建三个pod
    kubectl create -f pod01.yml
    kubectl create -f pod02.yml
    kubectl create -f pod03.yml
    #查看
    [root@k8s-master pod]# kubectl get pod -o wide
    NAME    READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
    pod01   1/1     Running   0          11s   10.244.2.164   k8s-node2   <none>           <none>
    pod02   1/1     Running   0          8s    10.244.1.31    k8s-node1   <none>           <none>
    pod03   1/1     Running   0          6s    10.244.1.32    k8s-node1   <none>           <none>
    
    

    新建一个pod04希望和pod01运行在一起

    vim pod04.yml

    apiVersion: v1
    kind: Pod
    metadata: 
      name: pod04
      labels:
        app: pod04
    spec: 
      containers: 
      - name: nginx
        image: habor-repo.com/library/nginx:v1 
        imagePullPolicy: IfNotPresent # 镜像下载策略为:本地有的话不用重新下载
      affinity:
        podAffinity: # pod亲和
          preferredDuringSchedulingIgnoredDuringExecution: # 软策略
          - weight: 3
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - pod01
              topologyKey: kubernetes.io/hostname
          - weight: 1
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - pod02
              topologyKey: kubernetes.io/hostname
        podAntiAffinity: # 反亲和
          requiredDuringSchedulingIgnoredDuringExecution: # 硬策略
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - pod02
                - pod03
            topologyKey: kubernetes.io/hostname # node节点的命名空间,不能为空      
    

    这里pod04对pod01、pod02是亲和的软策略,但是对pod02、pod03是反亲和的硬策略,最终pod04还是最运行在pod01所在的node上

    kubectl create -f pod04.yml
    # 发现 pod04 和 pod01 运行在同一个节点
    [root@k8s-master pod]# kubectl get pod -o wide
    NAME    READY   STATUS    RESTARTS   AGE     IP             NODE        NOMINATED NODE   READINESS GATES
    pod01   1/1     Running   0          27m     10.244.2.164   k8s-node2   <none>           <none>
    pod02   1/1     Running   0          27m     10.244.1.31    k8s-node1   <none>           <none>
    pod03   1/1     Running   0          27m     10.244.1.32    k8s-node1   <none>           <none>
    pod04   1/1     Running   0          3m20s   10.244.2.165   k8s-node2   <none>           <none>
    

    亲和性/反亲和性调度策略比较如下:

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

    污点&容忍度

    节点亲和性,是pod的一种属性(偏好或硬性要求),它使pod被吸引到一类特定的节点。Taint 则相反,它使节点能够排斥一类特定的 pod

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

    污点

    1)污点的组成

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

    key=value:effect
    

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

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

    2)污点的设置、查看和去除

    # 设置污点
    kubectl taint nodes node1 key1=value1:NoSchedule
    # 节点说明中,查找 Taints 字段
    kubectl describe pod pod-name  
    # 去除污点
    kubectl taint nodes node1 key1:NoSchedule
    
    # 例子:
    # 查看所有的node
    [root@k8s-master pod]# kubectl get node
    NAME         STATUS   ROLES    AGE     VERSION
    k8s-master   Ready    master   4d      v1.15.1
    k8s-node1    Ready    <none>   3d23h   v1.15.1
    k8s-node2    Ready    <none>   3d23h   v1.15.1
    # 给 node01添加tain 去除所有的该节点上的pod
    kubectl taint nodes k8s-node1 author=bart:NoExecute
    
    # 验证
    [root@k8s-master pod]# kubectl get pod -o wide
    NAME    READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
    pod01   1/1     Running   0          47m   10.244.2.164   k8s-node2   <none>           <none>
    pod04   1/1     Running   0          23m   10.244.2.165   k8s-node2   <none>           <none>
    
    # 删除(后面添加减号"-"即可)
    kubectl taint nodes k8s-node1 author=bart:NoExecute-
    
    容忍度

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

    pod.spec.tolerations

    tolerations:
    - key: key1  
      operator: Equal  
      value: value1  
      effect: NoSchedule  
      tolerationSeconds: 3600
    - key: key1
      operator: Equal 
      value: value1
      effect: NoExecute
    - key: key2
      operator: Exists
      effect: NoSchedule
    
    • 其中 key, vaule, effect 要与 Node 上设置的 taint 保持一致
    • operator 的值为 Exists 将会忽略 value 值
    • tolerationSeconds 用于描述当 Pod 需要被驱逐时可以在 Pod 上继续保留运行的时间

    1)当不指定 key 值时,表示容忍所有的污点 key:

    tolerations:
    - operator: Exists
    

    2)当不指定 effect 值时,表示容忍所有的污点作用

    tolerations:
    - key: key1
      operator: Exists
    

    3)有多个 Master 存在时,防止资源浪费,可以如下设置

    kubectl taint nodes k8s-master01 node-role.kubernetes.io/master=:PreferNoSchedule
    

    指定调度节点

    1)强制指定

    vim fix01.yml

    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: nginx-deployment
    spec:
      replicas: 3
      template:
        metadata: 
          labels:
            app: nginx
        spec:
          nodeName: k8s-node1 # 强制指定节点
          containers:
          - name: nginx
            image: habor-repo.com/library/nginx:v1
            imagePullPolicy: IfNotPresent 
            ports:
            - containerPort: 80
    
    kubectl create -f fix01.yml
    kubectl get pod -o wide
    
    # 删除
    kubectl delete deploy --all
    kubectl delete pod --all
    

    2)标签选择

    vim fix02.yml

    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: nginx-deployment
    spec:
      replicas: 3
      template:
        metadata: 
          labels:
            app: nginx
        spec:
          nodeSelector: # 标签选择所有的kv必须是"与"操作即包含了同样的
            nodeTag: bart
            nodeName: bart
          containers:
          - name: nginx
            image: habor-repo.com/library/nginx:v1
            imagePullPolicy: IfNotPresent 
            ports:
            - containerPort: 80
    
    kubectl create -f fix02.yml
    kubectl get deploy
    kubectl get pod -o wide
    
    # 查看标签
    kubectl get nodes --show-labels
    # 添加 label
    kubectl label node k8s-node1 nodeName=bart
    kubectl label node k8s-node1 nodeTag=bart
    
    kubectl label node k8s-node2 nodeName=bart
    kubectl label node k8s-node2 nodeTag=bart
    # 删除label
    kubectl label node k8s-node1 nodeName-
    kubectl label node k8s-node1 nodeTag-
    kubectl label node k8s-node2 nodeName-
    kubectl label node k8s-node2 nodeTag-
    
    # 修改replicas数量为 6
    kubectl edit deploy nginx-deployment
    
    kubectl get pod -o wide
    
    # 删除
    kubectl delete deploy --all
    kubectl delete pod --all
    
  • 相关阅读:
    Fix Installing .NET Framework 3.5 failed Error Code 0x800F0954 on Windows 10
    RHEL8安装五笔输入法
    Enable EPEL and Local Repository on RHEL8
    Why is Yum Replaced by DNF?
    检查Linux服务器是否被攻击的常用命令及方法
    IDEA 主题
    IDEA 如何显示一个类中所有的方法
    Appium 安装以及安装过程中遇到的问题
    Maven 如何发布 jar 包到 Nexus 私库
    java泛型的基本使用
  • 原文地址:https://www.cnblogs.com/bartggg/p/13021381.html
Copyright © 2011-2022 走看看