Kubernetes(k8s)之容器资源限制
Posted Tuki_a
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kubernetes(k8s)之容器资源限制相关的知识,希望对你有一定的参考价值。
k8s容器资源限制
资源限制的实现
Kubernetes对资源的限制实际上是通过cgroup来控制的,cgroup是容器的一组用来控制内核如何运行进程的相关属性集合。针对内存、CPU和各种设备都有对应的cgroup。
默认情况下,Pod运行没有CPU和内存的限额。这意味着系统中的任何Pod将能够像执行Pod所在节点机器一样,可以消耗足够多的CPU和内存。一般会针对某些应用的Pod资源进行资源限制,这个资源限制是通过resources的requests【要分配的资源】和limits【最大使用资源】来实现的。
资源的两种限制类型
Kubernetes采用request和limit两种限制类型来对资源进行分配。
1、request(资源需求):即运行Pod的节点必须满足运行Pod的最基本需求才能运行Pod。
2、limit(资源限额):即运行Pod期间,可能内存使用量会增加,那最多能使用多少内存,这就是资源限额。
资源类型单位
1、CPU
CPU 的单位是核心数,内存的单位是字节。
一个容器申请0.5个CPU,就相当于申请1个CPU的一半,你也可以加个后缀m,表示千分之一的概念。
比如说100m(100豪)的CPU等价于0.1个CPU。
2、内存单位:
K、M、G、T、P、E ##通常是以1000为换算标准的。
Ki、Mi、Gi、Ti、Pi、Ei ##通常是以1024为换算标准的。
演示环境
server1:172.25.38.1 harbor仓库端
server2:172.25.38.2 k8s master端
server3:172.25.38.3 k8s node端
server4:172.25.38.4 k8s node端
Memory内存限制
在容器里使用镜像stress进行压力测试,指定资源数进行压力测试。先在仓库端拉取镜像并上传供k8s的master端使用。
#stress镜像其实就是封装了stress命令(模拟系统负载较高时的场景)
新创建一个目录,并创建一个用stress镜像的pod,内容如下:
apiVersion: v1
kind: Pod
metadata:
name: memory-demo
spec:
containers:
- name: memory-demo
image: stress
args: #提供了容器启动的参数
- --vm
- "1" #模拟一个进程
- --vm-bytes
- 200M #每个进程使用200M内存
resources:
requests:
memory: 50Mi #最少需要50Mi内存
limits:
memory: 100Mi #最多100Mi
应用文件创建pod
可以看到状态变化如下,OMMKilled是超出内存限制的意思。
我们要求启动时开一个使用200M内存的进程,可我们又限制最多100M,那么自然会超出限制。如果一个容器超过其内存请求,那么当节点内存不足时,它的 Pod 可能被逐出。
crashloopbackoff意味着pod挂掉又重启又挂掉如此往复。
如果容器超过其内存限制,则会被终止。如果可重新启动,则与所有其他类型的运行时故障一样,kubelet 将重新启动它。
CPU限制
创建一个用stress镜像的pod做cpu压测
apiVersion: v1
kind: Pod
metadata:
name: cpu-demo
spec:
containers:
- name: cpu-demo
image: stress #使用stress镜像
resources:
limits:
cpu: "10" #至多使用10个CPU
requests:
cpu: "5" #最少用5个CPU
args: #提供了容器启动的参数
- -c #CPU
- "2" #指定容器启动时使用2个CPU
应用文件出现如下状态,待调度。这是因为我们设置容器至少需要5个CPU,但我们根本没有5个CPU(我只给了虚拟机一个CPU)即没有符合条件的node,自然无法成功调度pod
LimitRange
LimitRange 在 namespace 中施加的最小和最大内存限制只有在创建和更新 Pod 时才会被应用。改变 LimitRange 不会对之前创建的 Pod 造成影响。
为namespace设置资源限制
定义default这个namespaces下的资源限制,文件内容如下:
apiVersion: v1
kind: LimitRange #资源类型
metadata:
name: limitrange-memory
spec:
limits:
- default: #当pod定义文件里没有指定资源数,在这个namespaces下最多使用0.5个cpu,512Mi内存
cpu: 0.5
memory: 512Mi
defaultRequest: #当pod定义文件里没有指定资源数,在这个namespaces下最少需要0.1个cpu,256Mi内存
cpu: 0.1
memory: 256Mi
max: #不管pod定义文件里有没有指定资源数,在这个namespaces下最多用1个cpu,1Gi内存
cpu: 1
memory: 1Gi
min: #不管pod定义文件里有没有指定资源数,在这个namespaces下最少需要0.1个cpu,100Mi内存
cpu: 0.1
memory: 100Mi
type: Container
应用文件创建出了属于default这个namespaces的资源限制
可以查看详细描述
编写一个限制内存的创建pod的定义文件,内容如下:
apiVersion: v1
kind: Pod
metadata:
name: memory-demo
spec:
containers:
- name: memory-demo
image: nginx
resources:
requests:
memory: 50Mi #最少需要50Mi内存
limits:
memory: 100Mi #最多100Mi
应用文件创建pod失败,是因为我们上面的limitrange的作用,最少要100Mi,而我们设定50Mi,所以出错了
将文件中如下图部分注释掉即不指定资源限制
重新应用
执行kubectl describe pod memory-demo
可以看到因为LimitRange的缘故自动加上了资源限制
ResourceQuota
LimitRange是针对单个pod设置资源限制,ResourceQuota是针对所有pod设置的资源总额。
创建的ResourceQuota对象将在default名字空间中添加以下限制:
每个容器必须设置内存请求(memory request),内存限额(memory limit),cpu请求(cpu request)和cpu限额(cpu limit)。
为namespace设置资源配额
定义default这个namespaces下的资源配额,文件内容如下:
apiVersion: v1
kind: ResourceQuota
metadata:
name: mem-cpu-demo
spec:
hard:
requests.cpu: "1" #所有容器的CPU请求总额不得超过1 CPU
requests.memory: 1Gi #所有容器的内存请求总额不得超过1 GiB
limits.cpu: "2" #所有容器的CPU限额总额不得超过2 CPU
limits.memory: 2Gi #所有容器的内存限额总额不得超过2 GiB
修改一下上面用过的pod2.yaml文件
apiVersion: v1
kind: Pod
metadata:
name: memory-demo
spec:
containers:
- name: memory-demo
image: nginx
resources:
requests:
cpu: 0.2
memory: 100Mi
limits:
cpu: 1
memory: 300Mi
应用创建pod,可以看到资源配额已经用了多少
再修改一下文件重新创建一个pod,并设置如下图资源请求
再看资源配额,可以看到累加起来的资源总额
修改资源配额定义文件,限制pod总数为4个
重新应用文件,资源配额更新成功
以上是关于Kubernetes(k8s)之容器资源限制的主要内容,如果未能解决你的问题,请参考以下文章
Kubernetes 系列K8S 进阶 容器和 Pod 分配内存资源
Linux企业运维——Kubernetes(十五)容器资源限制