资源约束

默认情况下,容器没有资源限制,并且可以使用尽可能多的 给定的资源。Docker 提供了 要控制容器可以使用多少内存或 CPU,请设置 runtime 命令的配置标志。本节提供详细信息 关于何时应设置此类限制以及设置这些限制可能产生的影响。docker run

其中许多功能要求您的内核支持 Linux 功能。自 检查支持,您可以使用 docker info 命令。如果功能 在内核中被禁用,您可能会在输出末尾看到一条警告,例如 以下内容:

WARNING: No swap limit support

请查阅操作系统的文档以启用它们。另请参阅 Docker Engine 故障排除指南 以了解更多信息。

记忆

了解内存不足的风险

重要的是,不要让正在运行的容器消耗过多的 主机的内存。在 Linux 主机上,如果内核检测到没有 足够的内存来执行重要的系统功能,它会抛出 、 或 ,并开始终止进程以释放 记忆。任何进程都会被终止,包括 Docker 和其他重要的 应用。如果错误,这可以有效地使整个系统停机 进程被终止。OOMEOut Of Memory Exception

Docker 尝试通过调整 Docker 守护进程,因此它比其他进程更不可能被杀死 在系统上。容器上的 OOM 优先级不会调整。这使得它更 单个容器被杀死的可能性比 Docker 守护进程的可能性更大 或其他要终止的系统进程。你不应该试图规避 这些保护措施通过手动设置为 Extreme Negative number 的 ID 值,或者通过在 容器。--oom-score-adj--oom-kill-disable

有关 Linux 内核的 OOM 管理的更多信息,请参阅内存不足管理

您可以通过以下方式降低因 OOME 而导致的系统不稳定风险:

  • 执行测试以了解应用程序的内存要求 在将其投入生产之前。
  • 确保您的应用程序仅在具有足够资源的主机上运行。
  • 限制容器可以使用的内存量,如下所述。
  • 在 Docker 主机上配置 swap 时要小心。Swap 慢于 内存,但可以提供缓冲区以防止系统内存耗尽。
  • 考虑将容器转换为服务,并使用服务级别约束 和节点标签,以确保应用程序仅在具有足够 记忆

限制容器对内存的访问

Docker 可以强制实施硬内存限制或软内存限制。

  • 硬限制允许容器使用不超过固定数量的内存。
  • 软限制允许容器根据需要使用尽可能多的内存,除非确定 满足条件,例如,当内核检测到内存不足或 主机。

其中一些选项在单独使用或多个 设置了一个选项。

这些选项中的大多数都采用正整数,后跟后缀 、 来表示字节、千字节、兆字节或千兆字节。bkmg

选择描述
-m--memory=容器可以使用的最大内存量。如果设置此选项,则允许的最小值为 (6 MB)。也就是说,您必须将该值设置为至少 6 MB。6m
--memory-swap*允许此容器交换到磁盘的内存量。请参阅 --memory-swap 详细信息
--memory-swappiness默认情况下,主机内核可以换出容器使用的一定比例的匿名页面。您可以设置为介于 0 和 100 之间的值,以调整此百分比。请参阅 --memory-swappiness 详细信息--memory-swappiness
--memory-reservation允许您指定一个软限制,该限制小于 Docker 在主机上检测到争用或内存不足时激活的软限制。如果使用 ,则必须将其设置为低于 ,才能优先。因为它是软限制,所以不能保证容器不会超过限制。--memory--memory-reservation--memory
--kernel-memory容器可以使用的最大内核内存量。允许的最小值为 。由于内核内存无法换出,因此内核内存不足的容器可能会阻止主机资源,这可能会对主机和其他容器产生副作用。请参阅 --kernel-memory 详细信息6m
--oom-kill-disable默认情况下,如果发生内存不足 (OOM) 错误,内核会杀死容器中的进程。要更改此行为,请使用该选项。仅在您也设置了 OOM 的容器上禁用 OOM Killer。如果未设置该标志,则主机可能会耗尽内存,内核可能需要终止主机系统的进程以释放内存。--oom-kill-disable-m/--memory-m

有关 cgroups 和内存的更多信息,请参阅文档 对于内存资源控制器

--memory-swap 详细信息

--memory-swap是一个修饰符标志,只有在 is 时才有意义 设置。使用 swap 允许容器将多余的内存需求写入磁盘 当容器用完了所有可用的 RAM 时。有一个 经常将内存交换到磁盘的应用程序的性能损失。--memory

