聊聊Kubernetes计算资源模型(上)——资源抽象、计量与调度

栏目: 编程工具 · 发布时间: 6年前

内容简介:聊聊Kubernetes计算资源模型(上)——资源抽象、计量与调度

导读:

是时候来缕一缕Kubernetes的资源模型了,它对我们在生产环境中运维Kubernetes至关重要。我们将这个话题分为三个部分,第一部分整体介绍Kubernetes的资源抽象,以及他们的计量方式,初步介绍资源调度;第二部分介绍Pod级别的QoS、实现细节以及资源超卖;第三部分将具体介绍Kubernetes的资源调度和整个调度体系。

1

预热

Kubernetes的资源模型的理解对Kubernetes的使用者至关重要,它不仅关系到基础设施和资源的使用率优化,还关系到生产环境中Kubernetes集群的稳定性。

在介绍资源模型之前,我们先来简单介绍一下Kubernetes的几个主要概念:

  • Node:计算节点,用来提供计算资源实体,可以理解为物理机、云主机、虚拟机等。

  • Pod:Kubernetes调度容器的基本单位,Pod中包含一个或者多个容器,每个Pod最终会被调度到Node上,消费Node上提供的计算资源。

  • Scheduler:Kubernetes将用户创建Pod的请求提交给Scheduler调度器,Scheduler决定Pod最终被调度到哪个Node上。

如下图所示,Pod经过Scheduler调度,绑定到某个Node上,消费该Node提供的计算资源:

聊聊Kubernetes计算资源模型(上)——资源抽象、计量与调度

2

资源分类、抽象与表示

A

什么是资源

对于一个Kubernetes Node(物理机、虚拟机、云主机)所提供的资源,可分为三大类:计算资源(CPU/内存/GPU)、网络资源(IP地址/带宽),存储资源(磁盘/SSD)。

显然这个粒度的分类对我们使用资源没有帮助,我们需要更加细分和量化这些资源,才能在系统中更好的进行资源分配和调度。

B

资源分类

在计算机体系中,可以被称为"资源"的可以列举很多:

  • CPU

  • 内存

  • GPU

  • 磁盘空间(Disk space)

  • 磁盘时间(Disk time)

  • 网络带宽

  • 端口号

  • 高速缓存

  • IP地址

  • PIDs

  • ...

这些资源从另外的角度又可分为两类:可压缩资源和不可压缩资源:

可压缩资源

可压缩资源有如下特性:

  • 资源本身无状态

  • 申请资源非常快

  • 回收资源几乎不会失败

CPU、GPU属于可压缩的资源,磁盘时间(Disk time)也属于可压缩资源。

可压缩资源

不可压缩资源有如下特性:

  • 资源本身持有状态

  • 申请资源相对比较慢

  • 回收资源时可能失败

内存、磁盘空间(Disk space)属于不可压缩资源。

C

资源抽象

不透明整数资源

Kubernetes使用"不透明的整数资源"( Opaque Integer Resources )方式来量化和使用计算资源。

对于上面提到的CPU、GPU、Memory、Disk time...等,Kubernetes将他们抽象成整数,而不用关心它的具体细节。

Kubernetes将CPU每个CPU核的计算能力抽象为整数1或者1000m,如果一个Pod申请了CPU为0.5或者500m,这就代表它申请了0.5CPU核。

关于" Opaque Integer Resources "资源的讨论: stackoverflow/the-opaque-integer-resources

资源的表示

对于用户和Kubernetes组件(Scheduler, Auto-Scaler, Auto-Sizer, Load Balancers)都需要知道Pod的资源需求,Node资源能力和资源的使用率。

Kubernetes将Pod的资源需求和Node资源能力通过设定它们的Spec字段实现,资源的使用率通过设置Status字段来实现。

下面的例子说明了如何定义一个Pod的资源需求:

resourceRequirementSpec: [
  request:   [ cpu: 2.5, memory: "40Mi" ],
  limit:     [ cpu: 4.0, memory: "99Mi" ],
]

