Kubernetes 给容器和Pod分配内存资源

这篇教程指导如何给容器分配申请的内存和内存限制。咱们保证让容器得到足够的内存 资源,可是不容许它使用超过限制的资源。node

Before you begin

You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using Minikube.git

你的集群里每一个节点至少必须拥有300M的内存。github

这个教程里有几个步骤要求Heapster , 可是若是你没有Heapster的话,也能够完成大部分的实验,就算跳过这些Heapster 步骤,也不会有什么问题。docker

检查看Heapster服务是否运行,执行命令:api

kubectl get services --namespace=kube-system

若是Heapster服务正在运行,会有以下输出:curl

NAMESPACE    NAME      CLUSTER-IP    EXTERNAL-IP  PORT(S)  AGE
kube-system  heapster  10.11.240.9   <none>       80/TCP   6d

建立一个命名空间

建立命名空间,以便你在实验中建立的资源能够从集群的资源中隔离出来。ide

kubectl create namespace mem-example

配置内存申请和限制

给容器配置内存申请,只要在容器的配置文件里添加resources:requests就能够了。配置限制的话, 则是添加resources:limits。ui

本实验,咱们建立包含一个容器的Pod,这个容器申请100M的内存,而且内存限制设置为200M,下面 是配置文件:url

memory-request-limit.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: memory-demo
spec:
  containers:
  - name: memory-demo-ctr
    image: vish/stress
    resources:
      limits:
        memory: "200Mi"
      requests:
        memory: "100Mi"
    args:
    - -mem-total
    - 150Mi
    - -mem-alloc-size
    - 10Mi
    - -mem-alloc-sleep
    - 1s

在这个配置文件里,args代码段提供了容器所需的参数。-mem-total 150Mi告诉容器尝试申请150M 的内存。spa

建立Pod:

kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/memory-request-limit.yaml --namespace=mem-example

验证Pod的容器是否正常运行:

kubectl get pod memory-demo --namespace=mem-example

查看Pod的详细信息:

kubectl get pod memory-demo --output=yaml --namespace=mem-example

这个输出显示了Pod里的容器申请了100M的内存和200M的内存限制。

...
resources:
  limits:
    memory: 200Mi
  requests:
    memory: 100Mi
...

启动proxy以便咱们能够访问Heapster服务:

kubectl proxy

在另一个命令行窗口,从Heapster服务获取内存使用状况:

curl http://localhost:8001/api/v1/proxy/namespaces/kube-system/services/heapster/api/v1/model/namespaces/mem-example/pods/memory-demo/metrics/memory/usage

这个输出显示了Pod正在使用162,900,000字节的内存,大概就是150M。这很明显超过了申请 的100M,可是还没达到200M的限制。

{
 "timestamp": "2017-06-20T18:54:00Z",
 "value": 162856960
}

删除Pod:

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

超出容器的内存限制

只要节点有足够的内存资源,那容器就能够使用超过其申请的内存,可是不容许容器使用超过其限制的 资源。若是容器分配了超过限制的内存,这个容器将会被优先结束。若是容器持续使用超过限制的内存, 这个容器就会被终结。若是一个结束的容器容许重启,kubelet就会重启他,可是会出现其余类型的运行错误。

本实验,咱们建立一个Pod尝试分配超过其限制的内存,下面的这个Pod的配置文档,它申请50M的内存, 内存限制设置为100M。

memory-request-limit-2.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: memory-demo-2
spec:
  containers:
  - name: memory-demo-2-ctr
    image: vish/stress
    resources:
      requests:
        memory: 50Mi
      limits:
        memory: "100Mi"
    args:
    - -mem-total
    - 250Mi
    - -mem-alloc-size
    - 10Mi
    - -mem-alloc-sleep
    - 1s

在配置文件里的args段里,能够看到容器尝试分配250M的内存,超过了限制的100M。

建立Pod:

kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/memory-request-limit-2.yaml --namespace=mem-example

查看Pod的详细信息:

kubectl get pod memory-demo-2 --namespace=mem-example

这时候,容器可能会运行,也可能会被杀掉。若是容器还没被杀掉,重复以前的命令直至 你看到这个容器被杀掉:

NAME            READY     STATUS      RESTARTS   AGE
memory-demo-2   0/1       OOMKilled   1          24s

查看容器更详细的信息:

kubectl get pod memory-demo-2 --output=yaml --namespace=mem-example

这个输出显示了容器被杀掉由于超出了内存限制。