其设置可能会产生复杂的效果:

  • 如果设置为正整数,则必须设置 both 和 。 表示 memory 和 swap 的 intent 和 swap 一起使用,并控制 non-swap 内存。因此,如果 和 ,则 容器可以使用 300M 的内存和 700M () 的交换。--memory-swap--memory--memory-swap--memory-swap--memory--memory="300m"--memory-swap="1g"1g - 300m

  • 如果设置为 ,则忽略该设置,值为 被视为 unset。--memory-swap0

  • 如果设置为与 相同的值,并且 为 设置为正整数,则容器无权访问 swap。 请参阅阻止容器使用 swap--memory-swap--memory--memory

  • 如果未设置且已设置,则容器可以使用 与设置一样多的 swap(如果主机容器具有 SWAP) 内存。例如,如果 和 是 未设置,则容器总共可以使用 600M 的内存和 swap。--memory-swap--memory--memory--memory="300m"--memory-swap

  • 如果显式设置为 ,则允许容器使用 无限制的掉期,最高可达主机系统上的可用金额。--memory-swap-1

  • 在容器内部,诸如 tools 之类的工具报告主机的可用交换时间,而不是容器内部的可用交换时间。不要依赖 或类似工具的输出来确定是否存在 swap。freefree

阻止容器使用 swap

如果 和 设置为相同的值,则这会阻止 containers 的 SWAP 一起使用。这是因为 是 可以使用的内存和 swap 的组合,而只是数量 可以使用的物理内存。--memory--memory-swap--memory-swap--memory

--memory-swappiness 详细信息

  • 值为 0 将关闭匿名页面交换。
  • 值 100 会将所有匿名页面设置为可交换页面。
  • 默认情况下,如果未设置 ,则值为 从主机继承。--memory-swappiness

--kernel-memory 详细信息

内核内存限制以分配给 一个容器。请考虑以下场景:

  • 无限内存,无限内核内存:这是默认设置 行为。
  • 无限内存,有限内核内存:当 所有 cgroups 所需的内存量大于 主机上实际存在的内存。您可以配置 kernel memory 永远不会超过主机上的可用内存, 需要更多内存的容器需要等待它。
  • 有限内存,无限内核内存:整体内存为 limited,但内核内存不是。
  • 有限的内存、有限的内核内存:限制用户和内核 内存可用于调试与内存相关的问题。如果容器 正在使用意外数量的任一类型的内存,则它会用完 的内存,而不会影响其他容器或主机。在 如果内核内存限制低于用户内存,则此设置 limit 时,内核内存不足会导致容器遇到 OOM 错误。如果内核内存限制高于用户内存 limit,则内核限制不会导致容器遇到 OOM。

启用内核内存限制时,主机会跟踪 “high water mark” 基于每个进程的统计信息,以便您可以跟踪哪些进程(在此 case、containers)正在使用过多的内存。这可以通过 在主机上查看。/proc/<PID>/status

中央处理器

默认情况下,每个容器对主机的 CPU 周期的访问是无限的。 您可以设置各种约束来限制给定容器对主机的访问 计算机的 CPU 周期。大多数用户使用和配置默认的 CFS 计划程序。您还可以 配置 Real-Time Scheduler

配置默认 CFS 计划程序

CFS 是用于正常 Linux 进程的 Linux 内核 CPU 调度程序。几个 运行时标志允许您配置对 CPU 资源的访问量, container has 的当您使用这些设置时,Docker 会修改 主机上容器的 cgroup。

选择描述
--cpus=<value>指定容器可以使用多少可用 CPU 资源。例如,如果主机有两个 CPU,并且您设置了 ,则容器最多保证一个半 CPU。这相当于设置 和 。--cpus="1.5"--cpu-period="100000"--cpu-quota="150000"
--cpu-period=<value>指定 CPU CFS 计划程序周期,该周期与 一起使用。默认为 100000 微秒(100 毫秒)。大多数用户不会更改默认值。对于大多数用例,是更方便的替代方案。--cpu-quota--cpus
--cpu-quota=<value>对容器施加 CPU CFS 配额。容器在受到限制之前限制的每微秒数。因此充当有效上限。对于大多数用例,是更方便的替代方案。--cpu-period--cpus
--cpuset-cpus限制容器可以使用的特定 CPU 或内核。如果您有多个 CPU,则容器可以使用的 CPU 的逗号分隔列表或连字符分隔的 CPU 范围。第一个 CPU 的编号为 0。有效值可能是 (使用第一个、第二个、第三个和第四个 CPU) 或 (使用第二个和第四个 CPU)。0-31,3
--cpu-shares将此标志设置为大于或小于默认值 1024 的值,以增加或减少容器的权重,并使其能够访问主机 CPU 周期的更大或更小比例。仅当 CPU 周期受到限制时,才会强制执行此操作。当有大量 CPU 周期可用时,所有容器都会根据需要使用 CPU。这样,这是一个软限制。 不会阻止容器在 Swarm 模式下调度。它为可用的 CPU 周期确定容器 CPU 资源的优先级。它不保证或保留任何特定的 CPU 访问权限。--cpu-shares

如果您有 1 个 CPU,则以下每个命令都保证容器处于 每秒最多 50% 的 CPU。

$ docker run -it --cpus=".5" ubuntu /bin/bash

这相当于手动指定 和--cpu-period--cpu-quota;

