K8S中pod和container的资源管理:CPU和Memory
K8S中创建pod时,可以显示地指明包含的container的资源需求(resouce request和resource limit),通常是CPU和Memory(RAM).
kube-scheduler将用这些container的资源请求(resource request)汇总成该pod的需求,来决定在哪个node上部署这个pod;而node上的kubelet则保留相应的资源给container使用,以及根据这些container的资源限制(resource limit)来执行,不允许其使用的资源超过设置的limit。
【requests和limits】
如果pod所在的node有足够的资源,可以允许container使用比request更多的资源,但不能超过limit的限制。
例如:一个container的memory request是256MiB,limit是4GiB,而所在node的RAM是8GiB,则该container使用的RAM可以大于256MiB,但不能多于4GiB。如果该process尝试使用更多的内存,system kernel将终止该process(注意:是该container所属的pod将被终止),并且报出out of memory (OOM)的错误信息。
(参考文档1:If a container exceeds its memory request and the node that it runs on becomes short of memory overall, it is likely that the Pod the container belongs to will be evicted)
> 如果container只是设置了memory limit,而没有设置memory request,则kubernetes会自动认为memory request等于memory limit;
> 如果container只是设置了cpu limit,而没有设置cpu request,则kubernetes会自动认为cpu request等于cpu limit;
> 如果container只是设置了memory request,而没有设置memory limit,则以下场景的其中一个会被应用:
- container可以无上限地使用memory,例如使用所在node的所有可用memory,这样可能会导致OOM Killer。
- container所属的namespace有default memory limit,则container使用这个limit。
> 如果container只是设置了cpu request,而没有设置cpu limit,则以下场景的其中一个会被应用:
- container可以无上限地使用cpu,例如使用所在node的所有可用cpu。
- container所属的namespace有default cpu limit,则container使用这个limit。
> container可能被允许或不被允许在较长时间内超过其CPU限制。然而container runtimes不会因CPU过度使用而终止该POD或container。
注:查看配置时看到cpu/memory limit是0(或者0%)时,表示没有limit。
container与资源request/limit相关的参数如下:
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>
注:与cpu,memory不一样,hugepage资源不能超配(overcommit)。
pod的资源request/limit就是所包含的container对应的资源request/limit的总和。
【资源计量单位(resource units)】
CPU Resource Units:
CPU resource用cpu unit来计量,在kubernetes中1个CPU Unit等于1个物理CPU core或者1个虚拟CPU core(1 physical CPU core, or 1 virtual core),取决于这个node是物理主机还是虚拟机。
CPU resource的计量可以使用小数,例如一个容器的spec.containers[].resources.requests.cpu=0.5,表示申请占用一半的cpu time。
为避免使用小数,millicpu(或者millicores) 被引入:1millicpu(简写成1m)=0.001cpu unit。这样0.1cpu unit就可以用100m表示。
kubernetes中1m是最小的cpu resource计量单位了,小于1m是不被允许的。
CPU resource总是一个绝对值,不是相对值;不管这个container是运行在哪种CPU架构上:single-core, dual-core, or 48-core,500m CPU表示相同的计算资源消耗。
Memory Resource Units:
内存用bytes来计量。可以将内存表示为一个正整数,或者使用以下数量后缀之一来表示:E、P、T、G、M、k。也可以使用计算机字节数:Ei、Pi、Ti、Gi、Mi、Ki。例如,以下值大致相同:128974848, 129M, 128974848000m,123Mi。注意:400m表示0.4byte,400Mi表示400M byte。
下面是一个container资源需求的YAML文件示例:
---
apiVersion: v1
kind: Pod
metadata:
name: frontend
spec:
containers:
- name: app
image: images.my-company.example/app:v4
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
- name: log-aggregator
image: images.my-company.example/log-aggregator:v6
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
【资源使用率的查看和排序】
简单快速查看实时资源使用情况可以用kubectl top指令:
1)查看node资源使用情况:
kubectl top node #资源实际使用情况
kubectl describe node #node的资源capacity,可用的资源情况(Allocatable),以及各pod已分配的(Allocated)资源配置情况(request和limit)
master-0:> kubectl top node W0421 13:48:16.185235 2602 top_node.go:119] Using json format to get metrics. NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% worker-0 518m 6% 10094Mi 63% master-0 515m 25% 2367Mi 61% |
上面两个node的cpu unit都等于500m左右,但是CPU使用率却不同,这是因为worker-0配置了8个vcpu(对应0.5/8=6%),而master-0配置了2个vcpu(对应0.5/2=25%)。
2)查看pod资源使用情况:
# Show metrics for all pods in the default namespace
kubectl top pod
# Show metrics for all pods in the given namespace
kubectl top pod --namespace=NAMESPACE
# Show metrics for a given pod and its containers
kubectl top pod POD_NAME --containers
# Show metrics for the pods defined by label name=myLabel
kubectl top pod -l name=myLabel --sort-by=''
//If non-empty, sort pods list using specified field. The field can be either 'cpu' or 'memory'.
kubectl top pod -A --sort-by=cpu
kubectl top pod -A --sort-by=memory
可以对node上pod的资源使用情况进行排序:
#按memory使用排序
kubectl get po -A -owide | grep <NODE_NAME> | awk '{print $1, $2}' | xargs -n2 kubectl top pod --no-headers -n $1 | sort --key 3 -nr | column -t
#按cpu使用排序
kubectl get po -A -owide | grep <NODE_NAME> | awk '{print $1, $2}' | xargs -n2 kubectl top pod --no-headers -n $1 | sort --key 2 -nr | column -t
//awk指令打印出namespace和pod信息;xargs指令用-n2表示输入pod和namespace两个参数;sort指令用key来选定memory或cpu列来排序,-nr表示按数字大小降序排列;column指令-t表示用空格做分隔符
【其它】
pod的使用量等于其所有业务容器的总和,不包括 pause 容器,值等于 cadvisr中的 container_memory_working_set_bytes 指标。
node 的值并不等于该 node 上所有 pod 值的总和,也不等于直接在机器上运行 top 或 free 看到的值。
Process ID (PID) limits表示kubelet限制pod消耗的PIDs数量。
资源使用情况的统计以及相关数据的来源,不一致等问题可以参见以下文档。
【参考】
- Resource Management for Pods and Containers | Kubernetes
- Assign CPU Resources to Containers and Pods | Kubernetes
- Assign Memory Resources to Containers and Pods | Kubernetes
- Process ID Limits And Reservations | Kubernetes
- kubectl top 命令解析 - 云+社区 - 腾讯云 (tencent.com)
- 一次关于k8s kubectl top 和 contained ps 不一致的问题探究 - 文章详情 (itpub.net)
- https://ops.tips/blog/why-top-inside-container-wrong-memory/
- How to read metrics `kubectl top nodes/pods`? · Issue #193 · kubernetes-sigs/metrics-server · GitHub
- https://www.ibm.com/support/pages/kubectl-top-pods-and-docker-stats-show-different-memory-statistics
- K8S 中虚拟机的资源管理与Pod调度 (iswbm.com)