原文
## 磁盘
--blkio-weight uint16 Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)
--blkio-weight-device list Block IO weight (relative device weight) (default [])
## CPU
--cpus decimal Number of CPUs
--cpu-period int Limit CPU CFS (Completely Fair Scheduler) period
--cpu-quota int Limit CPU CFS (Completely Fair Scheduler) quota
--cpu-rt-period int Limit CPU real-time period in microseconds
--cpu-rt-runtime int Limit CPU real-time runtime in microseconds
--cpu-shares int CPU shares (relative weight)
--cpuset-cpus string CPUs in which to allow execution (0-3, 0,1)
--cpuset-mems string MEMs in which to allow execution (0-3, 0,1)
## 内存
--memory bytes Memory limit
--memory-reservation bytes Memory soft limit
--memory-swap bytes Swap limit equal to memory plus swap: '-1' to enable unlimited swap
--memory-swappiness int Tune container memory swappiness (0 to 100) (default -1)
磁盘读写优先级
--blkio-weight: 全局磁盘读写优先级
--blkio-weight
控制容器在磁盘 I/O 方面的优先级。
- 当宿主机上有多个容器同时尝试进行磁盘读写操作时,此相对权重决定了每个容器能够获得的磁盘 I/O 资源。
- 此参数的取值范围为 10 ~ 1000 之间的整数。默认为 0,表示不对磁盘 I/O 进行限制。相对权重越大,容器在磁盘 I/O 方面的优先级越高。
- 此参数不能完全决定磁盘 I/O 优先级,容器实际获得的磁盘 I/O 资源还受其他容器的影响。
- 此参数仅适用于支持 CFS (Completely Fair Scheduler, 完全公平调度程序) 的 Linux 内核版本。
示例:
docker run --name "container_A" --blkio-weight 600 ubuntu
docker run --name "container_B" --blkio-weight 300 ubuntu
--blkio-weight-device: 执行磁盘读写优先级
--blkio-weight-device
用于为特定的设备(如磁盘或者分区)设置容器的 I/O 权重。
- 取代全局设置(
--blkio-weight
),更精细地控制容器在不同设备上的 I/O 操作的优先级 - 如果希望数据库在存储其数据的设备上高性能运行时,可以调高此参数
- 如果希望某些关键容器在某些设备上高性能运行时,可以调高此参数
- 同
--blkio-weight
一样,取值范围为 10 ~ 1000,仅支持 CFS
示例:
docker run --name db_container --blkio-weight-device="/dev/nvme0n1:800" mysql
CPU 资源控制
--cpu-period & --cpu-quota: CPU使用率
--cpu-period
用于配置 CPU CFS 周期的时间长度,单位为微秒,默认为 100000 微秒(100毫秒)。
通常与 --cpu-quota
一起使用,用来限制容器的 CPU 使用资源。
--cpu-quota
定义了容器在指定周期内可以使用的 CPU 时间的配额(CPU 资源是按照计算时间计算的)。
一般不需要手动设置这两个参数的值,通过设置另一个参数 --cpus
,Docker 会自动计算和设置这两个参数。
示例:
docker run --cpu-period=100000 --cpu-quota=25000 ubuntu
--cpus: CPU使用率
相对于 --cpu-period
和 --cpu-quota
,--cpus
更加直观(事实上它就是前者的简化版本),它直接指定了容器可以使用了 CPU 核心数量。
- 如果宿主机上的 CPU 资源紧张,
--cpus
设置不当可能导致容器无法获得所需的 CPU 资源,导致性能下降 --cpus
同样依赖于 Linux 内核的 CFS 功能--cpus
可以是小数,表示使用部分核心
示例:
docker run --cpus=2.5 ubuntu
--cpu-rt-period & --cpu-rt-runtime: 实时调度
--cpu-rt-period
的默认值一般为 1000000 微秒(1 秒)。
这两个参数的描述类似于 --cpu-period
和 --cpu-quota
,但它们针对的是不同的 CPU 调度机制,使用场景和功能有所不同。
前者针对 实时调度器(RTS, Real-Time Scheduler),后者针对普通调度器(CFS, Completely Fair Scheduler)。
🍉 RTS 和 CFS 的区别?
RTS 和 CFS 是 Linux 内核中用于处理任务调度的两种不同的机制,他们的主要区别在于 任务优先级 和 响应时间 的要求上。
实时调度器(RTS) | 完全公平调度器(CFS) | |
---|---|---|
优先级 | 根据任务的优先级对任务进行调度,实时任务通常具有较高的优先级,能够立即得到处理 | 根据任务的虚拟运行时间来调度任务,确保所有任务都能公平的获得 CPU 时间 |
响应时间 | 响应时间可预测 | 提供公平的 CPU 时间分配,一个任务执行完一个周期后会被放到队列末尾重新排队,响应时间取决于队列长度,不可预测 |
调度策略 | 提供多种调度策略,例如 FIFO(先进先出,栈)、RR(时间片轮转)等 | 使用 红黑树 来管理任务的调度,确保公平! |
使用场景 | 适用于需要严格时间保证的场景,例如实时控制系统、音频处理、网络路由器、医疗设备等 | 适用于需要公平分配 CPU 时间的场景:一般计算任务,如服务器、桌面系统、嵌入式系统等,这些任务对公平性要求较高,对响应时间没那么严格 |
配置和管理 | 通过设置 调度策略 和 任务优先级 来管理,可以使用 chrt 命令或系统调用来设置任务的实时优先级 | 通过设置任务的 nice 值来调整任务的优先级:nice 值越高,优先级越低 |
内核接口 | 使用 SCHED_FIFO , SCHED_RR 等实时调度策略 | 使用 SCHED_NORMAL , SCHED_BATCH 等非实时策略 |
🍉 容器已经设置了 CFS,为什么还需要设置 RTS?
普通的任务 CFS 已经够用了,但是如果我们的容器中有对执行时间有严格要求的任务时,CFS 无法满足我们的需求,因为它是公平分配 CPU 时间的,而我们需要这些特殊任务总是优先执行,但是又不能一直霸占 CPU,不然其他任务就假死了。这个时候就需要 RTS 来确保这些任务能够获得更高的优先级和可预测的响应时间。RTS 能够更加精细控制任务的调度。
🍉 容器内部如何为任务设置实时调度策略?
使用 chrt
命令:
chrt -f 99 some_command
但是容器默认是没有这个权限的,需要在启动容器时添加 --cap-add
参数授予容器设置任务实时策略的权限:
docker run --cap-add=sys_nice -it --rm ubuntu /bin/bash
🍉 --cap-add=sys_nice 是什么意思?
--cap-add
用于授予容器特定的 Linux 能力(capabilities),sys_nice 是 Linux 内核提供的一种能力,它允许进程(这里指容器)
- 提高自身或者另一个任务的优先级(
chrt
命令) - 设置任务的调度策略(如实时调度策略
SCHED_FIFO
,SCHED_RR
等,sched_setscheduler
,setpriority
等命令) - 调整任务的 nice 值(CFS 调度,
renice
命令)
Linux 能力将传统的 root 权限拆分成多个独立的单元,每个单元(能力)可以单独启用和禁用。
🍉 设置了 --cpu-rt-period 还需要添加 --cap-add=sys_nice 吗?
这两个选项没有必然的关联:
--cpu-rt-period
和--cpu-rt-runtime
用于设定 CPU 执行时间--cap-add=sys_nice
用于授予容器调整任务调度策略和优先级的能力
--cpu-shares
CPU 资源紧张时容器需要共享 CPU 资源,共享资源就涉及到优先级的问题,此参数就是用来控制容器在共享 CPU 资源时的相对优先级的。
当发生竞争时,不同容器可以获得的 CPU 时间比例由它们的 CPU 份额(--cpu-shares
)决定。例如下面两个容器在竞争时,db2 将获得两倍于 db1 的 CPU 时间。-cpu-shared
默认值为 1024。
docker run -d --name db1 --cpu-shares=512 mariadb
docker run -d --name db2 --cpu-shares=1024 mariadb
适用场景:
- 希望某些容器在 CPU 资源紧张是能够获得更多的 CPU 时间
- 确保不会因为其他任务的资源抢占影响关键任务的性能
- 多容器环境中根据任务的特性分配 CPU 份额以平衡系统的整体性能
注意点:
--cpu-shares
是一个相对值,容器最终能获得多少 CPU 份额由所有容器共同决定--cpu-shares
只在 CPU 资源紧张时才发挥作用
--cpuset-cpus
在多核系统中,将容器绑定到指定的物理 CPU 上。
任务可能在不同的 CPU 核心之间迁移,可能导致缓存未命中和性能下降,通过将容器固定在指定的 CPU 上,可以提高容器的性能,适用于需要高吞吐量或者低延迟的任务。
docker run -it --cpuset-cpus="1,2" ubuntu /bin/bash
docker run -it --cpuset-cpus="0-3" ubuntu /bin/bash
内存资源控制
--cpuset-mems
指定容器可以访问的内存节点。
对于高性能计算任务或者低延迟实时任务,将容器绑定到特定的内存节点可以减少内存访问延迟。
docker run -it --cpuset-mems="1,2" ubuntu /bin/bash
docker run -it --cpuset-mems="0-3" ubuntu /bin/bash
🍉 如何获取系统中可用的内存节点?
lscpu
$ lscpu
...
NUMA:
NUMA node(s): 1
NUMA node0 CPU(s): 0-15
...
NUMA node(s) 行为内存节点个数。
numactl
$ sudo apt install numactl
$ numactl --hardware
available: 1 nodes (0)
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
node 0 size: 32027 MB
node 0 free: 11680 MB
node distances:
node 0
0: 10
available 行为内存节点个数。
numastat
$ numastat
node0
numa_hit 324174572
numa_miss 0
numa_foreign 0
interleave_hit 1706
local_node 324174572
other_node 0
有几列就有几个内存节点。
🍉 NUMA 是什么意思?
NUMA 是 Non-Uniform Memory Access 的缩写,意为“非一致性内存访问”,用于在高性能服务器和工作站中优化 多核处理器 的内存访问性能。
在传统的系统中,所有处理器共享一个全局内存空间,这在内存资源充足的情况下是最优、最简单、最易于管理的方案。但是一旦任务负载过大,尤其是在高性能计算服务器中,内存资源会变得非常紧张,多核处理器使用共享内存的竞争造成的延迟问题极大影响任务性能。一个解决思路就是将内存划分成多个子区域,每个处理器主要使用分配给自己的区域,有需要时也可以访问其他区域(但是延迟会高很多),这就是 NUMA 架构。
综上,NUMA 将内存划分成多个小区域并与处理器绑定,以提高多核系统的任务执行性能。
--memory
限制容器可以使用的最大物理内存。
容器在运行时如果超过这个限制,会触发 OOM (Out Of Memory) 被强行终止。
参数值支持带单位:512
, 512b
, 512k
, 512m
, 512g
, ...
虽然 --oom-kill-disable
参数可以禁用 OOM 终止行为,但是不建议使用该选项。
docker run -d --name web_server --memory="512m" nginx
docker run -d --name database --memory="1g" mariadb
--memory-reservation
与 --memory
一样用来限制容器可使用的最大内存,但是是软限制。
在内存充足时,容器可使用内存可以超过此限制;但是在内存紧张时,Docker 会尝试降低该容器的内存到预设值之下。
该参数优先级低于 --memory
。同时设置时,只有此参数值小于 --memory
的参数值,软限制才能发挥作用。
docker run -it --memory="1g" --memory-reservation="512m" ubuntu /bin/bash
--memory-swap
设置容器可以使用的虚拟内存(物理内存+交换空间)总量。
交换空间是当物理内存(RAM)不足时,用于存放内存数据的磁盘空间。
如果只设置了 --memory
而没有设置 --memory-swap
,Docker 会将 --memory-swap
设置为 --memory
的两倍(交换空间=物理内存)。
将 --memory-swap
设置为 -1,容器可以无限制的使用交换空间。
将 --memory-swap
设置为与 --memory
相同的值,禁用交换空间。
--memory-swappiness
控制容器内进程使用交换空间的倾向性。
swappiness 是一个内核参数,取值范围为 0 ~ 100,值越大,操作系统越倾向于使用交换空间;值越小,操作系统越倾向于保留物理内存。
减小 swappiness 的值,可以减少交换空间的使用,提高内存访问速度,提升容器性能。
# 尽可能多的使用交换空间
docker run -it --memory-swappiness=100 ubuntu /bin/bash
# 完全禁用交换空间
docker run -it --memory-swappiness=0 ubuntu /bin/bash
🍉 如何查看系统默认的 swappiness?
$ sysctl vm.swappiness
vm.swappiness = 60
$ cat /proc/sys/vm/swappiness
60
评论区