• runc start container流程分析


    1、runc/start.go

    Action: func(context *cli.Context) error

    该函数首先调用container, err := getContainer(context)获取container信息,接着调用status, err := container.Status()获取容器的当前状态。最后,如果status为libcontainer.Created,则调用container.Exec()在创建的容器内执行用户定义的进程。若status为libcontainer.Stopped,则报错,因为runc不能start一个已经run并且stop了的容器,其他状况则都报错。

    --------------------------------------------------------------------------------获取容器实例-----------------------------------------------------------------------------------------------

    2、runc/utils_linux.go

    // getContainer returns the specified container instance by loading it from state with the default factory

    func getContainer(context *cli.Context) (libcontainer.Container, error)

    首先调用 id := context.Args().First()获取容器id,再调用factory, err := loadFactory(context)获取默认工厂实例,最后,return factory.Load(id)返回容器实例。

    3、runc.utils_linux.go

    // loadFactory returns the configured factory instance for execing containers

    获取存储容器信息的目录abs,一般为/run/runc/,获取cgroupManager,最后调用return libcontainer.New(abs, cgroupManager, libcontainer.CriuPath(context.GlobalString("criu")))返回默认factory实例。(详细的描述参见《runc create container流程分析》)

    4、runc/libcontainer/factory_linux.go

    func (l *LinuxFactory) Load(id string) (Container, error)

    调用containerRoot := filepath.Join(l.Root, id)获取容器目录(一般为/run/runc/container-id)。再调用state, err := l.loadState(containerRoot, id)加载容器状态(即加载/run/runc/container-id/state.json)。接着根据配置文件填充获得process和container,如下所示:

    r := &nonchildProcess {

      processPid:    state.InitProcessPid,

      processStartTime: state.InitProcessStartTime,

      fds:         state.ExternalDescriptors,

    }

    c := &linuxContainer {

      initProcess:      r,

      initProcessStartTime:   state.InitProcessStartTime,

      id:          id,

      config:        &state.Config,

      initArgs:         l.InitArgs,

      criuPath:        l.CriuPath,

      cgroupManager:    l.NewCgroupsManager(state.Config.Cgroups, state.CgroupPaths)

      root:          containerRoot,

      created:         state.Created,

    }

    c.state = &loadedState{c: c}

    最后c.refreshState()

    ------------------------------------------------------------------------------结束容器实例获取----------------------------------------------------------------------------------------

    5、runc/libcontainer/container_linux.go

    func (c *linuxContainer) exec() error

    获取容器实例之后,其实只要打开/run/runc/container-id/exec.fifo文件,通知之前已经创建的容器可以开始执行用户进程了。然后再从fifo文件中,获取一个字节的同步数据,最后删除fifo文件,容器start 完成。

    注:runc run命令与runc create & start的不同之处在于run命令在容器创建完成之后,就直接调用c.exec()启动容器内的用户进程,而create & start是把c.exec单独划分至start命令当中。 

  • 相关阅读:
    从zk监控canal-client消费延迟情况
    python面向对象——类的参数
    python面向对象——类的继承
    python并发——进程间同步和通信(二)
    python并发——线程池与进程池(转)
    python从指定目录排除部分子目录——用于删除目录
    python并发统计s3目录大小
    Java对象的序列化和反序列化
    多态、抽象类和接口
    Java输入输出流
  • 原文地址:https://www.cnblogs.com/YaoDD/p/5969365.html
Copyright © 2020-2023  润新知