lastState:
   terminated:
     containerID: docker://65183c1877aaec2e8427bc95609cc52677a454b56fcb24340dbd22917c23b10f
     exitCode: 137
     finishedAt: 2017-06-20T20:52:19Z
     reason: OOMKilled
     startedAt: null

本实验里的容器能够自动重启,所以kubelet会再去启动它。输入多几回这个命令看看它是怎么 被杀掉又被启动的:

kubectl get pod memory-demo-2 --namespace=mem-example

这个输出显示了容器被杀掉,被启动,又被杀掉,又被启动的过程:

stevepe@sperry-1:~/steveperry-53.github.io$ kubectl get pod memory-demo-2 --namespace=mem-example
NAME            READY     STATUS      RESTARTS   AGE
memory-demo-2   0/1       OOMKilled   1          37s
stevepe@sperry-1:~/steveperry-53.github.io$ kubectl get pod memory-demo-2 --namespace=mem-example
NAME            READY     STATUS    RESTARTS   AGE
memory-demo-2   1/1       Running   2          40s

查看Pod的历史详细信息:

kubectl describe pod memory-demo-2 --namespace=mem-example

这个输出显示了Pod一直重复着被杀掉又被启动的过程:

... Normal  Created   Created container with id 66a3a20aa7980e61be4922780bf9d24d1a1d8b7395c09861225b0eba1b1f8511
... Warning BackOff   Back-off restarting failed container

查看集群里节点的详细信息:

kubectl describe nodes

输出里面记录了容器被杀掉是由于一个超出内存的情况出现:

Warning OOMKilling  Memory cgroup out of memory: Kill process 4481 (stress) score 1994 or sacrifice child

删除Pod:

kubectl delete pod memory-demo-2 --namespace=mem-example

配置超出节点能力范围的内存申请

内存的申请和限制是针对容器自己的,可是认为Pod也有容器的申请和限制是一个颇有帮助的想法。 Pod申请的内存就是Pod里容器申请的内存总和,相似的,Pod的内存限制就是Pod里全部容器的 内存限制的总和。

Pod的调度策略是基于请求的,只有当节点知足Pod的内存申请时,才会将Pod调度到合适的节点上。

在这个实验里,咱们建立一个申请超大内存的Pod,超过了集群里任何一个节点的可用内存资源。 这个容器申请了1000G的内存,这个应该会超过你集群里能提供的数量。

memory-request-limit-3.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: memory-demo-3
spec:
  containers:
  - name: memory-demo-3-ctr
    image: vish/stress
    resources:
      limits:
        memory: "1000Gi"
      requests:
        memory: "1000Gi"
    args:
    - -mem-total
    - 150Mi
    - -mem-alloc-size
    - 10Mi
    - -mem-alloc-sleep
    - 1s

建立Pod:

kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/memory-request-limit-3.yaml --namespace=mem-example

查看Pod的状态:

kubectl get pod memory-demo-3 --namespace=mem-example

输出显示Pod的状态是Pending,由于Pod不会被调度到任何节点,全部它会一直保持在Pending状态下。

kubectl get pod memory-demo-3 --namespace=mem-example
NAME            READY     STATUS    RESTARTS   AGE
memory-demo-3   0/1       Pending   0          25s

查看Pod的详细信息包括事件记录

kubectl describe pod memory-demo-3 --namespace=mem-example

这个输出显示容器不会被调度由于节点上没有足够的内存:

Events:
  ...  Reason            Message
       ------            -------
  ...  FailedScheduling  No nodes are available that match all of the following predicates:: Insufficient memory (3).

内存单位

内存资源是以字节为单位的,能够表示为纯整数或者固定的十进制数字,后缀能够是E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki.好比,下面几种写法表示相同的数值:alue:

128974848, 129e6, 129M , 123Mi

删除Pod:

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

若是不配置内存限制

若是不给容器配置内存限制,那下面的任意一种状况可能会出现:

  • 容器使用内存资源没有上限,容器能够使用当前节点上全部可用的内存资源。
  • 容器所运行的命名空间有默认内存限制,容器会自动继承默认的限制。集群管理员能够使用这个文档 LimitRange来配置默认的内存限制。

内存申请和限制的缘由

经过配置容器的内存申请和限制,你能够更加有效充分的使用集群里内存资源。配置较少的内存申请, 可让Pod跟任意被调度。设置超过内存申请的限制,能够达到如下效果:

  • Pod能够在负载高峰时更加充分利用内存。
  • 能够将Pod的内存使用限制在比较合理的范围。

清理

删除命名空间,这会顺便删除命名空间里的Pod。

kubectl delete namespace mem-example
相关文章
相关标签/搜索