容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇

前言

本文仅代表作者的个人观点;

本文的内容仅限于技术探讨,不能直接作为指导生产环境的素材;

本文素材是红帽公司产品技术和手册;

本文分为系列文章,将会有多篇,初步预计将会有8篇。

本文最后一节网络QoS部分,引用了潘晓华的文章。


一、计算资源


在OCP中,每个计算节点(默认是node节点,master节点通过配置也可以运行业务,但不建议这么做。)对于pod而言,CPU和内存都是属于计算资源。


在创建pod的时候,可以指定容器需要多少CPU和内存(RAM)。其中:

  • CPU是以millicores的单位进行分配,即一个CPU core 1/1000的运算能力。

  • 内存分配以字节为单位,也可以设置成 以Gi, Mi, Ki为单位。


例如下图,设置pod需要获取的CPU是100m,内存是200MiB。100m相当于1/10 CPU Core的计算能力。

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇



二、几个参数

CPU Request

  • pod中的每个容器都可以指定它在节点上请求的CPU量;同时Scheduler使用CPU请求来查找适合容器的节点

  • CPU Request表示容器可能消耗的最小CPU量

  1. 如果节点上没有CPU争用,它可以使用所有可用的CPU

   2.如果节点上存在CPU争用,则CPU Request会在系统上的所有容器中提供相对权重,以确定容器可以使用多少CPU时间



CPU Limits

  • pod中的每个容器都可以指定限制在计算节点上使用的CPU数量上限

  • CPU Limits控制容器可以使用的最大CPU总数量

  • 如果容器获取的CPU数量不能超过CPU Limits的数值


Memory Requests

  • 默认情况下,容器在计算节点上消耗的内存是内有限制的

  • 设置Memory Requests有助于OCP做容器的调度(放到一个内存够的node上)


Memory Limits

  • 指定内存限制以限制容器可以使用的内存量

  • 示例:如果指定限制为200Mi,则容器仅限于在节点上使用该内存量

  • 如果容器超出指定的内存限制,则终止中期

  • 可以根据容器重启策略重新启动



三、CPU资源角度:服务等级的划分


所谓服务等级,指的是pod的服务等级。


BestEffort,表示容器“很爽”;不设置容器的 Limits数值和reuest数值,它想用多少资源用多少资源(在资源充裕无争抢的情况下)


Burstable,我们设置容器的request和limits数值,而且request<limits。这时候,容器不是想用多少就用多少了,它获取到的CPU总量,不能超过limits数值,已经“不太爽”


Guaranteed,我们设置容器的request和limits数值,而且request=limits。这时候容器非常不爽了,因为它只能获取到固定数量的CPU资源。

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇


BestEffort CPU容器可以占用具有最低优先级的计算节点上可用的CPU,有多少能占多少。


Burstable CPU保证容器最少得获得一定数量的CPU,也就是request的数值。在资源有富余的情况下,它还可以能获的额外的CPU资源,但不能超过limits的数值。


Guaranteed CPU保证容器最少得获得一定数量的CPU,也就是request的数值。但即使资源有富裕,容器也不能获得额外的CPU资源。


四、CPU资源角度:服务等级的划分


BestEffor memory配置:容器能够消耗节点上所有可用的内存,但这种模式有个风险:调度程序可能将容器放在可用内存较少的计算节点上。


Burstable memory配置:容器将会被放到可用内存能够满足request memory的计算节点上,容器可能会获取到额外的内存,但不能超过limiis


Guaranteed memory配置:容器将会被放到可用内存能够满足request memory的计算节点上,容器不可能再获取到额外的内存。


内存出现争抢,不够了,怎么办?(out-of-memory event)



  • BestEffor memory容器最先被干掉;


如果内存还是不够


  • Burstable memory容器被干掉;


当所有BestEffor memory容器和Burstable memory容器都被干掉了,内存还是不够;


  • Guaranteed memory容器最后被干掉





五、项目资源Project Resource Limits

在接下的文章中,我们将会提到limitrange和qouta两个概念,他们的区别是什么?


  • qouta是从宏观角度,限制一个项目总使用资源、创建资源的总量;

  • limitrange是限制一个项目内,每个容器使用多少资源。


举个例子,有一群猴子,猴群A,还有猴群B。我们分香蕉,猴群A最多只能100个,这个是qouta;猴群中:猴王分10个,猴王夫人分5个,其余的猴手一个,这就是limitrange。


