容器=cgroup(资源控制)+namespace(访问隔离)+rootfs(文件系统隔离)+容器引擎(生命周期控制)
容器的创建原理
- 创建进程
通过clone系统调用,并传入各个namespace对应的clone flag,创建了一个新的子进程,该进程用用自己的pid、mount、user、net、ipc、uts namespace。pid = clone(fun, stack, flags, clone_arg); (flags: CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWUSER | CLONE_NEWNET | CLONE_NEWPIC | CLONE_NEWUTS | ...)
- 设定cgroup
简单的说,创建一个新的cgroup就是在cgroupfs的挂载目录中创建一个新的文件夹,因为cgroup分了不同的subsystem,挂载在不同的目录下,所以在每个目录下都创建一个新的文件夹,将进程的pid写进去。
将进程pid写入各个cgroup子系统中。echo &pid > /sys/fs/cgroup/cpu/tasks echo &pid > /sys/fs/cgroup/cpuset/tasks echo &pid > /sys/fs/cgroup/blkio/tasks echo &pid > /sys/fs/cgroup/memory/tasks echo &pid > /sys/fs/cgroup/devices/tasks echo &pid > /sys/fs/cgroup/freezer/tasks
- 创建文件系统
该fun函数由上面生成的新进程执行,在fun函数中,通过pivot_root系统调用,使进程进入一个新的rootfs,之后通过进入一个新的rootfs,之后通过exec系统调用,在新的namespace、cgroup、rootfs中执行"/bin/bash"程序。fun() { ... pivot_root("path_of_rootfs/", path); ... exec("bin/bash"); ... }