- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章详解Docker 容器使用 cgroups 限制资源使用由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
上一篇文章将到 Docker 容器使用 linux namespace 来隔离其运行环境,使得容器中的进程看起来就像爱一个独立环境中运行一样。但是,光有运行环境隔离还不够,因为这些进程还是可以不受限制地使用系统资源,比如网络、磁盘、CPU以及内存 等。为了让容器中的进程更加可控,Docker 使用 Linux cgroups 来限制容器中的进程允许使用的系统资源.
1. 基础知识:Linux control groups 。
1.1 概念 。
Linux Cgroup 可让您为系统中所运行任务(进程)的用户定义组群分配资源 — 比如 CPU 时间、系统内存、网络带宽或者这些资源的组合。您可以监控您配置的 cgroup,拒绝 cgroup 访问某些资源,甚至在运行的系统中动态配置您的 cgroup。所以,可以将 controll groups 理解为 controller (system resource) (for) (process)groups,也就是是说它以一组进程为目标进行系统资源分配和控制.
它主要提供了如下功能:
使用 cgroup,系统管理员可更具体地控制对系统资源的分配、优先顺序、拒绝、管理和监控。可更好地根据任务和用户分配硬件资源,提高总体效率.
在实践中,系统管理员一般会利用CGroup做下面这些事(有点像为某个虚拟机分配资源似的):
Linux 系统中,一切皆文件。Linux 也将 cgroups 实现成了文件系统,方便用户使用。在我的 Ubuntu 14.04 测试环境中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
root@devstack:
/home/sammy
# mount -t cgroup
cgroup on
/sys/fs/cgroup/cpuset
type
cgroup (rw,relatime,cpuset)
cgroup on
/sys/fs/cgroup/cpu
type
cgroup (rw,relatime,cpu)
systemd on
/sys/fs/cgroup/systemd
type
cgroup (rw,noexec,nosuid,nodev,none,name=systemd)
root@devstack:
/home/sammy
# lssubsys -m
cpuset
/sys/fs/cgroup/cpuset
cpu
/sys/fs/cgroup/cpu
cpuacct
/sys/fs/cgroup/cpuacct
memory
/sys/fs/cgroup/memory
devices
/sys/fs/cgroup/devices
freezer
/sys/fs/cgroup/freezer
blkio
/sys/fs/cgroup/blkio
perf_event
/sys/fs/cgroup/perf_event
hugetlb
/sys/fs/cgroup/hugetlb
root@devstack:
/home/sammy
# ls /sys/fs/cgroup/ -l
total 0
drwxr-xr-x 3 root root 0 Sep 18 21:46 blkio
drwxr-xr-x 3 root root 0 Sep 18 21:46 cpu
drwxr-xr-x 3 root root 0 Sep 18 21:46 cpuacct
drwxr-xr-x 3 root root 0 Sep 18 21:46 cpuset
drwxr-xr-x 3 root root 0 Sep 18 21:46 devices
drwxr-xr-x 3 root root 0 Sep 18 21:46 freezer
drwxr-xr-x 3 root root 0 Sep 18 21:46 hugetlb
drwxr-xr-x 3 root root 0 Sep 18 21:46 memory
drwxr-xr-x 3 root root 0 Sep 18 21:46 perf_event
drwxr-xr-x 3 root root 0 Sep 18 21:46 systemd
|
我们看到 /sys/fs/cgroup 目录中有若干个子目录,我们可以认为这些都是受 cgroups 控制的资源以及这些资源的信息.
默认的话,在 Ubuntu 系统中,你可能看不到 net_cls 和 net_prio 目录,它们需要你手工做 mount:
1
2
3
4
5
6
7
8
9
10
11
12
|
root@devstack:
/sys/fs/cgroup
# modprobe cls_cgroup
root@devstack:
/sys/fs/cgroup
# mkdir net_cls
root@devstack:
/sys/fs/cgroup
# mount -t cgroup -o net_cls none net_cls
root@devstack:
/sys/fs/cgroup
# modprobe netprio_cgroup
root@devstack:
/sys/fs/cgroup
# mkdir net_prio
root@devstack:
/sys/fs/cgroup
# mount -t cgroup -o net_prio none net_prio
root@devstack:
/sys/fs/cgroup
# ls net_prio/cgroup.clone_children cgroup.procs net_prio.ifpriomap notify_on_release tasks
cgroup.event_control cgroup.sane_behavior net_prio.prioidx release_agent
root@devstack:
/sys/fs/cgroup
# ls net_cls/
cgroup.clone_children cgroup.event_control cgroup.procs cgroup.sane_behavior net_cls.classid notify_on_release release_agent tasks
|
1.2 实验 。
1.2.1 通过 cgroups 限制进程的 CPU 。
写一段最简单的 C 程序:
1
2
3
4
5
6
|
int
main(
void
)
{
int
i = 0;
for
(;;) i++;
return
0;
}
|
编译,运行,发现它占用的 CPU 几乎到了 100%:
top - 22:43:02 up 1:14, 3 users, load average: 0.24, 0.06, 0.06 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 2304 root 20 0 4188 356 276 R 99.6 0.0 0:11.77 hello 。
接下来我们做如下操作:
1
2
3
4
5
6
7
8
9
10
11
|
root@devstack:
/home/sammy/c
# mkdir /sys/fs/cgroup/cpu/hello
root@devstack:
/home/sammy/c
# cd /sys/fs/cgroup/cpu/hello
root@devstack:
/sys/fs/cgroup/cpu/hello
# ls
cgroup.clone_children cgroup.procs cpu.cfs_quota_us cpu.stat tasks
cgroup.event_control cpu.cfs_period_us cpu.shares notify_on_release
root@devstack:
/sys/fs/cgroup/cpu/hello
# cat cpu.cfs_quota_us
-1
root@devstack:
/sys/fs/cgroup/cpu/hello
# echo 20000 > cpu.cfs_quota_us
root@devstack:
/sys/fs/cgroup/cpu/hello
# cat cpu.cfs_quota_us
20000
root@devstack:
/sys/fs/cgroup/cpu/hello
# echo 2428 > tasks
|
然后再来看看这个进程的 CPU 占用情况:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 2428 root 20 0 4188 356 276 R 19.9 0.0 0:46.03 hello 。
它占用的 CPU 几乎就是 20%,也就是我们预设的阈值。这说明我们通过上面的步骤,成功地将这个进程运行所占用的 CPU 资源限制在某个阈值之内了.
如果此时再启动另一个 hello 进程并将其 id 加入 tasks 文件,则两个进程会共享设定的 CPU 限制:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 2428 root 20 0 4188 356 276 R 10.0 0.0 285:39.54 hello 12526 root 20 0 4188 356 276 R 10.0 0.0 0:25.09 hello 。
1.2.2 通过 cgroups 限制进程的 Memory 。
同样地,我们针对它占用的内存做如下操作:
1
2
3
4
5
6
7
|
root@devstack:
/sys/fs/cgroup/memory
# mkdir hello
root@devstack:
/sys/fs/cgroup/memory
# cd hello/
root@devstack:
/sys/fs/cgroup/memory/hello
# cat memory.limit_in_bytes
18446744073709551615
root@devstack:
/sys/fs/cgroup/memory/hello
# echo 64k > memory.limit_in_bytes
root@devstack:
/sys/fs/cgroup/memory/hello
# echo 2428 > tasks
root@devstack:
/sys/fs/cgroup/memory/hello
#
|
上面的步骤会把进程 2428 说占用的内存阈值设置为 64K。超过的话,它会被杀掉.
1.2.3 限制进程的 I/O 。
运行命令:
1
|
sudo
dd
if
=
/dev/sda1
of=
/dev/null
|
通过 iotop 命令看 IO (此时磁盘在快速转动),此时其写速度为 242M/s:
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND 2555 be/4 root 242.60 M/s 0.00 B/s 0.00 % 61.66 % dd if=/dev/sda1 of=/dev/null 。
接着做下面的操作:
1
2
3
4
5
6
|
root@devstack:
/home/sammy
# mkdir /sys/fs/cgroup/blkio/io
root@devstack:
/home/sammy
# cd /sys/fs/cgroup/blkio/io
root@devstack:
/sys/fs/cgroup/blkio/io
# ls -l /dev/sda1
brw-rw---- 1 root disk 8, 1 Sep 18 21:46
/dev/sda1
root@devstack:
/sys/fs/cgroup/blkio/io
# echo '8:0 1048576' > /sys/fs/cgroup/blkio/io/blkio.throttle.read_bps_device
root@devstack:
/sys/fs/cgroup/blkio/io
# echo 2725 > /sys/fs/cgroup/blkio/io/tasks
|
结果,这个进程的IO 速度就被限制在 1Mb/s 之内了:
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND 2555 be/4 root 990.44 K/s 0.00 B/s 0.00 % 96.29 % dd if=/dev/sda1 of=/dev/null 。
1.3 术语 。
cgroups 的术语包括:
2. Docker 对 cgroups 的使用 。
2.1 默认情况 。
默认情况下,Docker 启动一个容器后,会在 /sys/fs/cgroup 目录下的各个资源目录下生成以容器 ID 为名字的目录(group),比如:
/sys/fs/cgroup/cpu/docker/03dd196f415276375f754d51ce29b418b170bd92d88c5e420d6901c32f93dc14 。
此时 cpu.cfs_quota_us 的内容为 -1,表示默认情况下并没有限制容器的 CPU 使用。在容器被 stopped 后,该目录被删除.
运行命令 docker run -d --name web41 --cpu-quota 25000 --cpu-period 100 --cpu-shares 30 training/webapp python app.py 启动一个新的容器,结果:
1
2
3
4
5
6
|
root@devstack:
/sys/fs/cgroup/cpu/docker/06bd180cd340f8288c18e8f0e01ade66d066058dd053ef46161eb682ab69ec24
# cat cpu.cfs_quota_us
25000
root@devstack:
/sys/fs/cgroup/cpu/docker/06bd180cd340f8288c18e8f0e01ade66d066058dd053ef46161eb682ab69ec24
# cat tasks
3704
root@devstack:
/sys/fs/cgroup/cpu/docker/06bd180cd340f8288c18e8f0e01ade66d066058dd053ef46161eb682ab69ec24
# cat cpu.cfs_period_us
2000
|
Docker 会将容器中的进程的 ID 加入到各个资源对应的 tasks 文件中。表示 Docker 也是以上面的机制来使用 cgroups 对容器的 CPU 使用进行限制.
相似地,可以通过 docker run 中 mem 相关的参数对容器的内存使用进行限制:
1
2
3
4
5
6
|
--cpuset-mems string MEMs in which to allow execution (0-3, 0,1)
--kernel-memory string Kernel memory limit
-m, --memory string Memory limit
--memory-reservation string Memory soft limit
--memory-swap string Swap limit equal to memory plus swap: '-1' to enable unlimited swap
--memory-swappiness int Tune container memory swappiness (0 to 100) (default -1)
|
比如 docker run -d --name web42 --blkio-weight 100 --memory 10M --cpu-quota 25000 --cpu-period 2000 --cpu-shares 30 training/webapp python app.py:
1
2
3
4
5
|
root@devstack:
/sys/fs/cgroup/memory/docker/ec8d850ebbabaf24df572cb5acd89a6e7a953fe5aa5d3c6a69c4532f92b57410
# cat memory.limit_in_bytes
10485760
root@devstack:
/sys/fs/cgroup/blkio/docker/ec8d850ebbabaf24df572cb5acd89a6e7a953fe5aa5d3c6a69c4532f92b57410
# cat blkio.weight
100
|
目前 docker 已经几乎支持了所有的 cgroups 资源,可以限制容器对包括 network,device,cpu 和 memory 在内的资源的使用,比如:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
root@devstack:
/sys/fs/cgroup
# find -iname ec8d850ebbabaf24df572cb5acd89a6e7a953fe5aa5d3c6a69c4532f92b57410
.
/net_prio/docker/ec8d850ebbabaf24df572cb5acd89a6e7a953fe5aa5d3c6a69c4532f92b57410
.
/net_cls/docker/ec8d850ebbabaf24df572cb5acd89a6e7a953fe5aa5d3c6a69c4532f92b57410
.
/systemd/docker/ec8d850ebbabaf24df572cb5acd89a6e7a953fe5aa5d3c6a69c4532f92b57410
.
/hugetlb/docker/ec8d850ebbabaf24df572cb5acd89a6e7a953fe5aa5d3c6a69c4532f92b57410
.
/perf_event/docker/ec8d850ebbabaf24df572cb5acd89a6e7a953fe5aa5d3c6a69c4532f92b57410
.
/blkio/docker/ec8d850ebbabaf24df572cb5acd89a6e7a953fe5aa5d3c6a69c4532f92b57410
.
/freezer/docker/ec8d850ebbabaf24df572cb5acd89a6e7a953fe5aa5d3c6a69c4532f92b57410
.
/devices/docker/ec8d850ebbabaf24df572cb5acd89a6e7a953fe5aa5d3c6a69c4532f92b57410
.
/memory/docker/ec8d850ebbabaf24df572cb5acd89a6e7a953fe5aa5d3c6a69c4532f92b57410
.
/cpuacct/docker/ec8d850ebbabaf24df572cb5acd89a6e7a953fe5aa5d3c6a69c4532f92b57410
.
/cpu/docker/ec8d850ebbabaf24df572cb5acd89a6e7a953fe5aa5d3c6a69c4532f92b57410
.
/cpuset/docker/ec8d850ebbabaf24df572cb5acd89a6e7a953fe5aa5d3c6a69c4532f92b57410
|
2.2 net_cls 。
net_cls 和 tc 一起使用可用于限制进程发出的网络包所使用的网络带宽。当使用 cgroups network controll net_cls 后,指定进程发出的所有网络包都会被加一个 tag,然后就可以使用其他工具比如 iptables 或者 traffic controller (TC)来根据网络包上的 tag 进行流量控制。关于 TC 的文档,网上很多,这里不再赘述,只是用一个简单的例子来加以说明.
关于 classid,它的格式是 0xAAAABBBB,其中,AAAA 是十六进制的主ID(major number),BBBB 是十六进制的次ID(minor number)。因此,0X10001 表示 10:1,而 0x00010001 表示 1:!.
(1)首先在host 的网卡 eth0 上做如下设置:
1
2
3
4
|
tc qdisc del dev eth0 root
#删除已有的规则
tc qdisc add dev eth0 root handle 10: htb default 12
tc class add dev eth0 parent 10: classid 10:1 htb rate 1500kbit ceil 1500kbit burst 10k
#限速
tc filter add dev eth0 protocol ip parent 10:0 prio 1 u32 match ip protocol 1 0xff flowid 10:1
#只处理 ping 参数的网络包
|
其结果是:
(2)启动容器 。
容器启动后,其 init 进程在host 上的 PID 就被加入到 tasks 文件中了:
1
2
|
root@devstack:
/sys/fs/cgroup/net_cls/docker/ff8d9715b7e11a5a69446ff1e3fde3770078e32a7d8f7c1cb35d51c75768fe33
# ps -ef | grep 10047
231072 10047 10013 1 07:08 ? 00:00:00 python app.py
|
设置 net_cls classid:
1
|
echo
0x100001 > net_cls.classid
|
再在容器启动一个 ping 进程,其 ID 也被加入到 tasks 文件中了.
(3)查看tc 情况: tc -s -d class show dev eth0 。
1
2
3
4
5
6
7
|
Every 2.0s: tc -s class
ls
dev eth0 Wed Sep 21 04:07:56 2016
class htb 10:1 root prio 0 rate 1500Kbit ceil 1500Kbit burst 10Kb cburst 1599b
Sent 17836 bytes 182 pkt (dropped 0, overlimits 0 requeues 0)
rate 0bit 0pps backlog 0b 0p requeues 0
lended: 182 borrowed: 0 giants: 0
tokens: 845161 ctokens: 125161
|
我们可以看到 tc 已经在处理 ping 进程产生的数据包了。再来看一下 net_cls 和 ts 合作的限速效果:
10488 bytes from 192.168.1.1: icmp_seq=35 ttl=63 time=12.7 ms 10488 bytes from 192.168.1.1: icmp_seq=36 ttl=63 time=15.2 ms 10488 bytes from 192.168.1.1: icmp_seq=37 ttl=63 time=4805 ms 10488 bytes from 192.168.1.1: icmp_seq=38 ttl=63 time=9543 ms 。
其中:
后两条说使用的 tc class 规则是 tc class add dev eth0 parent 10: classid 10:1 htb rate 1500kbit ceil 15kbit burst 10k 。
前两条所使用的 tc class 规则是 tc class add dev eth0 parent 10: classid 10:1 htb rate 1500kbit ceil 10Mbit burst 10k 。
3. Docker run 命令中 cgroups 相关命令 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
block IO:
--blkio-weight value Block IO (relative weight), between 10 and 1000
--blkio-weight-device value Block IO weight (relative device weight) (default [])
--cgroup-parent string Optional parent cgroup
for
the container
CPU:
--cpu-percent int CPU percent (Windows only)
--cpu-period int Limit CPU CFS (Completely Fair Scheduler) period
--cpu-
quota
int Limit CPU CFS (Completely Fair Scheduler)
quota
-c, --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)
Device:
--device value Add a host device to the container (default [])
--device-
read
-bps value Limit
read
rate (bytes per second) from a device (default [])
--device-
read
-iops value Limit
read
rate (IO per second) from a device (default [])
--device-write-bps value Limit write rate (bytes per second) to a device (default [])
--device-write-iops value Limit write rate (IO per second) to a device (default [])
Memory:
--kernel-memory string Kernel memory limit
-m, --memory string Memory limit
--memory-reservation string Memory soft limit
--memory-swap string Swap limit equal to memory plus swap:
'-1'
to
enable
unlimited swap
--memory-swappiness int Tune container memory swappiness (0 to 100) (default -1)
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.
原文链接:http://www.cnblogs.com/sammyliu/p/5886833.html 。
最后此篇关于详解Docker 容器使用 cgroups 限制资源使用的文章就讲到这里了,如果你想了解更多关于详解Docker 容器使用 cgroups 限制资源使用的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在使用以下dockerfile: FROM ubuntu:14.04 MAINTAINER xxx xxx # SSH RUN apt-get update && apt-get install
我运行了docker-compose build celery,(经过数小时的尝试,我的连接不良)成功了。 app Dockerfile的前80%是相同的,但不会重复使用缓存。从我可以浏览的内容来看,
我可以使用以下命令成功创建 Docker 注册表 v2 服务:docker service create 然后我使用 docker Push 将一些图像推送到该服务。 当我通过 curl localh
我正在尝试使用 gitlab 构建 CI,我从 docker 的 docker 镜像开始,我的前端存储库没有任何问题,但现在使用相同的 gitlab-ci 配置文件,我有此守护程序错误。 这是构建的输
用例: 我们在 Jenkins 中有几个“发布作业”build 和 push 应用程序的 Docker 镜像到 docker registry,更新各种文件中的项目版本,最后将发布标签推送到相应的 G
当我尝试构建我的 docker 文件时,docker 返回以下错误: [+] Building 0.0s (1/2)
docker-in-docker 的作者在此博客中建议不要将此图像用于 CI 目的: jpetazzo/Using Docker-in-Docker for your CI or testing en
我创建了一个 Dockerfile 来在 Docker 中运行 Docker: FROM ubuntu:16.04 RUN apt-get update && \ apt-get in
我尝试为 Docker 镜像定位一个特定标签。我怎样才能在命令行上做到这一点?我想避免下载所有图像,然后删除不需要的图像。 在 Ubuntu 官方版本中,https://registry.hub.do
我正在尝试在docker中运行docker。唯一的目的是实验性的,我绝不尝试实现任何功能,我只想检查docker从另一个docker运行时的性能。 我通过Mac上的boot2docker启动docke
docker-compose.yml version: "3" services: daggr: image: "docker.pvt.com/test/daggr:stable"
我有一个非常具体的开发环境用例。在一些代码中,我启动了一个容器来抓取页面并检索在容器中运行的服务(Gitlab)的 token 。 现在,我希望 Dockerize 运行它的代码。具体来说,类似: o
之前已经问过这个问题,但我不确定当时是否可以使用docker-compose文件完成docker堆栈部署。 由于最新版本支持使用compose将服务部署到堆栈,因此,我无法理解dab文件的值。 我检查
我在一次采访中被问到这个问题,但无法回答。也没有找到任何相关信息。 最佳答案 正如 Docker 文档中所述,Docker 注册表是: [...] a hosted service containin
有没有一种方法可以将具有给定扩展名的所有文件复制到Docker中的主机?就像是 docker cp container_name:path/to/file/in/docker/*.png path/o
我的日志驱动程序设置为journald。使用日志记录驱动程序时,daemon.json文件中的日志级别配置会影响日志吗?使用docker logs 时仅会影响容器日志? 例如,docker和journ
我最近开始使用Docker + Celery。我还共享了full sample codes for this example on github,以下是其中的一些代码段,以帮助解释我的观点。 就上下文
运行docker build .命令后,尝试提交构建的镜像,但收到以下错误 Step 12 : CMD activator run ---> Using cache ---> efc82ff1ca
我们有docker-compose.yml,其中包含Kafka,zookeeper和schema registry的配置 当我们启动docker compose时,出现以下错误 docker-comp
我是Docker的新手。是否可以在Docker Hub外部建立Docker基本镜像存储库?假设将它们存储在您的云中,而不是拥有DH帐户?谢谢。 最佳答案 您可以根据需要托管自己的注册表。可以在Depl
我是一名优秀的程序员,十分优秀!