暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

k8s 调度

程序猿Damon 2020-08-25
213





k8s 调度

1、 k8s 架构



k8s的架构如图:

我们都知道k8s分为master、node,其中:

master 主要有如下几个组件:

  • Kubernetes Controller Manager(kube-controller-manager):Kubernetes资源对象的”大总管”,是所有资源对象的自动化控制中心,比如Deployment中的pod副本数

  • Kubernetes API Server (kube-apiserver):Kubernetes的“心脏”,是集群控制的入口进程,也是所有资源增、删、查、改等操作的唯一入口

  • Kubernetes Scheduler(kube-scheduler):Kubernetes的”调度室“,负责资源调度(Pod调度)

  • etcd:是用于共享配置和服务发现的分布式,一致性的KV存储系统,被用作Kubernetes集群后端数据的持久化存储


  node 主要包含以下组件:

  • kubelet:负责Pod对应容器的创建、启停和销毁等任务

  • kube-proxy:与Kubernetes Service通信与负载均衡机制

  • Container Runtime:Docker Engine,负责本机容器的创建、启停与销毁等工作



2、k8s 调度


2.1  Pod 调度


这个过程看起来似乎比较简单,但实际生产环境的调度过程中,有很多问题需要考虑:

  • 首先,如何保证全部计算节点调度的公平性?如何保证每个节点都能被分配资源?

  • 其次,计算资源如何能够被高效利用?集群所有计算资源如何才能被最大化的使用?


  • 再次,如何保证Pod调度的性能和效率?如何能够快速的对大批量的Pod完成调度到较优的计算节点之上?


  • 最后,用户最了解自己的业务,用户是否可以根据实际需求定制自己的调度逻辑和策略?


2.2  Pod 调度过程

调度过程分为2个阶段:

  • 第一阶段:预选过程,过滤节点,调度器用一组规则过滤掉不符合要求的主机。比如Pod指定了所需要的资源量,那么可用资源比Pod需要的资源量少的主机会被过滤掉。

  • 第二阶段:优选过程,节点优先级打分,对第一步筛选出的符合要求的主机进行打分,在主机打分阶段,调度器会考虑一些整体优化策略,比如把容一个Replication Controller的副本分布到不同的主机上,使用最低负载的主机等。