Project Resource Limits:

  • 群集管理员可以按项目设置资源限制

  • 开发人员无法创建,编辑或删除这些限制,但他们可以查看他们可以访问的项目


Project Resource Limits范围由LimitRange对象定义,它可以限制项目中的pod、容器、image和imagestream的总数量。这个显示是强制的。


既然是范围,那就有最小值和最大值,我们看具体注意事项:


有关容器的限制:

  • Resource Limits的最小值,必须要<= pod中定义的request;要要<= pod中定义的limits

  • Resource Limits的最大值,必须要>pod中定义的limits

  • MaxLimitRequestRatio,必须要 <= pod中定义的limits/Request比值,例如,容器的cpu:500表示limits,cpu:100表示request,则cpu的LimitRequestRatio 为5.此比率必须小于或等于maxLimitRequestRatio。

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇


有关pod的限制

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇


有关镜像的限制:

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇

我们看个例子:

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇



六、Quotas


使用qouta和LimitRange,集群管理员可以设置约束以限制对象数量或项目中使用的计算资源量。这有助于集群管理员更好地管理和分配所有项目的资源;开发人员还可以在pod和容器级别设置计算资源的请求和限制


由qouta管理的资源:

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇

qouta管理的对象数量

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇


Qouta的范围:

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇



配额执行

  • 首次创建项目的资源Qouta后,项目会限制创建违反Qouta约束的新资源的能力,直到计算出更新的使用情况统计信息为止

  • 创建Qouta并更新使用情况统计信息后,项目中新创建的资源将会受此限制

  • 当尝试创建或修改资源时,根据创建或修改资源的请求,配额使用会立即增加

  • 删除资源时,在下次完全重新计算项目的配额统计信息期间,配额使用量会减少

  • 可配置的时间总量,决定了将配额使用统计信息减少到当前观察到的系统值所需的时间

  • 如果项目修改超出配额使用限制:

       服务器拒绝该操作

       向用户返回适当的错误消息,说明违反的配额约束,以及他们当前观察到的使用统计数据在系统中的情况



例如,我们配置qouta的数量限制:

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇

计算资源限制:

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇

查看一个项目的qouta:

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇




七、过量使用

CPU

容器保证其请求的CPU数量得到满足,如果容器未指定相应的limits,则可能会消耗节点上可用的多余CPU


如果多个容器尝试使用多余的CPU,则根据每个容器请求的CPU数量分配CPU时间


例如,如果Container A请求500m的CPU时间,而Container B请求250m的CPU时间:

     节点上可用的任何额外CPU时间以2:1的比例分配在容器A和B之间



内存:

容器可能会使用比请求的内存更多的内存,但是一旦超过请求的数量,当计算节点内存不足是后,容器可能会被干掉;


如果容器使用的内存少于请求的内存,则除非系统任务或守护程序需要的内存多于节点资源预留中所占用的内存,否则它不会被终止


如果container指定内存limits,如果超过有限数量,则会立即终止



当出现过量使用的情况下,容器被杀死的可能性如下:

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇

要控制过度使用的级别并管理节点上的容器密度,可以将master节点配置为覆盖开发人员容器上的请求和限制之间的比率


结合每个项目的LimitRange指定限制和默认值,这会调整容器限制并请求达到所需的过度使用级别


需要在master-config.yaml中配置ClusterResourceOverride许可控制器,如下例所示:

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇

配置后,可以通过编辑项目并添加以下注释来为每个项目禁用覆盖:


quota.openshift.io/cluster-resource-override-enabled:“false”



  八、HPA


OCP中的pod,可以基于CPU、内存做自动的水平弹性扩展。


我们对一个pod设置request和limit资源。当pod繁忙的时候,会获取额外的资源,直到到达limits,我们可以简单理解成这是纵向扩展。


但在容器中,显然横向扩展更靠谱。HPA基于CPU的利用率。


选定一个pod,对其设置CPU和HPA:



 

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇


由于CPU较为空闲利用率低于20%,在设置的HPA生效以后,pod自动缩减:

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇



接下来,通过Curl循环对pod加压。

查看pod的route:


 

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇


IP=dzwls-demo3.apps.ab.com   

for time in {1..5000}

  do

   echo time$time

   curl ${IP}:80

  done

 

Pod的数量很快增加到4个:

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇



查看Pod的event:


 

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇


基于内存的HPA

启动内存HPA:

 

修改master-config.yaml,增加如下一行:

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇



创建内存HPA的yaml。



 

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇


查看pod的route:

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇



压测前:

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇



