聊一聊应用的资源限制(cgroup篇)

背景

自从 docker 这一类容器化工具出来之后,我们想对应用做一些资源限制的时候已经是非常的简单了,在启动容器的时候加一些限制的参数就可以了。

在不同的操作系统下面,资源限制这一块还是有一些不一样的地方。linux 一般就是 cgroup v1 或 cgroup v2,windows 则是 kernel 32。

在 dotnet/crank 中,对这两种操作系统都有实现,下面主要来看看Linux的一些实现细节。

Linux 下的资源限制

crank 是依赖于 cgroup-tools,所以需要在操作系统上面先进行安装才能使用。

由于 cgroup v1 和 v2 之间有一些差异,所以它的实现也是根据不同版本的语义进行了区分。

区分 v1 v2 用的是下面的命令

stat -fc %T /sys/fs/cgroup/

# cgroup v1 返回 tmpfs
# cgroup v2 返回 cgroup2fs

创建 cgroup 和 执行命令在 v1 和 v2 是一样的,所以这一块不需要区分。

cgcreate -g memory,cpu,cpuset:benchmark-1-1

# 具体的限制语义设置。。。

cgexec -g memory,cpu,cpuset:benchmark-1-1 /tmp/publised/webapp

cgcreate 就是用来创建 cgroup 的一个命令,可以看到 crank 这块主要是针对了 memroy,cpu,cpuset 这三个做了限制。

下面就分别看看这三个限制的具体内容。

内存

先来看看 v1 的内存限制:

# 限制 1G 的内存
cgset -r memory.limit_in_bytes=1073741824 benchmark-1-1

# 不限制内存
cgset -r memory.limit_in_bytes=-1 benchmark-1-1

v2 的语义发生了变化,与 memory.limit_in_bytes 相对应的是 memory.max,所以与之对应的是

cgset -r memory.max=1073741824 benchmark-1-1

# 不限制内存
cgset -r memory.max=max benchmark-1-1

参考:

  • https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/memory.html

  • https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html#memory-interface-files

cpu

先来看看 v1 cpu 的限制:

The amount of CPU available for the process, e.g., "0.5". For a 12 cores machines this value would result in 50% out of 1200% total available CPU time.

# 限制 50% 的 cpu,其中 cfs_period_us = 10000 是为了和docekr对齐
cgset -r cpu.cfs_period_us=100000 benchmark-1-1
cgset -r cpu.cfs_quota_us=50000 benchmark-1-1

# 不限制 cpu
cgset -r cpu.cfs_quota_us=-1 benchmark-1-1

v2 这边的语义变化的还是比较大的,把 cfs_period_us 和 cfs_quota_us 整合到 max 上面了。

cgset -r cpu.max="50000 100000" benchmark-1-1
cgset -r cpu.max="max 100000" benchmark-1-1

参考:

  • https://docs.kernel.org/scheduler/sched-bwc.html

  • https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html#cpu-interface-files

cpuset

crank 这块用的的关于cpuset 的语义没有不一样的地方,都是 cpuset.cpuscpuset.mems

# 限制使用 0和1 两个cpu
cgset -r cpuset.cpus=0-1 benchmark-1-1
cgset -r cpuset.mems=0 benchmark-1-1

########

# 不限制cpu,8个cpu都可以使用 (8c机器)
cgset -r cpuset.cpus=0-7 benchmark-1-1
cgset -r cpuset.mems=0 benchmark-1-1

有一个需要注意的是, cpuset.mems 的取值问题,在 v1 时,是从 /sys/fs/cgroup/cpuset/cpuset.mems 中取, v2 则是 /sys/fs/cgroup/{controller}/cpuset.mems/sys/fs/cgroup/{controller}/cpuset.mems.effective

这个主要是由于 v1 和 v2 的层级发生了变化。

cpuset 还可以在 NUMA 架构的机器上面发挥一定的作用。

参考:

  • https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/cpusets.html

  • https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html#cpuset-interface-files

来看一个 crank 具体的例子:

crank --config ./hello.benchmarks.yml --profile local --scenario hello \
          --application.cpuSet "0" \
          --application.cpuLimitRatio 0.5 \
          --application.memoryLimitInBytes 1073741824

