kubernetes之定义容器和Pod的内存资源
简介
此文主要讲述如何定以容器的内存请求数和内存限制数。一个容器的运行必须保证内存大于容器请求的内存数,但是不能超过容器的限制数。
备注:此文档参考官方文档,并加以自己的理解。如有误导性的内容,请批评指正。
创建命名空间
# kubectl create namespace mem-example
定义内存请求数和内存限制数
创建一个Pod,其中args
块中的--vm-bytes
参数请求150MiB
的内存。文件名:memory-request-limit.yaml
apiVersion: v1
kind: Pod
metadata:
name: memory-demo
namespace: mem-example
spec:
containers:
- name: memory-demo-ctr
image: polinux/stress
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
# kubectl apply -f /root/k8s-example/pods/memory-request-limit.yaml --namespace=mem-example
确认Pod 容器正在运行
# kubectl get pod memory-demo --output=yaml --namespace=mem-example
查看Pod详情
# kubectl get pod memory-demo --output=yaml --namespace=mem-example
从结果可以看出,改Pod内存请求数200Mi
,限制数100Mi
...
resources:
limits:
memory: 200Mi
requests:
memory: 100Mi
...
执行kubectl top
命令,查看当前Pod好用了CPU和内存
# kubectl top pod memory-demo --namespace=mem-example
备注:执行kubectl top
首先确保安装metrics server
,若没有安装可参考如下,需保证能下载k8s.gcr.io/metrics-server-amd64:v0.3.1
镜像:
# git clone https://github.com/kodekloudhub/kubernetes-metrics-server.git
# kubectl create -f kubernetes-metrics-server/
从kubectl top
结果可以看出,当前Pod使用了150Mi
字节内存,大于该Pod的请求值100MiB
,小于该Pod的限制值200MiB
:
NAME CPU(cores) MEMORY(bytes)
memory-demo 138m 150Mi
删除该Pod
# kubectl delete pod memory-demo --namespace=mem-example
超过容器的内存限制
如果容器有更多的内存可以分配,则容器可以超过自定义的请求内存。如果容器需要的内存超过自定义的内存限制,则容器将会成为被终止的候选对象。如果容器持续消耗的内存大于自定义的内存限制,则容器被强制停止运行。容器被终止运行后,kubelet会重新启动改容器。
创建一个分配的内存超过内存限制的Pod,如下配置,请求内存50MiB
,限制内存100MiB
。文件名:memory-request-limit-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: memory-demo-2
namespace: mem-example
spec:
containers:
- name: memory-demo-2-ctr
image: polinux/stress
resources:
requests:
memory: "50Mi"
limits:
memory: "100Mi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"]
# kubectl apply -f /root/k8s-example/pods/memory-request-limit-2.yaml --namespace=mem-example
# kubectl get pod memory-demo-2 --namespace=mem-example
从结果可以看出,由于内存溢出,导致Pod直接被kill掉了。
# kubectl get pod memory-demo-2 --namespace=mem-example NAME READY STATUS RESTARTS AGE
memory-demo-2 0/1 OOMKilled 1 4s
查看Pod详情
# kubectl get pod memory-demo-2 --output=yaml --namespace=mem-example
从结果可以看出,最后的状态由于OOMKilled
即Out Of Memory
导致容器被kill
lastState:
terminated:
containerID: docker://0d4d5580e28df2a936f28cbef8580ac21c1014e1fad2814e28cfa28417bd3bb0
exitCode: 1
finishedAt: "2020-01-10T00:39:55Z"
reason: OOMKilled
startedAt: "2020-01-10T00:39:55Z"
删除Pod
# kubectl delete pod memory-demo-2 --namespace=mem-example
定义内存请求大于节点内存的容器
内存请求数、内存限制数和容器相关联,因此,对于Pod来说,设置合适的内存请求和限制非常有必要。Pod的内存请求数等于Pod内所有容器的内存请求数总和。Pod的内存限制数就是Pod内所有容器内存限制数总和。
Pod的调度是基于请求调度的。一个Pod运行于哪个Pod上取决于改Node是否能满足该Pod的存请求。
在下面的联系中,创建一个内存请求远大于节点内存总数的Pod,下面的实例中定义的Pod内存请求数为1000GiB
。文件名:memory-request-limit-3.yaml
apiVersion: v1
kind: Pod
metadata:
name: memory-demo-3
namespace: mem-example
spec:
containers:
- name: memory-demo-3-ctr
image: polinux/stress
resources:
limits:
memory: "1000Gi"
requests:
memory: "1000Gi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
# kubectl apply -f /root/k8s-example/pods/memory-request-limit-3.yaml --namespace=mem-example
查看容Pod状态
# kubectl get pod memory-demo-3 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-3 0/1 Pending 0 15s
查看Pod资源详情
# kubectl describe pod memory-demo-3 --namespace=mem-example
从结果看,7个node节点没有足够的内存,由于我的是3个master节点高可用、4个node节点的k8s集群
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling <unknown> default-scheduler 0/7 nodes are available: 7 Insufficient memory.
删除名称空间
内存单位
内存资源用bytes
字节衡量。单位有E
、P
、T
、G
、M
、K
、Ei
、Pi
、Ti
、Gi
、Mi
、Ki
。例如如下表达式均为同一个值
128974848, 129e6, 129M , 123Mi
删除Pod资源
# kubectl delete pod memory-demo-3 --namespace=mem-example
没有定义内存限制
如果没有定义容器的内存限制,则适用以下情况之一:
- 容器对其使用的内存量没有上限。容器可以使用其正在运行的节点上的所有可用内存,进而可以调用OOM Killer。此外,如果发生OOM Kill,则没有资源限制的容器将有更大的机会被杀死。
- 运行在有默认内存限制的namespace中的容器,系统会自动为容器分配默认限制。集群管理员可以通过
LimitRange
定义内存限制的值。
内存请求限制的原因
通过在集群中配置容器的内存请求和内存限制,可以合理的使用集群中node节点的内存资源。如果保证Pod的内存请求在合理值范围内,则该Pod可以在集群中被合理的调度到合适的node节点上。