资源约束
默认情况下,容器没有资源限制,并且可以使用尽可能多的
给定的资源。Docker 提供了
要控制容器可以使用多少内存或 CPU,请设置 runtime
命令的配置标志。本节提供详细信息
关于何时应设置此类限制以及设置这些限制可能产生的影响。docker run
其中许多功能要求您的内核支持 Linux 功能。自
检查支持,您可以使用 docker info
命令。如果功能
在内核中被禁用,您可能会在输出末尾看到一条警告,例如
以下内容:
WARNING: No swap limit support
请查阅操作系统的文档以启用它们。另请参阅 Docker Engine 故障排除指南 以了解更多信息。
记忆
了解内存不足的风险
重要的是,不要让正在运行的容器消耗过多的
主机的内存。在 Linux 主机上,如果内核检测到没有
足够的内存来执行重要的系统功能,它会抛出 、 或 ,并开始终止进程以释放
记忆。任何进程都会被终止,包括 Docker 和其他重要的
应用。如果错误,这可以有效地使整个系统停机
进程被终止。OOME
Out Of Memory Exception
Docker 尝试通过调整
Docker 守护进程,因此它比其他进程更不可能被杀死
在系统上。容器上的 OOM 优先级不会调整。这使得它更
单个容器被杀死的可能性比 Docker 守护进程的可能性更大
或其他要终止的系统进程。你不应该试图规避
这些保护措施通过手动设置为 Extreme Negative
number 的 ID 值,或者通过在
容器。--oom-score-adj
--oom-kill-disable
有关 Linux 内核的 OOM 管理的更多信息,请参阅内存不足管理。
您可以通过以下方式降低因 OOME 而导致的系统不稳定风险:
- 执行测试以了解应用程序的内存要求 在将其投入生产之前。
- 确保您的应用程序仅在具有足够资源的主机上运行。
- 限制容器可以使用的内存量,如下所述。
- 在 Docker 主机上配置 swap 时要小心。Swap 慢于 内存,但可以提供缓冲区以防止系统内存耗尽。
- 考虑将容器转换为服务,并使用服务级别约束 和节点标签,以确保应用程序仅在具有足够 记忆
限制容器对内存的访问
Docker 可以强制实施硬内存限制或软内存限制。
- 硬限制允许容器使用不超过固定数量的内存。
- 软限制允许容器根据需要使用尽可能多的内存,除非确定 满足条件,例如,当内核检测到内存不足或 主机。
其中一些选项在单独使用或多个 设置了一个选项。
这些选项中的大多数都采用正整数,后跟后缀 、 来表示字节、千字节、兆字节或千兆字节。b
k
m
g
选择 | 描述 |
---|---|
-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-swap
0
如果设置为与 相同的值,并且 为 设置为正整数,则容器无权访问 swap。 请参阅阻止容器使用 swap。
--memory-swap
--memory
--memory
如果未设置且已设置,则容器可以使用 与设置一样多的 swap(如果主机容器具有 SWAP) 内存。例如,如果 和 是 未设置,则容器总共可以使用 600M 的内存和 swap。
--memory-swap
--memory
--memory
--memory="300m"
--memory-swap
如果显式设置为 ,则允许容器使用 无限制的掉期,最高可达主机系统上的可用金额。
--memory-swap
-1
在容器内部,诸如 tools 之类的工具报告主机的可用交换时间,而不是容器内部的可用交换时间。不要依赖 或类似工具的输出来确定是否存在 swap。
free
free
阻止容器使用 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-3 1,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_SCHED
zcat /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=950000
systemd
docker
配置单个容器
您可以传递多个标志来控制容器的 CPU 优先级,当您
使用 启动容器。查阅您的操作系统的
documentation 或命令以获取有关适当值的信息。docker run
ulimit
选择 | 描述 |
---|---|
--cap-add=sys_nice | 授予容器功能,允许容器提高进程值、设置实时计划策略、设置 CPU 关联性和其他操作。CAP_SYS_NICE nice |
--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
这将启用驱动程序功能,该功能将工具添加到
容器。utility
nvidia-smi
功能以及其他配置可以通过以下方式在镜像中设置 环境变量。有关有效变量的更多信息,请参阅 nvidia-container-toolkit 文档。可以在 Dockerfile 中设置这些变量。
您还可以使用 CUDA 镜像来自动设置这些变量。请参阅 官方 CUDA 镜像 NGC 目录页面。