压测:

IP=dzwls923-demo3.apps.ab.com  

for time in {1..5000}

do

   echo time$time

   curl ${IP}:80

  done

 



 

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇

容器计算资源管理&网络QoS的实现---Openshift3.9学习系列第四篇




八、网络QoS的实现


前面谈了对CPU和内存的QoS限制,最后我们看看网络的QoS如何实现。

Pod网络(速)控制的必要性


高速公路上,当流量大时,如果汽车仍然不限制速度的话,将会很容易发生车祸,我们都会自觉地减速缓慢通过,只有减速才能安全行驶。
在平台的集群中也是一样,一台主机上会有大量容器运行,容器相当于高速速上的汽车,对外的网络通信都使用主机出口这条高速路,如果某(几)个容器突然访问流量大增,而且没有作任何网络限速,会占用了主机的网络,严重影响其它容器的网络,进而影响其它业务。

前提

  • Openshift打开多租户网络模式
    修改/etc/origin/master/master-config.yaml将networkPluginName设置为redhat/openshift-ovs-multitenant


...
  hostSubnetLength: 9
  networkPluginName: redhat/openshift-ovs-multitenant
  serviceNetworkCIDR: 172.30.0.0/16
...

为Pod添加网络限速标记

kind: Pod
apiVersion: v1
metadata:
  name: nginx
 annotations:
   kubernetes.io/ingress-bandwidth: 1M
   kubernetes.io/egress-bandwidth: 1M
spec:
    containers:
      - image: nginx
        name: nginx


说明:

  • kubernetes.io/ingress-bandwidth设置的是 (出端口)下行的网速限制

  • kubernetes.io/egress-bandwidth设置的是 (入端口)上行的网速限制

  • 网络限制单位必须是M,实际单位对应的是Mb

为DeploymentConfig添加限速标记

kind: DeploymentConfig
metadata:
  labels:
    app: nginx
  name: nginx  namespace: test
spec:
  replicas: 1
  selector:
    deploymentconfig: nginx  template:
    metadata:
      annotations:
        kubernetes.io/egress-bandwidth: 0.5M
        kubernetes.io/ingress-bandwidth: 0.5M
      labels:
        app: nginx
        deploymentconfig: nginx
    spec:
      containers:
        - image: nginx
          name: nginx

说明:

  • 因为限速是面向Pod的所以需要要Pod对应的template中添加网络上下行速度限制。


测试(上行与下行都限制为0.5M)

Pod访问外网

[root@demo ~]# oc rsh op-java-sample-13-7bmj7sh-4.2$ wget https://xxxx.com/xx.zip
--2018-07-10 08:31:26--  https://xxxx.com/xx.zip
Resolving xxxx.com (xxxx.com)... 117.211.167.14Connecting to xxxx.com (xxxx.com)|117.211.167.14|:443... connected.
HTTP request sent, awaiting response... 200 OKLength: unspecified [application/zip]
Saving to: 'xx.zip.2'

  14% [               <=>                                                 ] 211,857     57.2KB/s

说明:
下载速度为57.2KB/s,恰好是被限的500Kb

外部访问Pod

[root@demo ~]# wget http://10.131.1.32:8080/20180416.db--2018-07-10 16:50:02--  http://10.131.1.32:8080/20180416.dbConnecting to 10.131.1.32:8080... connected.
HTTP request sent, awaiting response... 200 OK
Length: 10698784 (10M) [application/octet-stream]
Saving to: ‘20180416.db.1’ 9% [               <=>                                                 ]1,056,888   58.3KB/s  eta 4m 10s

说明
10.131.1.32为Pod在集群下的IP,从主机访问Pod的服务下载文件,速度为58.3KB/s,恰好是被限的500Kb

同一个Poroject下的Pod间访问

sh-4.2$ wget http://10.131.1.32:8080/20180416.db--2018-07-10 08:54:50--  http://10.131.1.32:8080/20180416.dbConnecting to 10.131.1.32:8080... connected.
HTTP request sent, awaiting response... 200 OK
Length: 10698784 (10M) [application/octet-stream]
Saving to: '20180416.db' 13% [======================>                                       ] 1,480,482   57.6KB/s  eta 47s

说明:

  • Pod间网络访问也会受到Pod网络配置的控制

  • 同时在测试过程中发现,刚开始测试时网络是很高的,但是3-5s后会降到被限制的网速


上一篇:Token Bucket在QoS中入门级介绍python示例


下一篇:Chapter 3 Part 2