玩坏docker笔记(十):容器底层技术cgroup+namespace

cgroup和namespace是最重要的两种技术。cgroup实现资源限额,namespace实现资源隔离。
linux系统通过cgroup可以设置进程使用CPU、内存和IO资源限额。

cgroup 全称 Control Group。Linux 操作系统通过 cgroup 可以设置进程使用 CPU、内存 和 IO 资源,网络的限额。相信你已经猜到了:前面我们看到的–cpu-shares、-m、–device-write-bps 实际上就是在配置 cgroup。

cgroup 到底长什么样子呢?我们可以在 /sys/fs/cgroup 中找到它。还是用例子来说明,启动一个容器,设置 --cpu-shares=512:

[root@master1 ~]# docker run -it --cpu-shares 512 progrium/stress -c 2
stress: info: [1] dispatching hogs: 2 cpu, 0 io, 0 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 6000us
stress: dbug: [1] --> hogcpu worker 2 [6] forked

查看容器的 ID:

[root@master1 hanli]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                   PORTS               NAMES
efe806fcf906        progrium/stress     "/usr/bin/stress --v…"   6 seconds ago       Up 5 seconds                                 reverent_kare

在 /sys/fs/cgroup/cpu/docker 目录中,Linux 会为每个容器创建一个 cgroup 目录,以容器长ID 命名:

目录中包含所有与 cpu 相关的 cgroup 配置,文件 cpu.shares 保存的就是 --cpu-shares 的配置,值为 512。

同样的,/sys/fs/cgroup/memory/docker 和 /sys/fs/cgroup/blkio/docker 中保存的是内存以及 Block IO 的 cgroup 配置。

[root@master1 hanli]# ls /sys/fs/cgroup/cpu/docker/efe806fcf9062798ece25ed79114b0b029fbef0cd2cbff5477db53e7b0f3b746/
cgroup.clone_children  cgroup.procs  cpuacct.usage         cpu.cfs_period_us  cpu.rt_period_us   cpu.shares  notify_on_release
cgroup.event_control   cpuacct.stat  cpuacct.usage_percpu  cpu.cfs_quota_us   cpu.rt_runtime_us  cpu.stat    tasks
[root@master1 hanli]# cat /sys/fs/cgroup/cpu/docker/efe806fcf9062798ece25ed79114b0b029fbef0cd2cbff5477db53e7b0f3b746/cpu.shares 
512

namespace

在每个容器中,我们都可以看到文件系统、网卡等资源,这些资源看上去是容器自己的。拿网卡来说,每个容器都会认为自己有一块独立的网卡,及时docker host上只有一个块物理网卡。这种方式非常好,他使得容器更像一个独立的计算机。

Linux实现这种方式的技术是namespace,namespace管理着docker host中全局唯一的资源,并可以让每个容器都觉得只有自己在使用他。换句话说,namespace实现了容器间的资源隔离。

Linux使用了六种namespace,分别对应六种资源: mount、UTS、IPC、PID、Network、User。

Mount namespace

它使得容器看上去拥有整个文件系统

容器有自己的 / 目录,可以执行mount 和 unmount命令。当然我们知道这些操作系统只在当前容器中生效,不会影响到 docker host 和其他容器。

UTS namespace

简单的说,UTS namespace让容器有自己的hostname 。默认情况下,容器的hostname 是他的短ID,可以通过 -h 或者 --hostname 参数设定

docker run  -h myhost -it ubuntu

IPC namespace

它可以让容器拥有自己的共享内存和信号量(semaphore)来实现进程间通信,而不会与docker host和其他容器的IPC混在一起。

下面例子可以看到所有容器的进程都挂载 dockerd 进程下面,同时也可以看到容器自己的子进程。如果我们进入到容器中,使用ps命令只能看到自己的进程

root@docker-lab:~# docker run -d httpd
48ec7932db1c5c27a194b15b3a3c1349a5d43d9260661b381d1563092ed941b6
root@docker-lab:~#
root@docker-lab:~# docker run -d nginx
37a75b3a9bd9ad07fb07bff04b6df16e3cb693e47ffb87a1184d1b8f975e8b6d

root@docker-lab:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
37a75b3a9bd9        nginx               "nginx -g 'daemon of…"   25 seconds ago      Up 25 seconds       80/tcp              compassionate_chatterjee
48ec7932db1c        httpd               "httpd-foreground"       32 seconds ago      Up 32 seconds       80/tcp              amazing_banach
root@docker-lab:~# ps axf

24323 ?        Ssl   71:17 /usr/bin/dockerd -H fd:// -H tcp://0.0.0.0
24336 ?        Ssl  149:45  \_ docker-containerd --config /var/run/docker/containerd/containerd.toml
27680 ?        Sl     0:00      \_ docker-containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/48ec7932db1c5c27a194b15b3a3c1349a5d4
27712 ?        Ss     0:00      |   \_ httpd -DFOREGROUND
27759 ?        Sl     0:00      |       \_ httpd -DFOREGROUND
27760 ?        Sl     0:00      |       \_ httpd -DFOREGROUND
27761 ?        Sl     0:00      |       \_ httpd -DFOREGROUND
27954 ?        Sl     0:00      \_ docker-containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/37a75b3a9bd9ad07fb07bff04b6df16e3cb6
27989 ?        Ss     0:00          \_ nginx: master process nginx -g daemon off;
28033 ?        S      0:00              \_ nginx: worker process

Network namespace

Network namespace 让容器拥有自己的独立的网卡、IP、路由等资源。

User namespace

他让容器能够管理自己的用户,docker host 不能看到容器中创建的用户

docker exec -it ubuntu bash
useradd cloudman
exit

su cloudman  #报错

在容器中创建了用户 cloudman,但 host 中并不会创建相应的用户。
容器常用命令总结

create 创建
run 创建+启动
pause 暂停
unpause 恢复
stop 停止
kill 杀掉
start 启动
restart 重启
start 启动
attach 进入容器启动的终端
exec 在容器中启动新的进程,通常使用 -it
logs 显示容器启动进程的控制台输出 用-f 持续打印
rm 删除

你可能感兴趣的:(Docker容器实战)