默认情况下,容器没有资源限制,可以使用主机内核调度程序允许的尽可能多的给定资源。
不允许容器消耗宿主机太多的内存是非常重要的。在 Linux 主机上,如果内核检测到没有足够的内存来执行重要的系统功能,它会抛出 OOME
或 Out of Memory
异常,并开始终止进程以释放内存。任何进程都会被杀死,包括 Docker 和其他重要的应用程序。如果杀错进程,可能导致整个系统瘫痪。
Docker 通过调整 Docker daemon 上的 OOM 优先级来降低这些风险,以便它比系统上的其他进程更不可能被杀死。容器上的 OOM 优先级未调整,这使得单个容器被杀死的可能性比 Docker daemon 或其他系统进程被杀死的可能性更大。你不应试图通过在 daemon 或容器上手动设置 --oom-score-adj
到极端负数,或通过在容器上设置 --oom-kill-disable
来绕过这些安全措施。
有关Linux内核的OOM管理的更多信息,查看 Out of Memory Management
可以通过以下方式降低 OOME 导致系统不稳定的风险:
下述选项中的大多数采用正整数,后跟 b
/ k
/ m
/ g
的后缀,代表单位:字节 / 千字节 / 兆字节 / 千兆字节。
选项 | 描述 |
---|---|
-m or --memory= | 容器可使用的最大内存, 最小值是 4m |
--memory-swap* | 允许此容器交换到磁盘的内存量 |
--memory-swappiness | 默认情况下,主机内核可以交换容器使用的匿名页面的百分比,可以设置 --memory-swappiness 的值区间为 0 - 100 |
--memory-reservation | 指定小于 --memory 的软限制,当 Docker 检测到主机上的争用或内存不足时会激活该限制. 如果使用 --memory-reservation,则必须将其设置为低于 --memory 才能使其优先。因为它是软限制,所以不保证容器不超过限制。 |
--kernel-memory | 容器可以使用的最大内核内存量, 最小值是 4m,因为内核内存无法换出,缺乏内核内存的容器可能会阻塞主机资源,这会对主机和其他容器产生副作用 |
--oom-kill-disable | 默认情况, 如果发生内存不足(OOM)错误,内核会终止容器中的进程。 要改变这种行为,使用 --oom-kill-disable 选项。 仅在已设置 -m / -memory 选项的容器上禁用 OOM killer,如果未设置 -m 标志,则主机可能会耗尽内存,内核可能需要终止主机系统的进程才能释放内存 |
有关 cgroup 和内存的更多信息,查看 Memory Resource Controller
关于 --memory-swap
--memory-swap
是一个修饰符标志,只有在设置了 --memory
时才有意义。使用 swap 允许容器在容器耗尽所有可用的 RAM 时,将多余的内存需求写入磁盘。对于经常将内存交换到磁盘的应用程序,性能会受到影响。
它的设置会产生复杂的影响:
--memory-swap
设置为正整数,则必须设置 --memory
和 --memory-swap
。 --memory-swap
表示可以使用的 memory 和 swap 总量, --memory
控制 no-swap 的用量。 所以,如果设置 --memory="300m"
和 --memory-swap="1g"
, 容器可以使用 300m memory 和 700m (1g - 300m
) swap。--memory-swap
设置为 0
, 该设置被忽略,该值被视为未设置。--memory-swap
的值等于 --memory
的值, 并且 --memory
设置为正整数, 则容器无权访问 swap。这是因为 --memory-swap
是可以使用组合的 Memory 和 Swap,而 --memory
只是可以使用的 Memory。--memory-swap
不设置, 并且 --memory
设置了值, 容器可以使用 --memory
两倍的 Swap(如果主机容器配置了 Swap)。示例: 设置 --memory="300m"
并且不设置 --memory-swap
,容器可以使用 300m memory 和 600m swap。--memory-swap
设置为 -1
,允许容器无限制使用 Swap。free
等工具报告的是主机的可用 Swap,而不是容器内可用的。不要依赖于 free
或类似工具的输出来确定是否存在 Swap。关于 --memory-swappiness
--memory-swappiness
, 该值从主机继承。关于 --kernel-memory
内核内存限制是就分配给容器的总内存而言的,考虑一下方案:
当你打开任何内核内存限制时,主机会根据每个进程跟踪 “高水位线” 统计信息,因此您可以跟踪哪些进程(在本例中为容器)正在使用多余的内存。通过查看主机上的 /proc/<PID>/status
,可以在每个进程中看到这一点。
默认情况下,每个容器对主机 CPU 周期的访问权限是不受限制的,您可以设置各种约束来限制给定容器访问主机的 CPU 周期。大多数用户使用和配置 默认 CFS 调度程序。在 Docker 1.13 及更高版本中,还可以配置实时调度程序。
CFS 是用于普通 Linux 进程的 Linux 内核 CPU 调度程序。通过以下设置,可以控制容器的 CPU 资源访问量,使用这些设置时,Docker 会修改主机上容器的 cgroup 的设置。
选项 | 描述 |
---|---|
--cpus=<value> | 指定容器可以使用的 CPU 资源量。例如,如果主机有两个CPU并且,设置 --cpus="1.5",则容器最多可以使用 1.5 个 CPU,这相当于设置 --cpu-period="100000" 和 --cpu-quota="150000"。可在Docker 1.13及更高版本中使用。 |
--cpu-period=<value> | 指定 CPU CFS 调度程序周期,该周期与 --cpu-quota 一起使用,默认为100微秒。大多数用户不会更改默认设置,如果使用Docker 1.13 或更高版本,请改用 --cpus。 |
--cpu-quota=<value> | 对容器施加 CPU CFS 配额,在受限制之前容器限制为每个 --cpu-period 的微秒数,作为有效上限。如果使用Docker 1.13 或更高版本,请改用 --cpus。 |
--cpuset-cpus | 限制容器可以使用的特定 CPU 或核心。如果主机有多个CPU,则容器可以使用的以, 分 隔的列表或 - 分隔的 CPU 范围。第一个CPU 编号为 0,有效值可能是 0-3(使用第一个、第二个、第三个和第四个CPU)或 1,3(使用第二个和第四个CPU)。 |
--cpu-shares | 将此值设置为大于或小于默认值 1024,以增加或减少容器的权重,并使其可以访问主机的 CPU 周期的占较大或较小比例。仅在 CPU 周期受限时才会强制执行此操作。当有足够的 CPU 周期时,所有容器都会根据需要使用尽可能多的 CPU。这是一个软限制,--cpu-shares 不会阻止在群集模式下的容器调度。它为可用的 CPU 周期优先考虑容器 CPU 资源。它不保证或保留任何特定的 CPU 访问权限。 |
示例:如果你有 1 个 CPU,则以下每个命令都会保证容器每秒最多占 CPU 的 50%。
Docker 1.13 或更高版本:
docker run -it --cpus=".5" ubuntu /bin/bash
Docker 1.12 或更低版本:
docker run -it --cpu-period=100000 --cpu-quota=50000 ubuntu /bin/bash
In Docker 1.13 and higher, you can configure your container to use the realtime scheduler,
在 Docker 1.13 或更高版本,你可以配置容器使用实时调度程序。在配置 Docker daemon 或配置容器之前,需要确保正确配置主机的内核。
警告:CPU 调度和优先级是高级内核级功能,大多数用户不需要从默认值更改这些值,错误地设置这些值可能会导致主机系统变得不稳定或无法使用。
配置主机机器的内核
通过运行 zcat /proc/config.gz | grep CONFIG_RT_GROUP_SCHED
验证是否在 Linux 内核中启用了 CONFIG_RT_GROUP_SCHED
,或者检查是否存在文件 /sys/fs/cgroup/cpu.rt_runtime_us
。有关配置内核实时调度程序的教程,请参阅操作系统的文档。
配置DOCKER DAEMON
要使用实时调度程序运行容器,请运行 Docker daemon,并将 --cpu-rt-runtime
设置为每个运行时间段为实时任务保留的最大微秒数。例如,默认周期为 1000000 微秒(1秒),设置 --cpu-rt-runtime=950000
可确保使用实时调度程序的容器每 1000000 微秒可运行 950000 微秒,并保留至少 50000 微秒用于非实时任务。要在使用 systemd 的系统上永久保留此配置,请参阅 Control and configure Docker with systemd。
配置个别容器
使用 docker run
启动容器时,可以传递多个参数来控制容器的 CPU 优先级。有关适当值的信息,请参阅操作系统的文档或 ulimit
命令。
选项 | 描述 |
---|---|
--cap-add=sys_nice | 授予容器 CAP_SYS_NICE 功能,该功能允许容器引发进程良好值,设置实时调度策略,设置 CPU 亲和性以及其他操作。 |
--cpu-rt-runtime=<value> | 容器可以在 Docker 守护程序的实时调度程序周期内以实时优先级运行的最大微秒数,需要设置 --cap-add=sys_nice 。 |
--ulimit rtprio=<value> | 容器允许的最大实时优先级,需要 --cap-add=sys_nice 标志。 |
示例:
docker run --it --cpu-rt-runtime=950000 \
--ulimit rtprio=99 \
--cap-add=sys_nice \
debian:jessie
如果未正确配置内核或 Docker Daemon,则会发生错误。
Limit a container's resources Linux 使用 free 查看系统内存信息 CentOS 查看系统 CPU 信息