---
title: 为容器和 Pod 分配内存资源
content_type: task
weight: 10
---

<!--
title: Assign Memory Resources to Containers and Pods
content_type: task
weight: 10
-->

<!-- overview -->

<!--
This page shows how to assign a memory *request* and a memory *limit* to a
Container. A Container is guaranteed to have as much memory as it requests,
but is not allowed to use more memory than its limit.
-->
此页面展示如何将内存 *请求* （request）和内存 *限制* （limit）分配给一个容器。
我们保障容器拥有它请求数量的内存，但不允许使用超过限制数量的内存。

## {{% heading "prerequisites" %}}

{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}

<!--
Each node in your cluster must have at least 300 MiB of memory.
-->
你集群中的每个节点必须拥有至少 300 MiB 的内存。

<!--
A few of the steps on this page require you to run the
[metrics-server](https://github.com/kubernetes-sigs/metrics-server)
service in your cluster. If you have the metrics-server
running, you can skip those steps.
-->
该页面上的一些步骤要求你在集群中运行
[metrics-server](https://github.com/kubernetes-sigs/metrics-server) 服务。
如果你已经有在运行中的 metrics-server，则可以跳过这些步骤。

<!--
If you are running Minikube, run the following command to enable the
metrics-server:
-->
如果你运行的是 Minikube，可以运行下面的命令启用 metrics-server：

```shell
minikube addons enable metrics-server
```

<!--
To see whether the metrics-server is running, or another provider of the resource metrics
API (`metrics.k8s.io`), run the following command:
-->
要查看 metrics-server 或资源指标 API (`metrics.k8s.io`) 是否已经运行，请运行以下命令：

```shell
kubectl get apiservices
```

<!--
If the resource metrics API is available, the output includes a
reference to `metrics.k8s.io`.
-->
如果资源指标 API 可用，则输出结果将包含对 `metrics.k8s.io` 的引用信息。

```
NAME
v1beta1.metrics.k8s.io
```

<!-- steps -->

<!--
## Create a namespace

Create a namespace so that the resources you create in this exercise are
isolated from the rest of your cluster.
-->
## 创建命名空间

创建一个命名空间，以便将本练习中创建的资源与集群的其余部分隔离。

```shell
kubectl create namespace mem-example
```

<!--
## Specify a memory request and a memory limit

To specify a memory request for a Container, include the `resources:requests` field
in the Container's resource manifest. To specify a memory limit, include `resources:limits`.

In this exercise, you create a Pod that has one Container. The Container has a memory
request of 100 MiB and a memory limit of 200 MiB. Here's the configuration file
for the Pod:
-->
## 指定内存请求和限制

要为容器指定内存请求，请在容器资源清单中包含 `resources：requests` 字段。
同理，要指定内存限制，请包含 `resources：limits`。

在本练习中，你将创建一个拥有一个容器的 Pod。
容器将会请求 100 MiB 内存，并且内存会被限制在 200 MiB 以内。
这是 Pod 的配置文件：

{{< codenew file="pods/resource/memory-request-limit.yaml" >}}

<!--
The `args` section in the configuration file provides arguments for the Container when it starts.
The `"--vm-bytes", "150M"` arguments tell the Container to attempt to allocate 150 MiB of memory.

Create the Pod:
-->
配置文件的 `args` 部分提供了容器启动时的参数。
`"--vm-bytes", "150M"` 参数告知容器尝试分配 150 MiB 内存。

开始创建 Pod：

```shell
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit.yaml --namespace=mem-example
```

<!--
Verify that the Pod Container is running:
-->
验证 Pod 中的容器是否已运行：

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

<!--
View detailed information about the Pod:
-->
查看 Pod 相关的详细信息：

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

<!--
The output shows that the one Container in the Pod has a memory request of 100 MiB
and a memory limit of 200 MiB.
-->
输出结果显示：该 Pod 中容器的内存请求为 100 MiB，内存限制为 200 MiB。

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

<!--
Run `kubectl top` to fetch the metrics for the pod:
-->
运行 `kubectl top` 命令，获取该 Pod 的指标数据：

```shell
kubectl top pod memory-demo --namespace=mem-example
```

<!--
The output shows that the Pod is using about 162,900,000 bytes of memory, which
is about 150 MiB. This is greater than the Pod's 100 MiB request, but within the
Pod's 200 MiB limit.
-->
输出结果显示：Pod 正在使用的内存大约为 162,900,000 字节，约为 150 MiB。
这大于 Pod 请求的 100 MiB，但在 Pod 限制的 200 MiB之内。

```
NAME                        CPU(cores)   MEMORY(bytes)
memory-demo                 <something>  162856960
```

<!--
Delete your Pod:
-->
删除 Pod：

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

<!--
## Exceed a Container's memory limit

A Container can exceed its memory request if the Node has memory available. But a Container
is not allowed to use more than its memory limit. If a Container allocates more memory than
its limit, the Container becomes a candidate for termination. If the Container continues to
consume memory beyond its limit, the Container is terminated. If a terminated Container can be
restarted, the kubelet restarts it, as with any other type of runtime failure.
-->
## 超过容器限制的内存

当节点拥有足够的可用内存时，容器可以使用其请求的内存。
但是，容器不允许使用超过其限制的内存。
如果容器分配的内存超过其限制，该容器会成为被终止的候选容器。
如果容器继续消耗超出其限制的内存，则终止容器。
如果终止的容器可以被重启，则 kubelet 会重新启动它，就像其他任何类型的运行时失败一样。

<!--
In this exercise, you create a Pod that attempts to allocate more memory than its limit.
Here is the configuration file for a Pod that has one Container with a
memory request of 50 MiB and a memory limit of 100 MiB:
-->
在本练习中，你将创建一个 Pod，尝试分配超出其限制的内存。
这是一个 Pod 的配置文件，其拥有一个容器，该容器的内存请求为 50 MiB，内存限制为 100 MiB：

{{< codenew file="pods/resource/memory-request-limit-2.yaml" >}}

<!--
In the `args` section of the configuration file, you can see that the Container
will attempt to allocate 250 MiB of memory, which is well above the 100 MiB limit.

Create the Pod:
-->
在配置文件的 `args` 部分中，你可以看到容器会尝试分配 250 MiB 内存，这远高于 100 MiB 的限制。

创建 Pod：

```shell
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-2.yaml --namespace=mem-example
```

<!--
View detailed information about the Pod:
-->
查看 Pod 相关的详细信息：

```shell
kubectl get pod memory-demo-2 --namespace=mem-example
```
<!--
At this point, the Container might be running or killed. Repeat the preceding command until the Container is killed:
-->
此时，容器可能正在运行或被杀死。重复前面的命令，直到容器被杀掉：

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

<!--
Get a more detailed view of the Container status:
-->
获取容器更详细的状态信息：

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

<!--
The output shows that the Container was killed because it is out of memory (OOM):
-->
输出结果显示：由于内存溢出（OOM），容器已被杀掉：

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

<!--
The Container in this exercise can be restarted, so the kubelet restarts it. Repeat
this command several times to see that the Container is repeatedly killed and restarted:
-->
本练习中的容器可以被重启，所以 kubelet 会重启它。
多次运行下面的命令，可以看到容器在反复的被杀死和重启：

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

<!--
The output shows that the Container is killed, restarted, killed again, restarted again, and so on:
-->
输出结果显示：容器被杀掉、重启、再杀掉、再重启……：

```
kubectl get pod memory-demo-2 --namespace=mem-example
NAME            READY     STATUS      RESTARTS   AGE
memory-demo-2   0/1       OOMKilled   1          37s
```
```

kubectl get pod memory-demo-2 --namespace=mem-example
NAME            READY     STATUS    RESTARTS   AGE
memory-demo-2   1/1       Running   2          40s
```

<!--
View detailed information about the Pod history:
-->
查看关于该 Pod 历史的详细信息：

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

<!--
The output shows that the Container starts and fails repeatedly:
-->
输出结果显示：该容器反复的在启动和失败：

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

<!--
View detailed information about your cluster's Nodes:
-->
查看关于集群节点的详细信息：

```
kubectl describe nodes
```

<!--
The output includes a record of the Container being killed because of an out-of-memory condition:
-->
输出结果包含了一条练习中的容器由于内存溢出而被杀掉的记录：

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

<!--
Delete your Pod:
-->
删除 Pod:

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

<!--
## Specify a memory request that is too big for your Nodes

Memory requests and limits are associated with Containers, but it is useful to think
of a Pod as having a memory request and limit. The memory request for the Pod is the
sum of the memory requests for all the Containers in the Pod. Likewise, the memory
limit for the Pod is the sum of the limits of all the Containers in the Pod.
-->
## 超过整个节点容量的内存

内存请求和限制是与容器关联的，但将 Pod 视为具有内存请求和限制，也是很有用的。
Pod 的内存请求是 Pod 中所有容器的内存请求之和。
同理，Pod 的内存限制是 Pod 中所有容器的内存限制之和。

<!--
Pod scheduling is based on requests. A Pod is scheduled to run on a Node only if the Node
has enough available memory to satisfy the Pod's memory request.

In this exercise, you create a Pod that has a memory request so big that it exceeds the
capacity of any Node in your cluster. Here is the configuration file for a Pod that has one
Container with a request for 1000 GiB of memory, which likely exceeds the capacity
of any Node in your cluster.
-->
Pod 的调度基于请求。只有当节点拥有足够满足 Pod 内存请求的内存时，才会将 Pod 调度至节点上运行。

在本练习中，你将创建一个 Pod，其内存请求超过了你集群中的任意一个节点所拥有的内存。
这是该 Pod 的配置文件，其拥有一个请求 1000 GiB 内存的容器，这应该超过了你集群中任何节点的容量。

{{< codenew file="pods/resource/memory-request-limit-3.yaml" >}}

<!--
Create the Pod:
-->
创建 Pod：

```shell
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-3.yaml --namespace=mem-example
```

<!--
View the Pod status:
-->
查看 Pod 状态：

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

<!--
The output shows that the Pod status is PENDING. That is, the Pod is not scheduled to run on any Node, and it will remain in the PENDING state indefinitely:
-->
输出结果显示：Pod 处于 PENDING 状态。
这意味着，该 Pod 没有被调度至任何节点上运行，并且它会无限期的保持该状态：

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

<!--
View detailed information about the Pod, including events:
-->
查看关于 Pod 的详细信息，包括事件：


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

<!--
The output shows that the Container cannot be scheduled because of insufficient memory on the Nodes:
-->
输出结果显示：由于节点内存不足，该容器无法被调度：

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

<!--
## Memory units

The memory resource is measured in bytes. You can express memory as a plain integer or a
fixed-point integer with one of these suffixes: E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki.
For example, the following represent approximately the same value:
-->
## 内存单位

内存资源的基本单位是字节（byte）。你可以使用这些后缀之一，将内存表示为
纯整数或定点整数：E、P、T、G、M、K、Ei、Pi、Ti、Gi、Mi、Ki。
例如，下面是一些近似相同的值：

```shell
128974848, 129e6, 129M , 123Mi
```

<!--
Delete your Pod:
-->
删除 Pod：

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

<!--
## If you do not specify a memory limit

If you do not specify a memory limit for a Container, one of the following situations applies:
-->
## 如果你没有指定内存限制

如果你没有为一个容器指定内存限制，则自动遵循以下情况之一：

<!--
* The Container has no upper bound on the amount of memory it uses. The Container
could use all of the memory available on the Node where it is running which in turn could invoke the OOM Killer. Further, in case of an OOM Kill, a container with no resource limits will have a greater chance of being killed.

* The Container is running in a namespace that has a default memory limit, and the
Container is automatically assigned the default limit. Cluster administrators can use a
[LimitRange](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#limitrange-v1-core)
to specify a default value for the memory limit.
-->
* 容器可无限制地使用内存。容器可以使用其所在节点所有的可用内存，
  进而可能导致该节点调用 OOM Killer。
  此外，如果发生 OOM Kill，没有资源限制的容器将被杀掉的可行性更大。

* 运行的容器所在命名空间有默认的内存限制，那么该容器会被自动分配默认限制。
  集群管理员可用使用 [LimitRange](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#limitrange-v1-core)
  来指定默认的内存限制。

<!--
## Motivation for memory requests and limits

By configuring memory requests and limits for the Containers that run in your
cluster, you can make efficient use of the memory resources available on your cluster's
Nodes. By keeping a Pod's memory request low, you give the Pod a good chance of being
scheduled. By having a memory limit that is greater than the memory request, you accomplish two things:
-->
## 内存请求和限制的目的

通过为集群中运行的容器配置内存请求和限制，你可以有效利用集群节点上可用的内存资源。
通过将 Pod 的内存请求保持在较低水平，你可以更好地安排 Pod 调度。
通过让内存限制大于内存请求，你可以完成两件事：

<!--
* The Pod can have bursts of activity where it makes use of memory that happens to be available.
* The amount of memory a Pod can use during a burst is limited to some reasonable amount.
-->
* Pod 可以进行一些突发活动，从而更好的利用可用内存。
* Pod 在突发活动期间，可使用的内存被限制为合理的数量。

<!--
## Clean up

Delete your namespace. This deletes all the Pods that you created for this task:
-->
## 清理

删除命名空间。下面的命令会删除你根据这个任务创建的所有 Pod：

```shell
kubectl delete namespace mem-example
```

## {{% heading "whatsnext" %}}

<!--
### For app developers

* [Assign CPU Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-cpu-resource/)

* [Configure Quality of Service for Pods](/docs/tasks/configure-pod-container/quality-service-pod/)
-->
### 应用开发者扩展阅读

* [为容器和 Pod 分配 CPU 资源](/zh/docs/tasks/configure-pod-container/assign-cpu-resource/)

* [配置 Pod 的服务质量](/zh/docs/tasks/configure-pod-container/quality-service-pod/)


<!--
### For cluster administrators

* [Configure Default Memory Requests and Limits for a Namespace](/docs/tasks/administer-cluster/manage-resources/memory-default-namespace/)

* [Configure Default CPU Requests and Limits for a Namespace](/docs/tasks/administer-cluster/manage-resources/cpu-default-namespace/)

* [Configure Minimum and Maximum Memory Constraints for a Namespace](/docs/tasks/administer-cluster/manage-resources/memory-constraint-namespace/)

* [Configure Minimum and Maximum CPU Constraints for a Namespace](/docs/tasks/administer-cluster/manage-resources/cpu-constraint-namespace/)

* [Configure Memory and CPU Quotas for a Namespace](/docs/tasks/administer-cluster/manage-resources/quota-memory-cpu-namespace/)

* [Configure a Pod Quota for a Namespace](/docs/tasks/administer-cluster/manage-resources/quota-pod-namespace/)

* [Configure Quotas for API Objects](/docs/tasks/administer-cluster/quota-api-object/)
-->
### 集群管理员扩展阅读

* [为命名空间配置默认的内存请求和限制](/zh/docs/tasks/administer-cluster/manage-resources/memory-default-namespace/)
* [为命名空间配置默认的 CPU 请求和限制](/zh/docs/tasks/administer-cluster/manage-resources/cpu-default-namespace/)
* [配置命名空间的最小和最大内存约束](/zh/docs/tasks/administer-cluster/manage-resources/memory-constraint-namespace/)
* [配置命名空间的最小和最大 CPU 约束](/zh/docs/tasks/administer-cluster/manage-resources/cpu-constraint-namespace/)
* [为命名空间配置内存和 CPU 配额](/zh/docs/tasks/administer-cluster/manage-resources/quota-memory-cpu-namespace/)
* [配置命名空间下 Pod 总数](/zh/docs/tasks/administer-cluster/manage-resources/quota-pod-namespace/)
* [配置 API 对象配额](/zh/docs/tasks/administer-cluster/quota-api-object/)

