关于 cgroup
cgroup 有现在(2020)有 2 个版本, 尽管大部分公司还在使用 v1, 不过 v2 更好. 官方文档:
https://www.kernel.org/doc/Documentation/cgroup-v1/
https://www.kernel.org/doc/Documentation/cgroup-v2.txt
下面的内容都是基于 v1:
如何查看一个进程的 cgroup 的 group name?
$ pgrep java #找到我要查看的进程号
23850
# cat /proc/23850/cgroup #这个进程的 cgroup 名字
11:devices:/docker/dfa566d
10:pids:/docker/dfa566d
9:blkio:/docker/dfa566d
8:hugetlb:/docker/dfa566d
7:freezer:/docker/dfa566d
6:cpuset:/docker/dfa566d
5:memory:/docker/dfa566d
4:cpuacct,cpu:/docker/dfa566d
3:net_prio,net_cls:/docker/dfa566d
2:perf_event:/docker/dfa566d
1:name=systemd:/docker/dfa566d
$ mount | grep cgroup # 查看 cgroup 文件系统挂载的路径 默认是 /sys/fs/cgroup/
# 可以看到 /sys/fs/group 是 tmpfs 文件系统, 每个具体的层级树 根都是 cgroup 文件系统
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
(rw,nosuid,nodev,noexec,relatime,net_prio,net_cls)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
...
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
$ ls -lah /sys/fs/cgroup/cpu/docker/dfa566d/ #该进程的 cgroup 文件
-rw-r--r-- 1 root root 0 Aug 13 05:05 cgroup.clone_children
--w--w--w- 1 root root 0 Aug 13 05:05 cgroup.event_control
-rw-r--r-- 1 root root 0 Aug 13 05:07 cgroup.procs
-r--r--r-- 1 root root 0 Aug 13 05:05 cpuacct.stat
-rw-r--r-- 1 root root 0 Aug 13 05:05 cpuacct.usage
-r--r--r-- 1 root root 0 Aug 13 05:05 cpuacct.usage_percpu
-rw-r--r-- 1 root root 0 Aug 13 05:05 cpu.cfs_period_us
-rw-r--r-- 1 root root 0 Aug 13 05:05 cpu.cfs_quota_us
-rw-r--r-- 1 root root 0 Aug 13 05:05 cpu.rt_period_us
-rw-r--r-- 1 root root 0 Aug 13 05:05 cpu.rt_runtime_us
-rw-r--r-- 1 root root 0 Aug 13 05:05 cpu.shares
-r--r--r-- 1 root root 0 Aug 13 05:05 cpu.stat
-rw-r--r-- 1 root root 0 Aug 13 05:05 notify_on_release
-rw-r--r-- 1 root root 0 Aug 13 05:05 tasksCPU:
https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt
https://engineering.squarespace.com/blog/2017/understanding-linux-container-scheduling
cpu usage soft限制: 使用 cpu.shares 文件. 它基于各 group 之间的比重, 默认比重是 1024. 如果某个 group 的进程使用量达不到自己的比重, 就会把自己剩余的 CPU 使用时间放到一个公共的 pool, 其它使用量超过自己使用量的比重的 group 里面的进程都可以到这个 pool 去取用. 当公共 pool 里面没有可用的时候, 就按照竞争CPU 的各个 group 的比重去分配. 所以如果竞争不激烈, 这个值意义不大, 比重低的group 里面的进程也有可能使用最多的 CPU(其他 group 都有剩余).
cpu usage hard 限制: 使用 cpu.cfs_period_us & cpu.cfs_quota_us 配合. period 代表一段时间, 单位是微妙,默认值是 100ms (100000), 最大值是 1s (1000000). quota 代表在 period 期间该 group 可以使用的量, 最小可能值是 1ms(1000). -1 代表不限制. 在多 CPU core 情况下, quota 的值可能比 period 大, 代表可能是用 n 个 CPU, 比如 period 是 100ms, quota 是 300ms 代表可以使用 3 个 CPU 的 core 的量.
内存 Memory
https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt
内存的限额使用 memory.limit_in_bytes 限制, 当前的使用量可以查看 memory.usage_in_bytes.
/sys/fs/cgroup/memory/docker/dfa566d/
文件系统
在 host 上面可以通过 /proc/<pid>/root/ 访问 container 里面的文件
或者可以通过 docker cp 命令来 copy 文件
在 container 里面访问 host 文件要在 container 里面加 volume 的方式
cgroup v2
相比于 cgroup v1 的多个层级树(hierarchy), v2只有一个层级树.
cgroup 主要有2部份组成: core 和 controller. core 主要负责层级树. controller 主要负责资源的分配,统计和限制.
每个进程仅且仅属于层级树的某个group. 该进程下的所有线程都属于这个group.
某个group 可以选择enable/disable 某个controller, 这会影响它和它的子树.
挂载 cgroup v2
mount -t cgroup2 none /sys/fs/group/cgroup 文件
跟 cgroup v1 一样, 使用 : 分开. 最前面的数字表示第一个层级树(hierarchy), 由于 v2 只有一个层级树, 所以默认是0, cgroup v2 中间两个冒号的中间是空, 因为它使用同一个层级树, 所有的controller 都包含. 最后一个是相对的cgroup 文件地址. 在下面的例子里, 在宿主机里的绝对地址是: /sys/fs/cgroup/system.slice/docker-45e75dc7f97abf18a972fc0b12190e3a59ca77263d7677fd1ca077132dce6229.scope.
$ cat /proc/5369/cgroup
0::/system.slice/docker-45e75dc7f97abf18a972fc0b12190e3a59ca77263d7677fd1ca077132dce6229.scopecgroup 控制器文件
$ ls -lah
-r--r--r-- 1 root root 0 May 12 18:05 cgroup.controllers
-r--r--r-- 1 root root 0 May 12 18:05 cgroup.events
-rw-r--r-- 1 root root 0 May 12 18:05 cgroup.freeze
--w------- 1 root root 0 May 13 07:58 cgroup.kill
-rw-r--r-- 1 root root 0 May 13 07:58 cgroup.max.depth
-rw-r--r-- 1 root root 0 May 13 07:58 cgroup.max.descendants
-rw-r--r-- 1 root root 0 May 13 07:58 cgroup.procs
-r--r--r-- 1 root root 0 May 13 07:58 cgroup.stat
-rw-r--r-- 1 root root 0 May 12 18:05 cgroup.subtree_control
-rw-r--r-- 1 root root 0 May 13 07:58 cgroup.threads
-rw-r--r-- 1 root root 0 May 12 18:05 cgroup.type