$ docker run -it --cpu-period=100000 --cpu-quota=50000 ubuntu /bin/bash

配置实时计划程序

您可以将容器配置为使用实时调度程序,用于 无法使用 CFS 计划程序。您需要确保主机的内核配置正确,然后才能配置 Docker 守护程序配置单个容器

警告

CPU 调度和优先级排序是高级内核级功能。最 用户不需要更改这些值的默认值。设置这些 值不正确可能会导致主机系统变得不稳定或不可用。

配置主机的内核

通过运行或检查 文件 的存在有关以下方面的指导 配置内核实时调度程序,请查阅 操作系统。CONFIG_RT_GROUP_SCHEDzcat /proc/config.gz | grep CONFIG_RT_GROUP_SCHED/sys/fs/cgroup/cpu.rt_runtime_us

配置 Docker 守护程序

要使用实时调度程序运行容器,请使用 将标志设置为保留的最大微秒数 对于每个运行时周期的实时任务。例如,如果默认时间段为 1000000 微秒 (1 秒),设置可确保 使用 Real-time Scheduler 的容器可以为每个 1000000 微秒的周期,至少留出 50000 微秒的可用时间 非实时任务。要在使用 的系统上永久使用此配置,请为服务创建一个 systemd 单元文件。例如, 请参阅有关如何配置守护程序以将代理与 systemd 单元文件一起使用的说明。--cpu-rt-runtime--cpu-rt-runtime=950000systemddocker

配置单个容器

您可以传递多个标志来控制容器的 CPU 优先级,当您 使用 启动容器。查阅您的操作系统的 documentation 或命令以获取有关适当值的信息。docker runulimit

选择描述
--cap-add=sys_nice授予容器功能,允许容器提高进程值、设置实时计划策略、设置 CPU 关联性和其他操作。CAP_SYS_NICEnice
--cpu-rt-runtime=<value>容器可以在 Docker 守护程序的实时调度程序周期内以实时优先级运行的最大微秒数。您还需要 flag。--cap-add=sys_nice
--ulimit rtprio=<value>容器允许的最大实时优先级。您还需要 flag。--cap-add=sys_nice

以下示例命令在容器上设置这三个标志中的每一个。debian:jessie

$ docker run -it \
    --cpu-rt-runtime=950000 \
    --ulimit rtprio=99 \
    --cap-add=sys_nice \
    debian:jessie

如果内核或 Docker 守护程序配置不正确,则会发生错误。

图形处理器

访问 NVIDIA GPU

先决条件

访问官方 NVIDIA 驱动程序页面以下载并安装正确的驱动程序。完成后重新启动系统 这样做了。

验证您的 GPU 是否正在运行且可访问。

安装 nvidia-container-toolkit

按照官方 NVIDIA Container Toolkit 安装说明进行操作。

公开 GPU 以供使用

在启动容器以访问 GPU 资源时包含该标志。 指定要使用的 GPU 数量。例如:--gpus

$ docker run -it --rm --gpus all ubuntu nvidia-smi

公开所有可用的 GPU 并返回类似于以下内容的结果:

+-------------------------------------------------------------------------------+
| NVIDIA-SMI 384.130            	Driver Version: 384.130               	|
|-------------------------------+----------------------+------------------------+
| GPU  Name 	   Persistence-M| Bus-Id    	Disp.A | Volatile Uncorr. ECC   |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M.   |
|===============================+======================+========================|
|   0  GRID K520       	Off  | 00000000:00:03.0 Off |                  N/A      |
| N/A   36C	P0    39W / 125W |  	0MiB /  4036MiB |      0%  	Default |
+-------------------------------+----------------------+------------------------+
+-------------------------------------------------------------------------------+
| Processes:                                                       GPU Memory   |
|  GPU   	PID   Type   Process name                         	Usage  	|
|===============================================================================|
|  No running processes found                                                   |
+-------------------------------------------------------------------------------+

使用该选项指定 GPU。例如:device

$ docker run -it --rm --gpus device=GPU-3a23c669-1f69-c64e-cf85-44e9b07e7a2a ubuntu nvidia-smi

公开该特定 GPU。

$ docker run -it --rm --gpus '"device=0,2"' ubuntu nvidia-smi

公开第一个和第三个 GPU。

注意

NVIDIA GPU 只能由运行单个引擎的系统访问。

设置 NVIDIA 功能

您可以手动设置功能。例如,在 Ubuntu 上,您可以运行 以后:

$ docker run --gpus 'all,capabilities=utility' --rm ubuntu nvidia-smi

这将启用驱动程序功能,该功能将工具添加到 容器。utilitynvidia-smi

功能以及其他配置可以通过以下方式在镜像中设置 环境变量。有关有效变量的更多信息,请参阅 nvidia-container-toolkit 文档。可以在 Dockerfile 中设置这些变量。

您还可以使用 CUDA 镜像来自动设置这些变量。请参阅 官方 CUDA 镜像 NGC 目录页面。