如何限制Kubernetes资源(CPU和内存)
默认情况下,当我们创建Pod时,它有权使用主机上的所有系统资源,除非我们对允许的资源添加了限制,或者Container在具有默认CPU限制的命名空间中运行,并且Container会自动分配了默认限制。现在,Linux内核具有可用于限制CPU和内存的cgroup。 docker run使用cgroup来实现这些限制。因此,当我们指定Pod时,我们还可以选择提供容器可能需要的资源限制,以避免过度使用。要指定的最常见资源是CPU和内存(RAM)。
当我们实现这种资源限制时,然后在创建Pod的阶段,调度程序将使用此信息来根据资源的可用性来决定将Pod放置在哪个节点上。 kubelet还至少保留专门用于该容器的系统资源的请求量。
不同的Kubernetes资源类型
在撰写本教程时,有不同的资源类型可以针对Pod和Container施加请求和限制:
中央处理器
记忆
大页面(Kubernetes v1.14或者更高版本)
CPU和内存统称为计算资源,或者仅称为资源。计算资源是可请求,分配和消耗的可测量数量
Pod和容器的资源请求和限制
通常,当我们谈论这种阈值限制时,我们必须有一个软性限制和硬性限制。因此,我们可以为各个Pod和Containers的允许资源定义一个软限制值,以及一个上限,超过该上限将拒绝使用。在Kubernetes中,这种软限制被定义为请求
,而硬限制被定义为限制
。
如果运行Pod的节点有足够的可用资源,则容器有可能(允许)使用比该资源指定的"请求"更多的资源。但是,容器不能使用超过其资源limit
的值。
Pod的每个容器可以指定以下一项或者多项:
spec.containers []。resources.limits.cpu
spec.containers []。resources.limits.memory`
spec.containers []。resources.limits.hugepages- <size>
spec.containers []。resources.requests.cpu
spec.containers []。resources.requests.memory`
spec.containers []。resources.requests.hugepages- <size>
说明:
如果容器指定了自己的内存限制,但未指定内存请求,则Kubernetes会自动分配与该限制匹配的内存请求。同样,如果容器指定了自己的CPU限制,但未指定CPU请求,则Kubernetes会自动分配与该限制匹配的CPU请求。
了解资源单位
我们在Kubernetes中使用了一个不同的单位来测量CPU和内存:
定义CPU限制
CPU资源的限制和请求以cpu为单位进行度量。
Kubernetes中的一个cpu相当于云提供商的1个vCPU/Core和裸机Intel处理器上的1个超线程。
每当我们指定CPU请求或者限制时,我们都会根据CPU内核数来指定它们。
因为通常我们希望将Pod的使用要求或者限制为整个CPU内核的一部分,所以我们可以将CPU的这一部分指定为小数或者毫内核值。
例如,值为0.5表示核心的一半。
还可以使用毫核心值配置请求或者限制。由于单核有1,000毫微微升,因此我们可以将一半的CPU指定为500 m。
可以指定的最小CPU数量为1 m或者0.001.
定义内存限制
限制和对内存的请求以字节为单位。
我们可以使用以下后缀之一将内存表示为纯整数或者定点数字:E,P,T,G,M,K。
我们还可以使用2的幂次方:Ei,Pi,Ti,Gi,Mi,Ki
Kubernetes支持的存储单元
名称 | 字节 | 后缀 | 名称 | 字节 | 后缀 |
---|---|---|---|---|---|
库洛比特 | 1000 | K | kibibyte | 1024 | Ki |
兆字节 | 1000*2 | M | 兆字节 | 1024*2 | Mi |
千兆字节 | 1000*3 | G | 千兆字节 | 1024*3 | Gi |
太字节 | 1000*4 | T | 太字节 | 1024*4 | Ti |
千兆字节 | 1000*5 | P | 千兆字节 | 1024*5 | Pi |
字节 | 1000*6 | E | 字节 | 1024*6 | Ei |
如何管理具有资源限制的Pod
当Kubelet启动容器时,CPU和内存限制将传递给容器运行时,然后运行时负责管理该容器的资源使用情况。
如果我们使用的是Docker,则将CPU限制(以milicores为单位)乘以100,以得到允许容器每100毫秒使用一次的CPU时间。如果CPU处于负载状态,则一旦容器使用了其配额,它就必须等待下一个100毫秒的时间才能继续使用CPU。
在cgroup中运行的不同进程之间共享CPU资源的方法称为
完全公平调度程序
或者CFS
;这是通过在不同cgroup之间划分CPU时间来实现的。这通常意味着将一定数量的片分配给cgroup。如果一个cgroup中的进程处于空闲状态,并且不使用其分配的CPU时间,则这些共享将可供其他cgroup中的进程使用。
如果达到内存限制,则容器运行时将使用
OOM
终止容器(并且可能会重新启动)。如果容器使用的内存超过了请求的数量,则当节点何时开始耗尽内存时,它将成为逐出的候选对象。
这是一个容器被OOM杀死的示例:
Nov 28 23:27:36 worker-1.example.com kernel: Memory cgroup out of memory: Kill process 1331 (mysqld) score 2250 or sacrifice child Nov 28 23:27:36 worker-1.example.com kernel: Killed process 1331 (mysqld) total-vm:1517000kB, anon-rss:126500kB, file-rss:42740kB, shmem-rss:0kB
示例:定义容器的CPU和内存限制
在定义资源限制时,最好使用单独的名称空间,以使在本练习中创建的资源与群集的其余部分隔离。
[root@controller ~]# kubectl create namespace cpu-limit namespace/cpu-limit created
验证新创建的NS
[root@controller ~]# kubectl get ns NAME STATUS AGE cpu-limit Active 46s default Active 24h kube-node-lease Active 24h kube-public Active 24h kube-system Active 24h
在此示例中,我们将创建一个Pod,其中包含2个具有MySQL数据库和Wordpress的容器,并带有一些CPU和内存预留空间。
[root@controller ~]# cat pod-resource-limit.yml apiVersion: v1 kind: Pod metadata: name: frontend namespace: cpu-limit spec: containers: - name: db image: mysql env: - name: MYSQL_ROOT_PASSWORD value: "password" resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m" - name: wp image: wordpress resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"
接下来,我们使用以下YAML文件创建pod:
[root@controller ~]# kubectl create -f pod-resource-limit.yml pod/frontend created
监视新创建的容器的状态:
[root@controller ~]# kubectl get pods -n cpu-limit -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES frontend 0/2 ContainerCreating 0 38s <none> worker-1.example.com <none> <none>
创建容器可能需要一些时间,并在几秒钟内进行验证:
[root@controller ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES frontend 2/2 Running 1 3m6s 10.36.0.2 worker-1.example.com <none> <none>
我们可以使用kubectl describe
检查Pod的详细信息:
[root@controller ~]# kubectl describe pods frontend Name: frontend Namespace: cpu-limit Priority: 0 Node: worker-1.example.com/192.168.43.49 Start Time: Sat, 28 Nov 2017 23:31:10 +0530 Labels: <none> Annotations: <none> Status: Running IP: 10.36.0.2 IPs: IP: 10.36.0.2 Containers: ... State: Running Started: Sat, 28 Nov 2017 23:31:51 +0530 Ready: True Restart Count: 0 Limits: cpu: 500m memory: 128Mi Requests: cpu: 250m memory: 64Mi Environment: <none>
如果未指定CPU限制
如果我们没有为容器指定CPU限制,则适用以下情况之一:
容器在可以使用的CPU资源上没有上限。容器可以使用运行它的节点上所有可用的CPU资源。
容器在具有默认CPU限制的命名空间中运行,并且自动为容器分配了默认限制。集群管理员可以使用
LimitRange
来指定CPU限制的默认值。
删除pod
要删除cpu-limit
名称空间的pod部分,我们可以使用:
[root@controller ~]# kubectl delete pods -n cpu-limit frontend pod "frontend" deleted