代码位置(1.10 ):

    https://github.com/kubernetes/kubernetes/tree/release-1.10/pkg/scheduler/algorithm



    优选(Priorities)


    经过预选策略(Predicates)对节点过滤,获取节点列表,再对符合需求节点列表进行打分,最终选择Pod调度到一个分值最高节点。


    最终主机的得分用以下公式计算得出:

      finalScoreNode = (weight1 * priorityFunc1) + (weight2 * priorityFunc2) + … + (weightn * priorityFuncn)





      2.3  Node 定义

      查看一个node的资源信息:

        apiVersion: v1
        kind: Node
        metadata:
        labels:
        beta.kubernetes.io/arch: amd64
        beta.kubernetes.io/os: linux
        kubernetes.io/hostname: node-n1
        name: node-n1
        spec:
        externalID: node-n1
        status:
        addresses:
        - address: 10.162.197.135
        type: InternalIP
        allocatable:
        cpu: "8"
        memory: 16309412Ki
        pods: "110"
        capacity:
        cpu: "8"
        memory: 16411812Ki
        pods: "110"
        conditions: {...}
        daemonEndpoints:
        kubeletEndpoint:
        Port: 10250
        images: {...}
        nodeInfo: {...}



        2.4  Pod 定义

        查看一个pod的资源信息:

          kubectl explain pod.spec



          我们看这个pod:


          • requests:申请范围是0到node节点的最大配置


          • limits:申请范围是requests到无限大,即0 <= requests <=Node Allocatable, requests <= limits <= Infinity。

            说明:resoureces.limits影响pod的运行资源上限,不影响调度。



          注释:


          • 红色部分表示资源分配


          • 浅蓝色表示采用的调度器


          • 灰色表示普通调度策略


          • 荧光色表示高级调度策略



          2.5  k8s 调度器资源分配机制

          1. 基于Pod 中容器 request 资源“总和”调度

            a. resoureces.limits 影响 pod 的运行资源上限,不影响调度

            b. initContainer 取最大值,container 取累加值,最后两者中取大,即 Max( Max(initContainers.requests), Sum(containers.requests) )

            c. 未指定request资源时(QoS Guaranteed除外), 按资源需求为0进行调度

          2. 基于资源声明量的调度,即:request 字段值,而非实际占用

            i. 不依赖监控,系统不会过于敏感

            ii. 能否调度成功:pod.request < node.allocatable - node.requested

          3. Kubernetes node 资源的盒子模型




          4. 资源分配相关算法

            A. GeneralPredicates(主要是PodFitsResources)

            B. LeastRequestedPriority

            C. BalancedResourceAllocation,平衡cpu/mem的消耗比例



          3、k8s 调度策略


          3.1  普通调度策略


          nodeSelector【将来会被废弃】:将 Pod 调度到特定的 Node 上:

            apiVersion: v1
            kind: Pod
            metadata:
            labels:
            pod-template-hash: "4173307778"
            run: my-pod
            name: my-pod
            namespace: default
            spec:
            containers:
            - image: nginx
            imagePullPolicy: Always
            name: my-pod
            ports:
            - containerPort: 80
            protocol: TCP
            resources: {}
            nodeSelector:
            disktype: ssd
                node-flavor: s3.large.2


            • 匹配node.labels

            • 排除不包含nodeSelector中指定label的所有node

            • 匹配机制 :完全匹配



            3.2  高级调度策略


            1. podAffinity:让某些 Pod 分布在同一组 Node 上:

              apiVersion: v1
              kind: Pod
              metadata:
              name: with-pod-affinity
              spec:
              affinity:
              podAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
              - labelSelector:
              matchExpressions:
              - key: security
              operator: In
              values:
              - S1
              topologyKey: kubernetes.io/zone
              preferredDuringSchedulingIgnoredDuringExecution:
              - weight: 100
              podAffinityTerm:
              labelSelector:
              matchExpressions:
              - key: security
              operator: In
              values:
              - S2
              topologyKey: kubernetes.io/hostname
              containers:
              - name: with-pod-affinity
                  image: k8s.gcr.io/pause:2.0


              与nodeAffinity的关键差异:


              • 定义在PodSpec中,亲和与反亲和规则具有对称性


              • labelSelector的匹配对象为Pod



              • 对node分组,依据label-key = topologyKey,每个label-value取值为一组


              • 硬性过滤规则,条件间只有逻辑与运算



              硬性过滤:排除不具备指定pod的node组

                requiredDuringSchedulingIgnoredDuringExecution:
                - labelSelector:
                matchExpressions:
                - key: security
                operator: In
                values:
                - S1
                topologyKey: kubernetes.io/zone



                软性:不具备指定pod的node组打低分,降低该组node被选中的几率

                  - weight: 100
                  podAffinityTerm:
                  labelSelector:
                  matchExpressions:
                  - key: security
                  operator: In
                  values:
                  - S2
                  topologyKey: kubernetes.io/hostname



                  2. podAntiAffinity:避免某些 Pod 分布在同一组 Node 上:

                    apiVersion: v1
                    kind: Pod
                    metadata:
                    name: with-pod-affinity
                    spec:
                    affinity:
                    podAntiAffinity:
                    requiredDuringSchedulingIgnoredDuringExecution:
                    - labelSelector:
                    matchExpressions:
                    - key: security
                    operator: In
                    values:
                    - S1
                    topologyKey: kubernetes.io/zone
                    preferredDuringSchedulingIgnoredDuringExecution:
                    - weight: 100
                    podAffinityTerm:
                    labelSelector:
                    matchExpressions:
                    - key: security
                    operator: In
                    values:
                    - S2
                    topologyKey: kubernetes.io/hostname
                    containers:
                    - name: with-pod-affinity
                    image: k8s.gcr.io/pause:2.0


                    与podAffinity的差异:


                    • 匹配过程相同

                    • 最终处理调度结果时取反,podAffinity中可调度节点,在podAntiAffinity中为不可调度,podAffinity中高分节点,在podAntiAffinity中为低分



                    3. Taints:避免 Pod 调度到特定 Node 上:

                      apiVersion: v1
                      kind: Node
                      metadata:
                      labels:
                      beta.kubernetes.io/arch: amd64
                      beta.kubernetes.io/os: linux
                      kubernetes.io/hostname: node-n1
                      name: node-n1
                      spec:
                      externalID: node-n1
                      taints:
                      - effect: NoSchedule
                      key: accelerator
                      timeAdded: null
                          value: gpu


                      • 带effect的特殊label,对Pod有排斥性

                        1. 硬性排斥 NoSchedule(如果一个pod没有声明容忍这个Taint,则系统不会把该Pod调度到有这个Taint的node上)

                        2. 软性排斥 PreferNoSchedule(如果一个Pod没有声明容忍这个Taint,则系统会尽量避免把这个pod调度到这一节点上去,但不是强制的)


                      • 系统创建的taint附带时间戳

                        1. effect为NoExecute

                        2. 便于触发对Pod的超时驱逐


                      • 典型用法:预留特殊节点做特殊用途



                        kubectl taint node node-n1 foo=bar:NoSchedule


                        kubectl taint node node-n1 foo:NoSchedule-



                        4. Tolerations:允许 Pod 调度到有特定 taints 的 Node 上:

                          apiVersion: v1
                          kind: Pod
                          metadata:
                          labels:
                          run: my-pod
                          name: my-pod
                          namespace: default
                          spec:
                          containers:
                          - name: my-pod
                          image: nginx
                          tolerations:
                          - key: accelerator
                          operator: Equal
                          value: gpu
                          effect: NoSchedule



                          可以无视排斥:

                            apiVersion: v1
                            kind: Node
                            metadata:
                            labels:
                            beta.kubernetes.io/arch: amd64
                            beta.kubernetes.io/os: linux
                            kubernetes.io/hostname: node-n1
                            name: node-n1
                            spec:
                            externalID: node-n1
                            taints:
                            - effect: NoSchedule
                            key: accelerator
                            timeAdded: null
                                value: gpu


                            • 完全匹配

                              例:<key>=<value>:<effect>


                            • 匹配任意taint value

                              Operator为Exists,value为空

                              例:<key>:<effect>



                            • 匹配任意 taint effect

                              effect为空

                              例:<key>=<value>



                            3.3  无调度器调度 pod


                            1. nodeName:将Pod手动调度到特定的 Node 上:




                            2. DaemonSet:

                              apiVersion: apps/v1
                              kind: DaemonSet
                              metadata:
                              name: my-daemonset
                              spec:
                              selector:
                              matchLabels:
                              name: my-daemonset
                              template:
                              metadata:
                              labels:
                              name: my-daemonset
                              spec:
                              containers:
                              - name: container
                                      image: k8s.gcr.io/pause:2.0


                              等同于:

                                apiVersion: apps/v1
                                kind: Deployment
                                metadata:
                                name: my-deploy
                                spec:
                                replicas: <# of nodes>
                                selector:
                                matchLabels:
                                podlabel: daemonset
                                teplate:
                                metadata:
                                labels:
                                podlabel: daemonset
                                spec:
                                affinity:
                                podAntiAffinity:
                                requiredDuringSchedulingIgnoredDuringExecution:
                                - labelSelector:
                                matchExpressions:
                                - key: podlabel
                                operator: In
                                values:
                                - daemonset
                                topologyKey: kubernetes.io/hostname
                                containers:
                                - name: container
                                        image: k8s.gcr.io/pause:2.0



                                3.4  度结果和失败原因分析


                                查看调度结果:

                                  kubectl get po podname –o wide


                                  查看调度失败原因:

                                    kubectl describe po podname


                                    调度错误列表:




                                    3.5  自定义调度






                                    例子:

                                      https://kubernetes.io/blog/2017/03/advanced-scheduling-in-kubernetes/



                                      前面讲的调度是指资源节点的调度,优先级也是指节点的优先级。高优先级的Pod会优先被调度,或者在资源不足低情况牺牲低优先级的Pod,以便于重要的Pod能够得到资源部署。



                                      为了定义Pod优先级,需要先定义PriorityClass对象,该对象没有Namespace限制,官网示例:



                                      然后通过在Pod的spec. priorityClassName中指定已定义的PriorityClass名称即可:




                                      • 当节点没有足够的资源供调度器调度Pod、导致Pod处于pending时,抢占(preemption)逻辑会被触发。


                                      • Preemption会尝试从一个节点删除低优先级的Pod,从而释放资源使高优先级的Pod得到节点资源进行部署。




                                      欢迎大家关注个站哟:damon8.cn


                                      最后介绍新公号:天山六路折梅手,欢迎关注。

                                      往期回顾

                                      微服务自动化部署CI/CD

                                      如何利用k8s拉取私有仓库镜像

                                      个站建设基础教程

                                      ArrayList、LinkedList&nbsp;你真的了解吗?

                                      大佬整理的mysql规范,分享给大家

                                      如果张东升是个程序员

                                      微服务架构设计之解耦合

                                      浅谈负载均衡

                                      Oauth2的认证实战-HA篇

                                      Oauth2的授权码模式《上》

                                      浅谈开发与研发之差异

                                      浅谈&nbsp;Java&nbsp;集合&nbsp;|&nbsp;底层源码解析

                                      基于 Sentinel 作熔断 | 文末赠资料

                                      基础设施服务k8s快速部署之HA篇

                                      今天被问微服务,这几点,让面试官刮目相看

                                      Spring cloud 之多种方式限流(实战)

                                      Spring cloud 之熔断机制(实战)

                                      面试被问finally 和 return,到底谁先执行?

                                      Springcloud Oauth2 HA篇

                                      Spring Cloud Kubernetes之实战一配置管理

                                      Spring Cloud Kubernetes之实战二服务注册与发现

                                      Spring Cloud Kubernetes之实战三网关Gateway



                                      关注公众号,回复入群,获取更多惊喜!公众号(程序猿Damon)里回复 ES、Flink、Java、Kafka、MQ、ML、监控、大数据、k8s 等关键字可以查看更多关键字对应的文章。




                                      如有收获,点个在看,谢谢

                                      文章转载自程序猿Damon,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                      评论