资源约束
默认情况下,容器没有资源限制,可以使用尽可能多的
给定的资源。Docker 提供了
要控制容器可以使用多少内存或 CPU,请设置 runtime
配置标志的docker run
命令。本节提供详细信息
关于何时应设置此类限制以及设置这些限制可能产生的影响。
其中许多功能要求您的内核支持 Linux 功能。自
检查支持,您可以使用docker info
命令。如果功能
在内核中被禁用,您可能会在输出末尾看到一条警告,例如
以下内容:
WARNING: No swap limit support
请查阅作系统的文档以启用它们。另请参阅 Docker Engine 故障排除指南 以了解更多信息。
记忆
了解内存不足的风险
重要的是,不要让正在运行的容器消耗过多的
主机的内存。在 Linux 主机上,如果内核检测到没有
足够的内存来执行重要的系统功能,它会抛出一个OOME
或Out Of Memory Exception
,并开始终止进程以释放
记忆。任何进程都会被终止,包括 Docker 和其他重要的
应用。如果错误,这可以有效地使整个系统停机
进程被终止。
Docker 尝试通过调整
Docker 守护进程,因此它比其他进程更不可能被杀死
在系统上。容器上的 OOM 优先级不会调整。这使得它更
单个容器被杀死的可能性比 Docker 守护进程的可能性更大
或其他要终止的系统进程。你不应该试图规避
这些保护措施通过手动设置--oom-score-adj
到极度消极
number 上,或者通过设置--oom-kill-disable
在
容器。
有关 Linux 内核的 OOM 管理的更多信息,请参阅内存不足管理。
您可以通过以下方式降低因 OOME 而导致的系统不稳定风险:
- 执行测试以了解应用程序的内存要求 在将其投入生产之前。
- 确保您的应用程序仅在具有足够资源的主机上运行。
- 限制容器可以使用的内存量,如下所述。
- 在 Docker 主机上配置 swap 时要小心。Swap 慢于 内存,但可以提供缓冲区以防止系统内存耗尽。
- 考虑将容器转换为服务,并使用服务级别约束 和节点标签,以确保应用程序仅在具有足够 记忆
限制容器对内存的访问
Docker 可以强制实施硬内存限制或软内存限制。
- 硬限制允许容器使用不超过固定数量的内存。
- 软限制允许容器根据需要使用尽可能多的内存,除非确定 满足条件,例如,当内核检测到内存不足或 主机。
其中一些选项在单独使用或多个 设置了一个选项。
这些选项中的大多数都采用正整数,后跟后缀b
,k
,m
,g
来指示字节、千字节、兆字节或千兆字节。
选择 | 描述 |
---|---|
-m 或--memory= | 容器可以使用的最大内存量。如果设置此选项,则允许的最小值为6m (6 兆字节)。也就是说,您必须将该值设置为至少 6 MB。 |
--memory-swap * | 允许此容器交换到磁盘的内存量。看--memory-swap 详. |
--memory-swappiness | 默认情况下,主机内核可以换出容器使用的一定比例的匿名页面。您可以设置--memory-swappiness 设置为介于 0 和 100 之间的值,以调整此百分比。看--memory-swappiness 详. |
--memory-reservation | 允许您指定小于--memory 当 Docker 在主机上检测到争用或内存不足时,将激活该策略。如果您使用--memory-reservation ,它必须设置为低于--memory 让它优先。因为它是软限制,所以不能保证容器不会超过限制。 |
--kernel-memory | 容器可以使用的最大内核内存量。允许的最小值为6m .由于内核内存无法换出,因此内核内存不足的容器可能会阻止主机资源,这可能会对主机和其他容器产生副作用。看--kernel-memory 详. |
--oom-kill-disable | 默认情况下,如果发生内存不足 (OOM) 错误,内核会杀死容器中的进程。要更改此行为,请使用--oom-kill-disable 选择。仅在您还设置了-m/--memory 选择。如果-m 标志,则主机可能会耗尽内存,内核可能需要终止主机系统的进程以释放内存。 |
有关 cgroups 和内存的更多信息,请参阅文档 对于内存资源控制器。
--memory-swap
详
--memory-swap
是一个修饰符标志,仅当--memory
也是
设置。使用 swap 允许容器将多余的内存需求写入磁盘
当容器用完了所有可用的 RAM 时。有一个
经常将内存交换到磁盘的应用程序的性能损失。
其设置可能会产生复杂的效果:
如果
--memory-swap
设置为正整数,则--memory
和--memory-swap
必须设置。--memory-swap
表示 memory 和 swap 的--memory
控制 使用者 non-swap 内存。因此,如果--memory="300m"
和--memory-swap="1g"
这 容器可以使用 300M 的内存和 700M (1g - 300m
) 交换。如果
--memory-swap
设置为0
,则忽略该设置,值为 被视为 unset。如果
--memory-swap
设置为与--memory
和--memory
是 设置为正整数,则容器无权访问 swap。 请参阅阻止容器使用 swap。如果
--memory-swap
未设置,并且--memory
设置,容器可以使用 与--memory
设置中,如果主机容器具有 SWAP 内存。例如,如果--memory="300m"
和--memory-swap
是 未设置,则容器总共可以使用 600M 的内存和 swap。如果
--memory-swap
显式设置为-1
,则允许容器使用 无限制的掉期,最高可达主机系统上的可用金额。在容器内部,像
free
报告主机的可用交换时间,而不是容器内的可用交换时间。不要依赖free
或类似工具来确定是否存在 SWAP 的 SWAP 文件。
阻止容器使用 swap
如果--memory
和--memory-swap
设置为相同的值,这会阻止
containers 的 SWAP 一起使用。这是因为--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,并且您将--cpus="1.5" ,则容器最多保证一个半 CPU。这相当于设置--cpu-period="100000" 和--cpu-quota="150000" . |
--cpu-period=<value> | 指定 CPU CFS 计划程序周期,该周期与--cpu-quota .默认为 100000 微秒(100 毫秒)。大多数用户不会更改默认值。对于大多数用例,--cpus 是一种更方便的选择。 |
--cpu-quota=<value> | 对容器施加 CPU CFS 配额。每个--cpu-period 容器仅限于 Throttled 之前。因此充当有效上限。对于大多数用例,--cpus 是一种更方便的选择。 |
--cpuset-cpus | 限制容器可以使用的特定 CPU 或内核。如果您有多个 CPU,则容器可以使用的 CPU 的逗号分隔列表或连字符分隔的 CPU 范围。第一个 CPU 的编号为 0。有效值可能是0-3 (使用第一个、第二个、第三个和第四个 CPU)或1,3 (使用第二个和第四个 CPU)。 |
--cpu-shares | 将此标志设置为大于或小于默认值 1024 的值,以增加或减少容器的权重,并使其能够访问主机 CPU 周期的更大或更小比例。仅当 CPU 周期受到限制时,才会强制执行此作。当有大量 CPU 周期可用时,所有容器都会根据需要使用 CPU。这样,这是一个软限制。--cpu-shares 不会阻止容器在 Swarm 模式下调度。它为可用的 CPU 周期确定容器 CPU 资源的优先级。它不保证或保留任何特定的 CPU 访问权限。 |
如果您有 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
在 Linux 内核中启用,方法是运行zcat /proc/config.gz | grep CONFIG_RT_GROUP_SCHED
或通过检查
文件的存在/sys/fs/cgroup/cpu.rt_runtime_us
.有关以下方面的指导
配置内核实时调度程序,请查阅
操作系统。
配置 Docker 守护程序
要使用实时调度程序运行容器,请使用
这--cpu-rt-runtime
标志设置为保留的最大微秒数
对于每个运行时周期的实时任务。例如,如果默认时间段为
1000000 微秒 (1 秒),设置--cpu-rt-runtime=950000
确保
使用 Real-time Scheduler 的容器可以为每个
1000000 微秒的周期,至少留出 50000 微秒的可用时间
非实时任务。在使用systemd
中,为docker
服务。例如,
请参阅有关如何配置守护程序以将代理与 systemd 单元文件一起使用的说明。
配置单个容器
您可以传递多个标志来控制容器的 CPU 优先级,当您
使用 启动 Containerdocker run
.查阅您的作系统的
documentation 或ulimit
命令以获取有关适当值的信息。
选择 | 描述 |
---|---|
--cap-add=sys_nice | 向容器授予CAP_SYS_NICE 功能,它允许容器引发进程nice 值、设置实时调度策略、设置 CPU 关联性和其他作。 |
--cpu-rt-runtime=<value> | 容器可以在 Docker 守护程序的实时调度程序周期内以实时优先级运行的最大微秒数。您还需要--cap-add=sys_nice 旗。 |
--ulimit rtprio=<value> | 容器允许的最大实时优先级。您还需要--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 以供使用
包括--gpus
标志。
指定要使用的 GPU 数量。例如:
$ 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 |
+-------------------------------------------------------------------------------+
使用device
选项以指定 GPU。例如:
$ 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
driver 功能,该 driver 功能将nvidia-smi
工具设置为
容器。
功能以及其他配置可以通过以下方式在镜像中设置 环境变量。有关有效变量的更多信息,请参阅 nvidia-container-toolkit 文档。可以在 Dockerfile 中设置这些变量。
您还可以使用 CUDA 镜像来自动设置这些变量。请参阅 官方 CUDA 镜像 NGC 目录页面。