其中:

  • request: request字段是可选的,代表Pod请求资源的数量,或者已请求和已分配的资源数量。Scheduler的调度算法已经request字段的来度量一个Pod是否适合 一个Node(Node上足够提供request的资源)。如果一个容器或者Pod尝试使用比request更多的资源,该服务的SLO将得不到保障,在资源短缺的情况下,这种请求会失败。 如果Request没有设置,那么它默认是limit的值。如果Pod没有设置,那么,request是pod中所有container请求资源的总和。

  • limit: limit字段也是可选的,它代表着容器或者Pod的最大资源使用上限,如果容器或者Pod使用的资源超出这个上限,它会被终止。如果不设置limit,那么意味着Pod 可以无上限使用资源,这种方式非常危险,在实际生产运维过程中,这种不设置limit会导致不确定的行为,特别是对于内存来说,在生产环境中使用Kubernetes的团队一定要重视这个问题。

通过设定request和limit可是实现Kubernetes不同级别的QoS和资源超卖,我们会在后面的文章中详细讨论。

下面的例子说明Node上总体资源能力的定义:

resourceCapacitySpec: [
  total:     [ cpu: 12,  memory: "128Gi" ]
]

其中:

  • total: Node上所有可申请的资源总量。

C

Kubernetes保留的资源定义类型

从上面的例子中可以看出,"cpu", "memory"用来作为CPU资源和内存资源的标识,这两个是被Kubernetes保留的字段,用户定义的定义的第三方资源 不能使用这两个字段。Kubernetes对CPU和Memory两种资源进行了详细的描述:

CPU

  • 名称:cpu或者kubernetes.io/cpu

  • 单位:Kubernetes Compute Unit(KCU) Seconds/second(CPU核数记为"Kubernetes CPU")

  • 内部表示: milli-KCUs

  • 是否为可压缩资源:是

Kubernetes未来会支持两个特性用于细化CPU的使用:

  • [future] schedulingLatency: 在 lmctfy (Google开源的虚拟化技术)中设置调度延迟

  • [future] cpuConversionFactor: 作为Node的属性,用于区分不同Node上的CPU性能,用浮点数表示,默认为1.0

需要注意的是,如果CPU请求需要2个KCU,Kubernetes 不保证 真正申请到2个物理的CPU核心(保证相当于两个物理CPU核心的时间片),这方面的控制会在以后的feature中支持。

Memory

  • 名称:memory或者kubernetes.io/memory

  • 单位:bytes

  • 是否为可压缩资源:否

内存的单位支持EB,PB,TB,GB,MB,KB,m的标识方式,也支持2的幂次的标识方式:EiB,PiB,TiB,GiB,MiB,KiB,Kubernetes支持这两种方式是为了照顾用户的使用习惯,两种方式并没有好坏之分。

D

资源的量化

Kubernetes将计算资源抽象以"整数"的方式进行量化,让计算资源更好的管理。

对于内存,Kubernetes将其记为1000Mi或者1024M等,如果Pod是想申请512MB的内存,就在Pod中标记内存申请512M。

下面的例子说明了一个Pod如何申请1个CPU核和2G内存:

{  
    "kind": "Pod",  
    "apiVersion": "v1"
    "metadata": {
        "name": "kafka-1",
        "labels": {
            "component": "kafka",
            "role": "kafka-1"
        }
    },  
    "spec": {
        "restartPolicy": "Always",    
        "containers": [
            {
                "name": "kafka"                
                "image": "registry.docker:5000/kafka:2.11-0.9.0",
                "resources": {
                    "limits": {
                        "cpu": "1",           -- 申请1个CPU核
                        "memory": "20480M"    -- 申请2G内存
                }
             },
        "ports": [
          {
                "containerPort": 9092
          }
        ]
      }
    ]
  }
}

Kubernetes将每个Node的计算资源抽象为"Capacity",它代表着这个Node提供CPU/Memory等计算资源的总体能力, Kubelet内置的cAdvisor组件会探测所在节点的计算能力(CPU核数和内存数)。Capacity也是通过整数的形式来描述:

{    
    "kind": "Node",    
    "apiVersion": "v1",    
    "metadata": {        
        "name": "172.21.1.11",
        "labels": {
            "kubernetes.io/hostname": "172.21.1.11"
        }
    },    
    "spec": {
        "externalID": "172.21.1.11"
    },    
    "status": { 
        "capacity": {            
            "cpu": "40",             --- 共40个CPU核心
            "memory": "98760652Ki",  --- 共98G内存
        }
    }
        }

