zoukankan      html  css  js  c++  java
  • 十三. k8s--调度器

    k8s调度器

    Scheduler调度器做为Kubernetes三大核心组件之一, 承载着整个集群资源的调度功能,其根据特定调度算法和策略,将Pod调度到最优工作节点上,从而更合理与充分的利用集群计算资源。 其作用是根据特定的调度算法和策略将Pod调度到指定的计算节点(Node)上,其做为单独的程序运行,启动之后会一直监听API Server,获取PodSpec.NodeName为空的Pod,对每个Pod都会创建一个绑定。
    默认情况下,k8s的调度器采用扩散策略,将同一集群内部的pod对象调度到不同的Node节点,以保证资源的均衡利用。
    完成调度操作的步骤:节点预选(Predicate)、节点优先级排序(Priority)、节点择优(Select)

    1. 首先用户通过 Kubernetes 客户端 Kubectl 提交创建 Pod 的 Yaml 的文件,向Kubernetes 系统发起资源请求,该资源请求被提交到
    2. Kubernetes 系统中,用户通过命令行工具 Kubectl 向 Kubernetes 集群即 APIServer 用 的方式发送“POST”请求,即创建 Pod 的请求。
    3. APIServer 接收到请求后把创建 Pod 的信息存储到 Etcd 中,从集群运行那一刻起,资源调度系统 Scheduler 就会定时去监控 APIServer
    4. 通过 APIServer 得到创建 Pod 的信息,Scheduler 采用 watch 机制,一旦 Etcd 存储 Pod 信息成功便会立即通知APIServer,
    5. APIServer会立即把Pod创建的消息通知Scheduler,Scheduler发现 Pod 的属性中 Dest Node 为空时(Dest Node=””)便会立即触发调度流程进行调度。
    6. 而这一个创建Pod对象,在调度的过程当中有3个阶段:节点预选、节点优选、节点选定,从而筛选出最佳的节点
      • 节点预选:基于一系列的预选规则对每个节点进行检查,将那些不符合条件的节点过滤,从而完成节点的预选
      • 节点优选:对预选出的节点进行优先级排序,以便选出最合适运行Pod对象的节点
      • 节点选定:从优先级排序结果中挑选出优先级最高的节点运行Pod,当这类节点多于1个时,则进行随机选择
    Predicates是强制性规则,用来形容主机匹配Pod所需要的资源,如果没有任何主机满足该Predicates, 则该Pod会被挂起,直到有主机能够满足。
    ## k8s的调用工作方式

    Kubernetes调度器作为集群的大脑,在如何提高集群的资源利用率、保证集群中服务的稳定运行中也会变得越来越重要Kubernetes的资源分为两种属性。

    1. 可压缩资源(例如CPU循环,Disk I/O带宽)都是可以被限制和被回收的,对于一个Pod来说可以降低这些资源的使用量而不去杀掉Pod。

    2. 不可压缩资源(例如内存、硬盘空间)一般来说不杀掉Pod就没法回收。未来Kubernetes会加入更多资源,如网络带宽,存储IOPS的支持。

    常用预选策略

    预选策略 作用
    CheckNodeCondition 检查是否可以在节点报告磁盘、网络不可用或未准备好时将Pod调度其上
    HostName 如果Pod对象拥有spec.hostname属性,则检查节点名称字符串是否和该属性值匹配。
    PodFitsHostPorts Pod的spec.hostPort属性时,检查端口是否被占用
    MatchNodeSelector Pod的spec.nodeSelector属性时,检查节点标签
    NoDiskConflict Pod请求的存储卷在此节点是否可用
    PodFitsResources 检查节点上的资源(CPU、内存)可用性是否满足Pod对象的运行需求。
    PodToleratesNodeTaints Pod的spec.tolerations属性,仅关注NoSchedule和NoExecute两个效用标识的污点
    PodToleratesNodeNoExecuteTaints Pod的spec.tolerations属性,是否能接纳节点的NoExecute类型污点
    CheckNodeLabelPresence 仅检查节点上指定的所有标签的存在性
    CheckServiceAffinity 将相同Service的Pod对象放置在同一个或同一类节点上以提高效率
    MaxEBSVolumeCount 检查节点已挂载的EBS存储卷数量是否超过设置的最大值,默认为39
    MaxGCEPDVolumeCount 检查节点上已挂载的GCE PD 存储卷数量是否超过最大值,默认为16
    MaxAzureDiskVolumeCount 检查节点上已挂载的Azure Disk存储卷数量是否超过最大值,默认为16
    CheckVolumeBinding 检查节点上已绑定和未绑定的PVC是否满足需求
    NoVolumeZoneConflict 在给定区域zone限制下,检查此节点部署的Pod对象是否存在存储卷冲突
    CheckNodeMemoryPressure 若给定节点已报告内存资源压力过大,检查当前Pod是否可调度至该节点
    CheckPodePIDPressure 检查节点PID资源压力
    CheckNodeDiskPressure 检查节点磁盘资源压力
    MatchInterPodAffinity 检查节点是否满足Pod对象亲和性或反亲和性条件

    常用优先函数

    函数名称 详细说明
    LeastRequestedPriority 节点的优先级就由节点空闲资源与节点总容量的比值,即由(总容量-节点上Pod的容量总和-新Pod的容量)/总容量)来决定。
    CPU和内存具有相同权重,资源空闲比越高的节点得分越高。
    cpu((capacity – sum(requested)) * 10 / capacity) + memory((capacity – sum(requested)) * 10 / capacity) / 2
    BalancedResourceAllocation CPU和内存使用率越接近的节点权重越高,该策略不能单独使用,必须和LeastRequestedPriority组合使用,尽量选择在部署Pod后各项资源更均衡的机器。
    如果请求的资源(CPU或者内存)大于节点的capacity,那么该节点永远不会被调度到。
    InterPodAffinityPriority 通过迭代 weightedPodAffinityTerm 的元素计算和,并且如果对该节点满足相应的PodAffinityTerm,则将 “weight” 加到和中,具有最高和的节点是最优选的。
    SelectorSpreadPriority 为了更好的容灾,对同属于一个service、replication controller或者replica的多个Pod副本,尽量调度到多个不同的节点上。
    如果指定了区域,调度器则会尽量把Pod分散在不同区域的不同节点上。当一个Pod的被调度时,会先查找Pod对于的service或者replication controller,
    然后查找service或replication controller中已存在的Pod,运行Pod越少的节点的得分越高。
    NodeAffinityPriority 亲和性机制。Node Selectors(调度时将pod限定在指定节点上),
    支持多种操作符(In, NotIn, Exists, DoesNotExist, Gt, Lt),而不限于对节点labels的精确匹配。
    另外支持两种类型的选择器,一种是“hard(requiredDuringSchedulingIgnoredDuringExecution)”选择器,
    它保证所选的主机必须满足所有Pod对主机的规则要求。
    这种选择器更像是之前的nodeselector,在nodeselector的基础上增加了更合适的表现语法。
    另一种是“soft(preferresDuringSchedulingIgnoredDuringExecution)”选择器,
    它作为对调度器的提示,调度器会尽量但不保证满足NodeSelector的所有要求。
    NodePreferAvoidPodsPriority(权重1W) 如果 节点的 Anotation 没有设置 key-value:scheduler. alpha.kubernetes.io/ preferAvoidPods = "...",则节点对该 policy 的得分就是10分,
    加上权重10000,那么该node对该policy的得分至少10W分。如果Node的Anotation设置了,
    scheduler.alpha.kubernetes.io/preferAvoidPods = "..." ,如果该 pod 对应的 Controller 是 ReplicationController 或 ReplicaSet,
    则该 node 对该 policy 的得分就是0分。
    TaintTolerationPriority 使用 Pod 中 tolerationList 与 节点 Taint 进行匹配,配对成功的项越多,则得分越低。
    ImageLocalityPriority 根据Node上是否存在一个pod的容器运行所需镜像大小对优先级打分,分值为0-10。遍历全部Node,
    如果某个Node上pod容器所需的镜像一个都不存在,分值为0;
    如果Node上存在Pod容器部分所需镜像,则根据这些镜像的大小来决定分值,镜像越大,分值就越高;如果Node上存在pod所需全部镜像,分值为10。
    EqualPriority 是一个优先级函数,它给予所有节点相等权重。
    MostRequestedPriority 在 ClusterAutoscalerProvider 中,替换 LeastRequestedPriority,给使用多资源的节点,更高的优先级。
    计算公式为:
    (cpu(10 sum(requested) / capacity) + memory(10 sum(requested) / capacity)) / 2

    节点亲和调度

    节点亲和性规则:硬亲和性 required 、软亲和性 preferred。

    • 硬亲和性规则不满足时,Pod会置于Pending状态,软亲和性规则不满足时,会选择一个不匹配的节点
    • 当节点标签改变而不再符合此节点亲和性规则时,不会将Pod从该节点移出,仅对新建的Pod对象生效

    节点硬亲和性

    • 方式一:Pod使用 spec.nodeSelector (基于等值关系)
    • 方式二:Pod使用 spec.affinity 支持matchExpressions属性 (复杂标签选择机制)
    # 调度至 zone = foo 的节点
    kubectl label nodes kube-node1 zone=foo
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: with-required-nodeaffinity
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:  # 定义硬亲和性
            nodeSelectorTerms:
            - matchExpressions:
              - {key: zone,operator: In,values: ["foo"]}
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
    
    可有多个nodeSelectorTerms,相互间为逻辑或关系
    同个nodeSelectorTerms下可有多个matchExpressions,各matchExpressions间为逻辑与关系
    同个matchExpressions下可有多条标签选择规则,相互间为逻辑与关系
    节点亲和性仅是节点预选策略中的一项,其他预选策略依然生效

    节点软亲和性

    • 柔性控制逻辑,当条件不满足时,能接受被编排于其他不符合条件的节点之上
    • 权重 weight 定义优先级,1-100 值越大优先级越高
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp-deploy-with-node-affinity
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: myapp
      template:
        metadata:
          name: myapp-pod
          labels:
            app: myapp
        spec:
          affinity:
            nodeAffinity:
              preferredDuringSchedulingIgnoredDuringExecution:
              - weight: 60
                preference:
                  matchExpressions:
                  - {key: zone, operator: In, values: ["foo"]}
              - weight: 30
                preference:
                  matchExpressions:
                  - {key: ssd, operator: Exists, values: []}
          containers:
          - name: myapp
            image: ikubernetes/myapp:v1
    

    Pod资源亲和调度

    • Pod对象间亲和性,将一些Pod对象组织在相近的位置(同一节点、机架、区域、地区)
    • Pod对象间反亲和性,将一些Pod在运行位置上隔开

    调度器将第一个Pod放置于任何位置,然后与其有亲和或反亲和关系的Pod据此动态完成位置编排
    # 基于MatchInterPodAffinity预选策略完成节点预选,基于InterPodAffinityPriority优选函数进行各节点的优选级评估

    位置拓扑,定义"同一位置"

    Pod硬亲和调度

    Pod亲和性描述一个Pod与具有某特征的现存Pod运行位置的依赖关系;即需要事先存在被依赖的Pod对象

    # 被依赖Pod
    kubectl run tomcat -l app=tomcat --image tomcat:alpine
    kubectl explain pod.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution.topologyKey
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: with-pod-affinity
    spec:
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:  # 硬亲和调度
          - labelSelector:
              matchExpressions:
              - {key: app, operator: In, values: ["tomcat"]}  # 选择被依赖Pod
            topologyKey: kubernetes.io/hostname  # 根据挑选出的Pod所有节点的hostname作为同一位置的判定
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
    
    调度器先基于标签选择器查询拥有匹配标签的所有被依赖Pod,再获取它们所属节点的topologyKey指示的属性的标签值,再查询所有拥有匹配这些标签值的所有节点,从而完成节点预选,再根据优选函数计算节点优先级,挑选出运行新建Pod的节点
    若节点标签在运行时发生更改,不再满足Pod亲和性规则时,该Pod会继续运行;即仅对亲建的Pod生效
    ### Pod软亲和调度
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp-with-preferred-pod-affinity
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: myapp
      template:
        metadata:
          name: myapp
          labels:
            app: myapp
        spec:
          affinity:
            podAffinity:
              preferredDuringSchedulingIgnoredDuringExecution:
              - weight: 80
                podAffinityTerm:
                  labelSelector:
                    matchExpressions:
                    - {key: app, operator: In, values: ["cache"]}
                  topologyKey: zone
              - weight: 20
                podAffinityTerm:
                  labelSelector:
                    matchExpressions:
                    - {key: app, operator: In, values: ["db"]}
                  topologyKey: zone
          containers:
          - name: myapp
            image: ikubernetes/myapp:v1
    

    Pod反亲和调度

    Pod反亲和调度用于分散同一类应用,调度至不同的区域、机架或节点等
    spec.affinity.podAffinity替换为 spec.affinity.podAntiAffinity

    反亲和调度也分为柔性约束和强制约束

    apiVersion: v1
    kind: Pod
    metadata:
        name: pod-first
        labels: 
            app: myapp
            tier: fronted
    spec:
        containers:
        - name: myapp
          image: ikubernetes/myapp:v1
    ---
    apiVersion: v1
    kind: Pod
    metadata:
        name: pod-second
        labels:
            app: backend
            tier: db
    spec:
        containers:
        - name: busybox
          image: busybox:latest
          imagePullPolicy: IfNotPresent
          command: ["/bin/sh", "-c", "sleep 3600"]
        affinity:
          podAntiAffinity:
            requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                - {key: app, operator: In, values: ["myapp"]}
              topologyKey: zone
    

    污点和容忍度

    污点 taints 是定义在节点上的键值型属性数据,用于让节点拒绝将Pod调度运行于其上,除非Pod有接纳节点污点的容忍度容忍度 tolerations 是定义在Pod上的键值属性数据,用于配置可容忍的污点,且调度器将Pod调度至其能容忍该节点污点的节点上或没有污点的节点上

    使用PodToleratesNodeTaints预选策略和TaintTolerationPriority优选函数完成该机制

    • 节点亲和性使得Pod对象被吸引到一类特定的节点 (nodeSelector和affinity)
    • 污点提供让节点排斥特定Pod对象的能力

    定义污点和容忍度

    污点定义于nodes.spec.taints 容忍度定义于pods.spec.tolerations
    语法: key=value:effect

    effect定义排斥等级:

    • NoSchedule,不能容忍,节点现存Pod不受影响
    • PreferNoSchedule,柔性约束,节点现存Pod不受影响
    • NoExecute,不能容忍,当污点变动时,Pod对象会被驱逐

    在Pod上定义容忍度时:

    1. 等值比较 容忍度与污点在key、value、effect三者完全匹配
    2. 存在性判断 key、effect完全匹配,value使用空值

    一个节点可配置多个污点,一个Pod也可有多个容忍度

    管理节点的污点

    同一个键值数据,effect不同,也属于不同的污点

    添加污点:

    kubectl taint node <node-name> <key>=<value>:<effect>
    

    查看污点:

    kubectl get nodes <nodename> -o go-template={{.spec.taints}}
    

    删除污点:

    kubectl taint node <node-name> <key>[:<effect>]-
    kubectl patch nodes <node-name> -p '{"spec":{"taints":[]}}'
    
    kubectl taint node kube-node1 node-type=production:NoSchedule
    kubectl get nodes kube-node1 -o go-template={{.spec.taints}}
    
    # 删除key为node-type,effect为NoSchedule的污点
    kubectl taint node kube-node1 node-type:NoSchedule-
    
    # 删除key为node-type的所有污点
    kubectl taint node kube-node1 node-type-
    
    # 删除所有污点
    kubectl patch nodes kube-node1 -p '{"spec":{"taints":[]}}'
    

    Pod对象容忍度

    spec.tolerations字段添加
    tolerationSeconds用于定义延迟驱逐Pod的时长

    # 等值判断
    tolerations:
    - key: "key1"
      operator: "Equal"
      value: "value1"
      effect: "NoExecute"
      tolerationSeconds: 3600
     
    # 存在性判断
    tolerations:
    - key: "key1"
      operator: "Exists"
      effect: "NoExecute"
      tolerationSeconds: 3600
    
    上面两个例子表示如果某个Node存在key1=value1的污点或者存在key1的污点,Pod将不会调度到这样的节点。
    apiVersion: v1
    kind: Deployment
    metadata:
        name: myapp-deploy
        namespace: default
    spec:
        replicas: 3
        selector:
            matchLabels:
                app: myapp
                release: canary
        template:
            metadata:
                labels:
                    app: myapp
                    release: canary
            spec:
                containers:
                - name: myapp
                image: ikubernetes/myapp:v1
                ports:
                - name: http
                  containerPort: 80
                tolerations:
                - key: "node-type"
                  operator: "Equal"
                  value: "production":
                  effect: "NoExecute"
                  tolerationSeconds: 3600
    
    
    

    问题节点标识

    自动为节点添加污点信息,使用NoExecute效用标识,会驱逐现有Pod
    K8s核心组件通常都容忍此类污点

    node.kubernetes.io/not-ready 节点进入NotReady状态时自动添加
    node.alpha.kubernetes.io/unreachable 节点进入NotReachable状态时自动添加
    node.kubernetes.io/out-of-disk 节点进入OutOfDisk状态时自动添加
    node.kubernetes.io/memory-pressure 节点内存资源面临压力
    node.kubernetes.io/disk-pressure 节点磁盘面临压力
    node.kubernetes.io/network-unavailable 节点网络不可用
    node.cloudprovider.kubernetes.io/uninitialized kubelet由外部云环境程序启动时,自动添加,待到去控制器初始化此节点时再将其删除

    Pod优选级和抢占式调度

    优选级,Pod对象的重要程度
    优选级会影响节点上Pod的调度顺序和驱逐次序
    一个Pod对象无法被调度时,调度器会尝试抢占(驱逐)较低优先级的Pod对象,以便可以调度当前Pod

    Pod优选级和抢占机制默认处于禁用状态
    启用:同时为kube-apiserver、kube-scheduler、kubelet程序的 --feature-gates 添加 PodPriority=true
    使用:
    事先创建优先级类别,并在创建Pod资源时通过 priorityClassName属性指定所属的优选级类别

    参考链接

    https://pdf.us/2019/04/08/3222.html

    https://www.cnblogs.com/centos-python/articles/10884738.html

  • 相关阅读:
    第二阶段冲刺第一天
    第一次团队绩效评估
    其他团队对本团队评价的总结
    对其他团队的评价
    团队博客的检查结果
    站立会议第十天
    站立会议第九天
    站立会议第八天
    站立会议第七天
    团队站立会议10
  • 原文地址:https://www.cnblogs.com/peitianwang/p/11579793.html
Copyright © 2011-2022 走看看