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

从结果可以看出,最后的状态由于OOMKilledOut 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字节衡量。单位有EPTGMKEiPiTiGiMiKi。例如如下表达式均为同一个值

128974848, 129e6, 129M , 123Mi

删除Pod资源

# kubectl delete pod memory-demo-3 --namespace=mem-example

没有定义内存限制

如果没有定义容器的内存限制,则适用以下情况之一:

  • 容器对其使用的内存量没有上限。容器可以使用其正在运行的节点上的所有可用内存,进而可以调用OOM Killer。此外,如果发生OOM Kill,则没有资源限制的容器将有更大的机会被杀死。
  • 运行在有默认内存限制的namespace中的容器,系统会自动为容器分配默认限制。集群管理员可以通过LimitRange定义内存限制的值。

内存请求限制的原因

通过在集群中配置容器的内存请求和内存限制,可以合理的使用集群中node节点的内存资源。如果保证Pod的内存请求在合理值范围内,则该Pod可以在集群中被合理的调度到合适的node节点上。

posted @ 2020-01-19 16:39  McSiberiaWolf  阅读(1821)  评论(0编辑  收藏  举报