大家都知道容器是通过namespace和cgroup技术来创建的,但是具体代码是如何控制namespace和cgroup的呢?下面就以runc源码为例子简单介绍下。
runc的前身实际上是Docker的libcontainer项目演化而来。runC实际上就是libcontainer配上了一个轻型的客户端。
从本质上来说,容器是提供一个与宿主机系统共享内核但与系统中的其它进程资源相隔离的执行环境。Docker通过调用libcontainer包对namespaces、cgroups、capabilities以及文件系统的管理和分配来“隔离”出一个上述执行环境。同样的,runC也是对libcontainer包进行调用,去除了Docker包含的诸如镜像、Volume等高级特性,以最朴素简洁的方式达到符合OCF标准的容器管理实现。
runc主要的核心代码libcontainer中,调用namespace和cgroup的函数在libcontainer/process_linux.go:func (p *initProcess) start()中
func (p *initProcess) start() error {
defer p.parentPipe.Close()
err := p.cmd.Start()
//开始执行初始化进程命令
p.process.ops = p
p.childPipe.Close()
if err != nil {
p.process.ops = nil
return newSystemErrorWithCause(err, "starting init process command")
}
if err := p.manager.Apply(p.pid()); err != nil {
return newSystemErrorWithCause(