• Kubernetes Pod资源调度之全自动调度和定向调度


    1、控制器类型

    Kubernetes上,很少会直接创建一个Pod,在大多数情况下,会通过RCDeploymentDaemonSetJob等控制器完成对一组Pod副本的创建、调度和整个生命周期的自动化控制。

    在最早的Kubernetes版本里没有这么多Pod副本控制器的,只有一 个Pod副本控制器RC(Replication Controller),这个控制器是这样设计 实现的:RC独立于所控制的Pod,并通过Label标签这个松耦合关联关系 控制目标Pod实例的创建和销毁,随着Kubernetes的发展,RC也出现了新的继任者Deployment,用于更加自动地完成Pod副本的部署、版 本更新、回滚等功能。

    严谨地说,RC的继任者其实并不是Deployment,而是ReplicaSet, 因为ReplicaSet进一步增强了RC标签选择器的灵活性。之前RC的标签选择器只能选择一个标签,而ReplicaSet拥有集合式的标签选择器,可以选择多个Pod标签,如下所示

        selector:
          matchLables:
            tier: frontend
          matchExpressions:
            - {key: tier, operator: In, values: [frontend]}
    

    RC不同,ReplicaSet被设计成能控制多个不同标签的Pod副本。 一种常见的应用场景是,应用MyApp目前发布了v1v2两个版本,用户 希望MyAppPod副本数保持为3个,可以同时包含v1v2版本的Pod, 就可以用ReplicaSet来实现这种控制,写法如下

        selector:
          matchLables:
            version: v2
          matchExpressions:
            - {key: version, operator: In, values: [v1,v2]}
    

    Kubernetes的滚动升级就是巧妙运用ReplicaSet的这个特性来实现的,同时,Deployment也是通过ReplicaSet来实现Pod副本自动控制功能的。我们不应该直接使用底层的ReplicaSet来控制Pod副本,而应该 使用管理ReplicaSetDeployment对象来控制副本,这是来自官方的建议。

    2、全自动调度

    全自动调度的控制器是DeploymentRCDeploymentRC的主要功能之一就是自动部署一个容器应用的 份副本,以及持续监控副本的数量,在集群内始终维持用户指定的副本数量。

    下面是一个Deployment配置的例子,使用这个配置文件可以创建一个ReplicaSet,这个ReplicaSet会创建3Nginx应用的Pod

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
    spec:
      replicas: 3
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx
            ports:
            - containerPort: 80
    

    运行kubectl create命令创建这个Deployment

    # kubectl apply -f nginx-deployment.yaml 
    deployment.apps/nginx-deployment created
    

    查看DeploymentRSPod的状态

    # kubectl get deployment
    NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment        3/3     3            3           58s
    # kubectl get rs
    NAME                               DESIRED   CURRENT   READY   AGE
    nginx-deployment-7bffc778db        3         3         3       85s
    # kubectl get pods
    NAME                                     READY   STATUS    RESTARTS   AGE
    nginx-deployment-7bffc778db-j5czg        1/1     Running   0          1m34s
    nginx-deployment-7bffc778db-lbpjg        1/1     Running   0          1m34s
    nginx-deployment-7bffc778db-zcn6m        1/1     Running   0          1m34s
    

    从调度策略上来说,这3Nginx Pod由系统全自动完成调度。它们各自最终运行在哪个节点上,完全由MasterScheduler经过一系列算法计算得出,用户无法干预调度过程和结果。

    # kubectl get pods -o wide
    NAME                                     READY   STATUS    RESTARTS   AGE     IP             NODE         NOMINATED NODE   READINESS GATES
    nginx-deployment-7bffc778db-j5czg        1/1     Running   0          3m36s   172.20.3.229   k8s-node-1   <none>           <none>
    nginx-deployment-7bffc778db-lbpjg        1/1     Running   0          3m36s   172.20.4.27    k8s-node-2   <none>           <none>
    nginx-deployment-7bffc778db-zcn6m        1/1     Running   0          3m36s   172.20.5.203   k8s-node-3   <none>           <none>
    

    3、定向调度

    定向调度通过NodeSelector标签实现, Master上的Scheduler服务(kube-scheduler进程)负责实现Pod的调度,整个调度过程通过执行一系列复杂的算法,最终为每个Pod都计算出一个最佳的目标节点,这一过程是自动完成的,通常我们 无法知道Pod最终会被调度到哪个节点上。在实际情况下,也可能需要将Pod调度到指定的一些Node上,可以通过Node的标签(Label)和PodnodeSelector属性相匹配,来达到上述目的。

    首先通过kubectl label命令给目标Node打上一些标签

    # kubectl label nodes k8s-node-1 zone=north
    

    然后,在Pod的定义中加上nodeSelector的设置,以redismaster-controller.yaml为例

    apiVersion: v1
    kind: ReplicationController 
    metadata:
      name: redis-master
      labels:
        name: redis-master 
    spec:
      replicas: 1
      selector:
        name: redis-master
      template:
        metadata:
          labels:
            name: redis-master
        spec:
          containers:
          - name: master
            image: redis
            ports:
            - containerPort: 6379
          nodeSelector:
            zone: north
    

    创建Podscheduler就会将该Pod调度到拥有zone=north标签的Node

    如果我们给多个Node都定义了相同的标签(例如zone=north),则scheduler会根据调度算法从这组Node中挑选一个可用的Node进行Pod调度。

    通过基于Node标签的调度方式,我们可以把集群中具有不同特点的Node都贴上不同的标签,例 如role=frontendrole=backend``、role=database等标签,在部署应用时就可以根据应用的需求设置NodeSelector来进行指定Node范围的调度。

    如果我们指定了PodnodeSelector条件,且在集群中不存在包含相应标签的Node,则即使在集群中还有其他可供使用的Node,这个Pod也无法被成功调度。

    除了用户可以自行给Node添加标签,Kubernetes也会给Node预定义 一些标签,包括

    • kubernetes.io/hostname
    • beta.kubernetes.io/os(从1.14版本开始更新为稳定版,到1.18版 本删除)
    • beta.kubernetes.io/arch(从1.14版本开始更新为稳定版,到1.18 版本删除)
    • kubernetes.io/os(从1.14版本开始启用)
    • kubernetes.io/arch(从1.14版本开始启用)

    也可以使用这些系统标签进行Pod的定向调度。

    NodeSelector通过标签的方式,简单实现了限制Pod所在节点的方法。亲和性调度机制则极大扩展了Pod的调度能力,主要的增强功能如 下。

    • 更具表达力(不仅仅是“符合全部”的简单情况)
    • 可以使用软限制、优先采用等限制方式,代替之前的硬限制, 这样调度器在无法满足优先需求的情况下,会退而求其次,继续运行该Pod
    • 可以依据节点上正在运行的其他Pod的标签来进行限制,而非节点本身的标签。这样就可以定义一种规则来描述Pod之间的亲和或互斥关系

    亲和性调度功能包括节点亲和性NodeAffinityPod亲和性PodAffinity两个维度的设置。节点亲和性与NodeSelector类似,增 强了上述前两点优势;Pod的亲和与互斥限制则通过Pod标签而不是节点标签来实现,也就是上面所陈述的方式,同时具有前两点提到的优点。

    NodeSelector将会继续使用,随着节点亲和性越来越能够表达nodeSelector的功能,最终NodeSelector会被废弃。

    文章参考来源:《kubernetes权威指南-第4版》

  • 相关阅读:
    C#基础知识委托与泛型(转载)
    C.消息队列(转载)
    可编辑的 HTML JavaScript 表格控件 DataGrid
    Asp无组件上传进度条解决方案
    A lot of Javascript tips
    资料只看看,不能copy/paste。
    Converting Numbers to Strings
    浅析Google技术底蕴
    ASP.NET makes uploading files from the client to the server a snap(UploadInterface.PostedFile.SaveAs)
    IT IS an IMPORTANT String for Input TYPE=File Field enctype="multipart/formdata"
  • 原文地址:https://www.cnblogs.com/ssgeek/p/12731621.html
Copyright © 2020-2023  润新知