前言
本文仅代表作者的个人观点;
本文的内容仅限于技术探讨,不能直接作为指导生产环境的素材;
本文素材是红帽公司产品技术和手册;
本文分为系列文章,将会有多篇,初步预计将会有8篇。
本文最后一节网络QoS部分,引用了潘晓华的文章。
一、计算资源
在OCP中,每个计算节点(默认是node节点,master节点通过配置也可以运行业务,但不建议这么做。)对于pod而言,CPU和内存都是属于计算资源。
在创建pod的时候,可以指定容器需要多少CPU和内存(RAM)。其中:
例如下图,设置pod需要获取的CPU是100m,内存是200MiB。100m相当于1/10 CPU Core的计算能力。
二、几个参数
CPU Request
1. 如果节点上没有CPU争用,它可以使用所有可用的CPU
2.如果节点上存在CPU争用,则CPU Request会在系统上的所有容器中提供相对权重,以确定容器可以使用多少CPU时间
CPU Limits
Memory Requests
Memory Limits
三、CPU资源角度:服务等级的划分
所谓服务等级,指的是pod的服务等级。
BestEffort,表示容器“很爽”;不设置容器的 Limits数值和reuest数值,它想用多少资源用多少资源(在资源充裕无争抢的情况下)
Burstable,我们设置容器的request和limits数值,而且request<limits。这时候,容器不是想用多少就用多少了,它获取到的CPU总量,不能超过limits数值,已经“不太爽”
Guaranteed,我们设置容器的request和limits数值,而且request=limits。这时候容器非常不爽了,因为它只能获取到固定数量的CPU资源。
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容器都被干掉了,内存还是不够;
五、项目资源Project Resource Limits
在接下的文章中,我们将会提到limitrange和qouta两个概念,他们的区别是什么?
举个例子,有一群猴子,猴群A,还有猴群B。我们分香蕉,猴群A最多只能100个,这个是qouta;猴群中:猴王分10个,猴王夫人分5个,其余的猴手一个,这就是limitrange。
Project Resource Limits:
Project Resource Limits范围由LimitRange对象定义,它可以限制项目中的pod、容器、image和imagestream的总数量。这个显示是强制的。
既然是范围,那就有最小值和最大值,我们看具体注意事项:
有关容器的限制:
有关pod的限制:
有关镜像的限制:
我们看个例子:
使用qouta和LimitRange,集群管理员可以设置约束以限制对象数量或项目中使用的计算资源量。这有助于集群管理员更好地管理和分配所有项目的资源;开发人员还可以在pod和容器级别设置计算资源的请求和限制
由qouta管理的资源:
qouta管理的对象数量
Qouta的范围:
配额执行
例如,我们配置qouta的数量限制:
计算资源限制:
查看一个项目的qouta:
七、过量使用
CPU
容器保证其请求的CPU数量得到满足,如果容器未指定相应的limits,则可能会消耗节点上可用的多余CPU
如果多个容器尝试使用多余的CPU,则根据每个容器请求的CPU数量分配CPU时间
例如,如果Container A请求500m的CPU时间,而Container B请求250m的CPU时间:
节点上可用的任何额外CPU时间以2:1的比例分配在容器A和B之间
内存:
容器可能会使用比请求的内存更多的内存,但是一旦超过请求的数量,当计算节点内存不足是后,容器可能会被干掉;
如果容器使用的内存少于请求的内存,则除非系统任务或守护程序需要的内存多于节点资源预留中所占用的内存,否则它不会被终止
如果container指定内存limits,如果超过有限数量,则会立即终止
当出现过量使用的情况下,容器被杀死的可能性如下:
要控制过度使用的级别并管理节点上的容器密度,可以将master节点配置为覆盖开发人员容器上的请求和限制之间的比率
结合每个项目的LimitRange指定限制和默认值,这会调整容器限制并请求达到所需的过度使用级别
需要在master-config.yaml中配置ClusterResourceOverride许可控制器,如下例所示:
配置后,可以通过编辑项目并添加以下注释来为每个项目禁用覆盖:
quota.openshift.io/cluster-resource-override-enabled:“false”
八、HPA
OCP中的pod,可以基于CPU、内存做自动的水平弹性扩展。
我们对一个pod设置request和limit资源。当pod繁忙的时候,会获取额外的资源,直到到达limits,我们可以简单理解成这是纵向扩展。
但在容器中,显然横向扩展更靠谱。HPA基于CPU的利用率。
选定一个pod,对其设置CPU和HPA:
由于CPU较为空闲利用率低于20%,在设置的HPA生效以后,pod自动缩减:
接下来,通过Curl循环对pod加压。
查看pod的route:
IP=dzwls-demo3.apps.ab.com
for time in {1..5000}
do
echo time$time
curl ${IP}:80
done
Pod的数量很快增加到4个:
查看Pod的event:
基于内存的HPA
启动内存HPA:
修改master-config.yaml,增加如下一行:
创建内存HPA的yaml。
查看pod的route:
压测前:
压测:
IP=dzwls923-demo3.apps.ab.com
for time in {1..5000}
do
echo time$time
curl ${IP}:80
done
八、网络QoS的实现
高速公路上,当流量大时,如果汽车仍然不限制速度的话,将会很容易发生车祸,我们都会自觉地减速缓慢通过,只有减速才能安全行驶。 在平台的集群中也是一样,一台主机上会有大量容器运行,容器相当于高速速上的汽车,对外的网络通信都使用主机出口这条高速路,如果某(几)个容器突然访问流量大增,而且没有作任何网络限速,会占用了主机的网络,严重影响其它容器的网络,进而影响其它业务。
redhat/openshift-ovs-multitenant
...
hostSubnetLength: 9
networkPluginName: redhat/openshift-ovs-multitenant
serviceNetworkCIDR: 172.30.0.0/16
...
kind: Pod
apiVersion: v1
metadata:
name: nginx
annotations:
kubernetes.io/ingress-bandwidth: 1M
kubernetes.io/egress-bandwidth: 1M
spec:
containers:
- image: nginx
name: nginx
说明
:
(出端口)下行
的网速限制(入端口)上行
的网速限制M
,实际单位对应的是Mb
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访问外网
[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
说明
:
魏新宇