Agent 的具体输出

[18:53:09 INF] [/] chmod +x /tmp/benchmarks-agent/benchmarks-server-1/ancl3ltc.4a1/src/hello/published/hello
[18:53:09 INF] [/] cgcreate -g memory,cpu,cpuset:benchmarks-1-4
[18:53:09 INF] [/] cgset -r memory.max=1073741824 benchmarks-1-4
[18:53:09 INF] [/] cgset -r cpu.max="50000 100000" benchmarks-1-4
[18:53:09 INF] [/] cgset -r cpuset.cpus=0 benchmarks-1-4
[18:53:09 INF] [/] cgset -r cpuset.mems=0 benchmarks-1-4
[18:53:09 INF] [/] Invoking executable: cgexec
[18:53:09 INF] [/]   Arguments: -g memory,cpu,cpuset:benchmarks-1-4 /tmp/benchmarks-agent/benchmarks-server-1/ancl3ltc.4a1/src/hello/published/hello
[18:53:09 INF] [/]   Working directory: /tmp/benchmarks-agent/benchmarks-server-1/ancl3ltc.4a1/src/hello/published

除了上面提到的语义之外,还有硬盘,网络相关的也可以进行限制。

如果在没有安装 cgroup-tools 的前提下,需要通过 echo xx -> yyy 的方式来设置。

下面再来看2个 docker 限制内存和cpu的例子。

docker 示例

这里启动两个 nginx 容器,一个限制 200M 内存和 50000 的 cpu-quota 以及 100000 的 cpu-period,另一个不做任何限制。

# 8614aabd3e57  v1
# 0a7e61dd556f  v2
docker run -d -m 200M --cpu-quota=50000 --cpu-period=100000 --name ng-cg0 nginx
# 118bc903caee  v1
# ce356350e956  v2
docker run -d --name ng-cg1 nginx

然后分别看看 cgroup 的限制情况

cgroup v1

先是做了限制的容器:

cd /sys/fs/cgroup/memory/docker
cat 8614aabd3e57*****/memory.limit_in_bytes
# output is 209715200

cd /sys/fs/cgroup/cpu/docker
cat 8614aabd3e57*****/cpu.cfs_quota_us 
# output is 50000
cat 8614aabd3e57*****/cpu.cfs_period_us 
# output is 100000

然后是没做限制的容器:

cd /sys/fs/cgroup/memory/docker
cat 118bc903caee*****/memory.limit_in_bytes 
# output is 9223372036854771712

cd /sys/fs/cgroup/cpu/docker
cat 118bc903caee*****/cpu.cfs_quota_us 
# output is -1
cat 118bc903caee*****/cpu.cfs_period_us 
# output is 100000

cgroup v1 的 cgroup 控制文件在 /sys/fs/cgroup/<控制器>/docker/<longid>//sys/fs/cgroup/<控制器>/system.slice/docker-<longid>.scope/ 下面。

cgroup v2

先是做了限制的容器:

cd /sys/fs/cgroup/system.slice/docker-0a7e61dd556f*****.scope
cat memory.max
# output is 209715200

cat cpu.max
# output is 50000 100000

然后是没做限制的容器:

cd /sys/fs/cgroup/system.slice/docker-ce356350e956*****.scope
cat memory.max
# output is max

cat cpu.max
# output is max 100000

cgroup v1 的 cgroup 控制文件在 /sys/fs/cgroup/system.slice/docker-<longid>.scope//sys/fs/cgroup/docker/<longid/> 下面。

可以看到是做了不同版本的区分已经符合 cgroup 预期行为的。

写在最后

这篇是从 dotnet/crank 中用到 cgroup 知识的一个小结,也衍生出了一些 cgroup 相关的知识。

下面 3 个文件就是实现的具体细节,想了解详细的可以参考下面的链接:

https://github.com/dotnet/crank/blob/main/src/Microsoft.Crank.Agent/CGroup.cs https://github.com/dotnet/crank/blob/main/src/Microsoft.Crank.Agent/CGroupV1.cs https://github.com/dotnet/crank/blob/main/src/Microsoft.Crank.Agent/CGroupV2.cs

后面有空再写写 windows 下面的资源限制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值