容器的本质

2020-10-10  本文已影响0人  郭青耀

容器的本质就是一组特殊的进程,它使用namespace做隔离,用cgroup做限制。

如何使用namespace对容器做隔离的

容器是如何使用namespace做隔离的,因为namespace的种类也很多(pid,mount,network,ipc,user,UTS),这里以PID namespace为例。
首先看一下关于PID 的一个小实验:
环境说明:

实验步骤:

  1. 启动一个centos的交互终端
    docker run -it centos /bin/bash
  2. 看看容器内部bash进程的pid


    bash_pid.png
  3. 看看宿主机上bash进程的pid,用户是root的那个pid.


    宿主机pid.png

由上面的例子可以看到,容器启动的bash在容器内部看到的pid是1,在数组上看到的PID是31840,这是怎么做到的,其实很简单:
正常我们clone一个进程使用下面代码,
int pid = clone(child_main, stack_size, SIGCHLD, NULL);
如果要想这个新进程只能看到自己,以及由自己clone出来的进程(在上面的例子中就是容器内执行的ps进程),不能看到其他进程,使用这段代码
int pid = clone(child_main, stack_size, CLONE_NEWPID | SIGCHLD, NULL);
唯一的区别就是加入了CLONE_NEWPID,其他的namespace隔离也是使用相同的方式
int pid = clone(child_main, stack_size, CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | SIGCHLD, NULL);
这就是同时对,UTS, IPC,PID同时做namespace的隔离。

这里有点不同是mount namespace ,因为mount namespace一定是伴随着mount动作才会生效。mount namespace由chroot 命令发展而来,chroot: change root file system,将根目录"/",挂载到指定的位置。通常我们说的容器镜像,就是挂载在根目录的文件系统,它为隔离后的容器提供文件系统,专业称之为"rootfs".

如何使用cgroup 对资源做限制

cgroup是一个内核功能,它能限制一个或者一组进程对进程资源(cpu,内存,网络等)的使用量不超过被分配的量。cgroup 给用户暴露出来的的操作系统接口是文件系统
mount -t cgroup
可以看到有哪些可以做cgroup限制的类型。

cgroup_type.png

下面演示一个对cpu类型的cgroup做限制的实例。
环境说明:

实验步骤:

  1. 启动一个centos的交互终端
    docker run -it centos /bin/bash
  2. 查看cpu 限制文件参数
[root@f7ab6d1d8b37 /]# ls /sys/fs/cgroup/cpu
cgroup.clone_children  cpu.shares      cpuacct.stat      cpuacct.usage_percpu_sys   notify_on_release
cgroup.procs           cpu.stat        cpuacct.usage         cpuacct.usage_percpu_user  tasks
cpu.cfs_period_us      cpu.uclamp.max  cpuacct.usage_all     cpuacct.usage_sys
cpu.cfs_quota_us       cpu.uclamp.min  cpuacct.usage_percpu  cpuacct.usage_user

这些文件中重要的有,cpu.cfs_period_us和cpu.cfs_quota_us ,表示在时间长度为cpu.cfs_period_us的时间内,可以分配到的CPU时间是cpu.cfs_quota_us ,单位都是us;
默认是没有限制的

[root@f7ab6d1d8b37 /]# cat  /sys/fs/cgroup/cpu/cpu.cfs_quota_us 
-1
[root@f7ab6d1d8b37 /]# cat  /sys/fs/cgroup/cpu/cpu.cfs_period_us 
100000

  1. 写一个死循环,并放到后台执行,记下后台进程的PID
[root@f7ab6d1d8b37 /]# sh deadloop.sh &
[1] 39
[root@f7ab6d1d8b37 /]# cat deadloop.sh 
while true :;
do :;
done
[root@f7ab6d1d8b37 /]# 

后台进程的PID=39

  1. 使用top查看刚才死循环的CPU使用率100%


    cpu_100.png

  1. 现在使用限制cpu方式启动容器,
    设置cpu 100ms(即100000us)可以使用30ms(即30000us)
    docker run -it --cpu-period=100000 --cpu-quota=30000 centos /bin/bash
  2. 查看cgroup中的参数设置


    cgroup30.png
  3. 运行同样的死循环程序
[root@c10f06c1832b /]# sh deadloop.sh  &
[1] 17
[root@c10f06c1832b /]# cat deadloop.sh 
while true :;
do :;
done

后台进程的PID=17

  1. 使用top查看刚才死循环的CPU使用率约等于30%,说明CPU使用率设置生效。


    top30.png

其他类型的Cgroup也是使用类似的方式做资源限制的。

上一篇 下一篇

猜你喜欢

热点阅读