E

其它资源类型

目前Kubernetes支持对CPU/Memory/GPU三种资源的使用,Kubernetes计划将来支持更多的资源类型,比如

[future]网络带宽

  • 名称:network-bandwidth或者kubernetes.io/network-bandwidth

  • 单位:bytes per second(每秒字节数)

  • 是否为可压缩资源:是

[future]存储空间

  • 名称:storage-space或者kubernetes.io/storage-space

  • 单位:bytes

  • 是否为可压缩资源: 否

[future]存储时间

  • 名称:storage-time或者kubernetes.io/storage-time

  • 单位:seconds per second of disk time(每次硬盘时间的秒数)

  • 内部表示:milli-units

  • 是否为可压缩资源:是

[future]存储操作

  • 名称:storage-iops或者kubernetes.io/storage-iops

  • 单位:operations per second

  • 是否为可压缩资源:是

3

Node维度的计算资源

A

Node上资源划分划分

Node上除了运行Kubernetes创建的容器,还要运行操作系统和一些默认的守护进程,例如Docker daemon和Kubelet daemon等,"Capacity"不能代表 Kubernetes可以使用计算资源的全部,这就引入了一个新的问题,Kubernetes如何划分Node上的计算资源分配。

如下图所示,Kubernetes将Node上的计算资源分为三大块:

聊聊Kubernetes计算资源模型(上)——资源抽象、计量与调度

其中:

  • System-Reserved : 系统保留的计算资源,不能被Kubernetes调度和使用,它负责/system下所有进程的资源请求。

  • Kube-Reserved : Kubernetes为docker,kubelet,kube-proxy等保留的计算资源,这部分保证Kubernetes正常工作。

  • Kubelet Allocatable : 能够被Kubernetes调度和使用的计算资源,它的计算方法为:

[Allocatable] = [Node Capacity] - [Kube-Reserved] - [System-Reserved]

Scheduler将使用Allocatable替代Capacity作为调度的依据,kubelet也会根据Allocatable进行接纳检查。

用户可以设置Kube-Reserved使用的计算资源,在kubelet的启动选项中指定:

--kube-reserved=cpu=500m,memory=500Mi

目前,Kube-Reserved只支持CPU和Memory两种资源,未来会支持更多的资源类型,比如硬盘。如果Kube-Reserved没有设置,那么它 默认是0,System-Reserved如果不设置,也默认为零,这中情况下 Allocatable == Capacity ,Scheduler会按照Capacity进行调度。

Kube-Reserved的设定不仅仅是为了保证kubelet等组件正常运行,还有限定kubelet使用资源的用意。在某些情况下,用户会使用第三方的资源调度组件, 比如Mesos,hadoop...等,它们会划分自己的资源范围,这样kubelet和第三方组件可以互不干扰的运行。

System-Reserved默认是Kube-Reserved的值一致,如果Kube-Reserved没有设置,它们默认都为0.

在某些场景下,Kubernetes会出现自相矛盾的状况:Scheduler经过调度算法筛选,将Pod与某个Node绑定,该Node上Kubelet发现自身的资源不能满足Pod的需求,会拒绝运行这个Pod, Scheduler和Kubelet会出现循环依赖的问题,造成Pod永远调度不成功。

Kubernetes(1.3以后)使用"两阶段"的调度策略解决这个问题, 它调度过程分为两个阶段,第一阶段是Schedule经过筛选,选出一些符合的Node,Node根据自身的Capacity对Pod资源请求进行检查,如果满足需求则第一阶段完成,如果不能满足, 会告诉Scheduler将Pod调度到其他Node;第二阶段,Kubelet会根据Node上的Allocatable再次检查是否能够满足Pod的资源请求,如果满足,Scheduler与Kubelet达成共识, Pod会被调度在该Node上,否则,Scheduler会跟其他的Node重复这个过程,直到Pod被成功调度。

B

资源调度与碎片

Node节点经过一段时间的运行,从整体上看计算资源会分成四个区域,如下图所示:

聊聊Kubernetes计算资源模型(上)——资源抽象、计量与调度

A区域用于Scheduler调度新的Pod,但是A区域是不连续空间,整个节点上会形成很多碎片,就像下图所示:

聊聊Kubernetes计算资源模型(上)——资源抽象、计量与调度

这时,Node A和Node B不能被Schedule调度资源请求比较大Pod,如果集群中所有的节点都产生碎片后,那么资源请求量大的Pod永远会处于Pending状态, 应用发布过程会失败。

我们来假设一个场景: 所有Pod的request总量有小于所有Node提供的Capacity总量的时候,说明计算资源充足,但是,这是集群中出现了大量"Pending"的Pod,我们将如何处置?

显而易见的方式就是对Node上的计算资源进行重排,理想的情况,经过重排Node A和Node B的资源使用如下图-5所示:

聊聊Kubernetes计算资源模型(上)——资源抽象、计量与调度

C

碎片整理与重新平衡

Kubernetes集群运行一段时间后,每个Node上产生碎片是必然的,这个问题很难只通过优化Scheduler的调度算法来解决,当然,优化Scheduler算法是必须要做的, 从解决碎片的角度,在合适的时间,对计算做Rebalance,或者在一些Node宕机、升级、重启时发起一定范围的Rescheduler是个明智的选择。

聊聊Kubernetes计算资源模型(上)——资源抽象、计量与调度

在单一的Kubernetes集群上存在碎片的问题,多Kubernetes集群或者Kubernetes联邦也存在这个问题,什么最优的调度策略,合适触发rebalance和reschedule,目前还有 理论的指导,再加上每个公司的业务特点,很难找到"最优"的解决方案。

实际生产环境中,基础设施的高可用和保证业务稳定运行比提高资源利用率重要的多,即使我们做资源的重新排列,那也是在保证业务稳定性不受影响的情况下进行。 Rebalance是每个Kubernetes的使用者应该考虑和研究的问题,一定程"度"的碎片整理也是业务稳定运行的保证。

注:我们会在本系列(下)篇文章中重点介绍Rescheduler的场景和Rebalance的策略。

3

参考文献及致谢

参考文献:

  • 《Everything You Ever Wanted to Know About Resource Scheduling But Were Afraid to Ask》,Tim Hockin,Google, KubeCon Seattle 2016
  • http://doc.kubernetes.cn/docs/concepts/policy/resource-quotas/

  • https://github.com/kubernetes/community/blob/d1160c0c58e45ca980fa0953d3504dcbf7e3f3c9/contributors/design-proposals/resources.md

  • https://github.com/kubernetes/community/blob/d1160c0c58e45ca980fa0953d3504dcbf7e3f3c9/contributors/design-proposals/resource-qos.md

4

加入容器时代

容器时代公众号的目的是希望能够传播容器技术和理念,让更多的人能够享受到这场技术革命带来的好处。虽然我们不是大牛,对容器技术生态的了解和认识也还不够深刻,但是我们乐于分享,乐于交流。不管读者的你是学生,还是工程师,甚至都不是,我们都欢迎你加入进来,可以一起写文章、翻译文章,也可以一起分享经验、聊聊踩过的那些坑!为此特意建立了一个微信群,长按识别下方二维码加入,我们以梦为马,一起前行!

聊聊Kubernetes计算资源模型(上)——资源抽象、计量与调度

聊聊Kubernetes计算资源模型(上)——资源抽象、计量与调度

5

架构真经

《架构真经:互联网技术架构的设计原则(原书第2版)》 即将震撼上市,关注容器时代公众号可以 有机会获得 亲笔签名 图书,赶快关注 !!

聊聊Kubernetes计算资源模型(上)——资源抽象、计量与调度

版权声明:任何转载需全文转载并保留来源(微信公众号容器时代),同时转载容器时代的二维码,否则视作侵权。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

复杂网络理论及其应用

复杂网络理论及其应用

汪小帆、李翔、陈关荣 / 清华大学出版社 / 2006 / 45.00元

国内首部复杂网络专著 【图书目录】 第1章 引论 1.1 引言 1.2 复杂网络研究简史 1.3 基本概念 1.4 本书内容简介 参考文献 第2章 网络拓扑基本模型及其性质 2.1 引言 2.2 规则网络 2.3 随机图 2.4 小世界网络模型 2.5 无标度网络模型 ......一起来看看 《复杂网络理论及其应用》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

在线进制转换器
在线进制转换器

各进制数互转换器

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试