一个容器启动主要分为三大部分,如文章题目所示

  • create: 主要是为了解析、组装容器启动的配置和与子进程的消息通道等;
  • init : 主要根据容器配置启动容器整个运行环境,包括熟知ns,cgroups, seccomp, apparmor, caps等;
  • start : 主要是为了通知init 进程启动容器;

其中runc create会fork进程,执行runc init。
image.png

runc create

�utilslinux.go runner
**_CT_ACT_CREATE

�r.container.Start(process)
-> container.start
-�-> parent := newParentProcess 得到
initProcess(就是runc init 1)
—> parent.start() 读取p.messageSockPair.parent ,处理消息直到pipe关闭
—-> p.cmd.Start 启动第一个 (
runc init 1
�—-> manager.Apply 创建cgroup,把(
runc init 1)进程加进去
—-> intelRdtManager 设置intel的资源限制
—-> 发送p.bootstrapData 到 p.messageSockPair.parent
—-> waitInit 通过p.messageSockPair.parent 等待runc init完成initial setup
—-> 从 p.messageSockPair.parent 解析得到(runc init 3)
进程pid
—-> 通过/proc/(runc init 3)
pid**/fd 查询得到 pipe信息
—-> 通过p.messageSockPair.parent 发送createCgroupns的消息
—-> waitForChildExit 等待(runc init 1)子进程退出
�—-> createNetworkInterfaces
�—-> updateSpecState
�—-> 通过p.messageSockPair.parent 发送 config
—-> 通过 p.messageSockPair.parent 处理 事件,下图中的parent角色

—> RunHooks Poststart

image.png

runc run

相当于runc create和runc start。

�utilslinux.go runner
**_CT_ACT_RUN
**
�r.container.Run(process)
-> container.start 这一步和runc create是一样的
-> container.exec

在孙子进程中 (TODO)

(l *LinuxFactory) StartInitialization()

newContainerInit
—> populateProcessEnvironment

linuxStandardInit Init()
—> setupNetwork
—> setupRoute
�—> prepareRootfs:syncParentHooks,Chdir,RunHooks,pivotRoot 切换当前进程的rootfs
—> setupConsole
�—> finalizeRootfs :setReadonly 通过bind mount设置rootfs为readonly,设置umask
—> apparmor.ApplyProfile
—> Sysctl 处理
—> ReadonlyPaths 处理
—> MaskPaths 处理
—> syncParentReady 告诉父进程,准备执行exec
—> SetExecLabel
�—> InitSeccomp
�—> finalizeNamespace drops the caps, sets the correct user and working dir, and closes any leaked file descriptors before executing the command inside the namespace。设置用户名
�—> pdeath.Restore finalizeNamespace can change user/group which clears the parent death signal, so we restore it here.
�—> exec.LookPath(l.config.Args[0])
—> l.pipe.Close() : closing the pipe to signal completion
�—> unix.Close(l.logFd) Close the log pipe fd so the parent’s ForwardLogs can exit.
�—> unix.Open(“/proc/self/fd/“+strconv.Itoa(l.fifoFd) Wait for the FIFO to be opened on the other side before exec-ing the user process.
�—> RunHooks StartContainer
�—> system.Exec