containerd的create container的API如下所示:

  1. type CreateContainerRequest struct {
  2.  
  3.   Id       string
  4.   BundlePath  string
  5.   Checkpoint   string
  6.   Stdin     string
  7.   Stdout     string
  8.   Stderr     string
  9.   Labels    []string
  10.   NoPivotRoot  bool
  11.   Runtime    string
  12.   RuntimeArgs []string
  13.   CheckpointDir string
  14. }

  

StartTask结构如下所示:

  1. type StartTask struct {
  2.  
  3.   baseTask
  4.  
  5.   ID      string
  6.   BundlePath  string
  7.   Stdout     string
  8.   Stderr     string
  9.   Stdin     string
  10.   StartResponse chan StartResponse
  11.   Labels     []string
  12.   NoPivotRoot  bool
  13.   Checkpoint   *runtime.Checkpoint
  14.   CheckpointDir  string
  15.   Runtime     string
  16.   RuntimeArgs   []string
  17. }

  

1、containerd/api/grpc/server/server.go

func (s *apiServer) CreateContainer(ctx context.Context, c *types.CreateContainerRequest) (*types.CreateContainerResponse, error)

(1)、根据c填充获得e := &supervisor.StartTask{},并调用s.sv.SendTask(e)

(2)、调用 r := <-e.StartResponse,再调用apiC ,err := createAPIContainer(r.Container, false)获取创建的容器实例

(3)、return &types.CreateContainerResponse{Container: apiC,}

2、containerd/supervisor/create.go

func (s *Supervisor) start(t *StartTask) error

(1)、根据t的内容创建容器,runtime.New主要根据ContainerOpts填充结构container获得容器实例,再将创建state并写入状态文件中。

  1. container, err := runtime.New(runtime.ContainerOpts{
  2.  
  3.   Root:    s.stateDir,
  4.   ID:     t.ID,
  5.   Bundle:   t.BundlePath,
  6.   Runtime:   rt,
  7.   RuntimeArgs: rtArgs,
  8.  
  9.   Shim:    s.shim,
  10.  
  11.   Labels:    t.Labels,
  12.   NoPivotRoot: t.NoPivotRoot,
  13.   Timeout:   s.timeout
  14. })

  

(2)、注册新增加的容器,调用s.containers[t.ID] = &containerInfo{container: container,}

(3)、根据新获得的container实例和t的内容,填充获得startTask,再调用s.startTask <- task 交由worker处理

  1. task := &startTask{
  2.  
  3.   Err:      t.ErrorCh(),
  4.   Container:   container,
  5.   StartResponse: t.StartResponse,
  6.   Stdin:      t.Stdin,
  7.   Stdout:     t.Stdout,
  8.   Stderr:     t.Stderr
  9. }

  

3、containerd/supervisor/worker.go

// Start runs a loop in charge of starting new containers

func (w *Worker) Start()

containerd在刚创建时,就启动了10个goroutine,用于处理startTasks,这里的Start函数就是从startTasks这个channel中获取任务,并处理

(1)、调用process, err := t.Container.Start(t.checkpointPath, runtime.NewStdio(t.Stdin, t.Stdout, t.Stderr))启动容器,NewStdio()仅仅只是将参数封装到一个统一的Stdio结构中

(2)、分别调用w.s.monitor.MonitorOOM(t.Container),w.s.monitorProcess(process)对容器进行监控,调用t.StartResponse <- StartResponse{Container: t.Container}返回创建成功的容器实例

4、containerd/runtime/container.go

func (c *container) Start(checkpointPath string, s Stdio) (Process, error)

(1)、创建processRoot := filepath.Join(c.root, c.id, InitProcessID)目录

(2)、容器创建命令 cmd := exec.Command(c.shim, c.id, c.bundle, c.runtime),配置cmd目录为processRoot,spec, err := c.readSpec()

(3)、生成config如下:

  1. config := &processConfig {
  2.  
  3.   checkpoint:    checkpointPath,
  4.   root:       processRoot,
  5.   id:        InitProcessID,
  6.   c:         c,
  7.   stdio:       s,
  8.   spec:       spec,
  9.   processSpec:   specs.ProcessSpec(spec.Process),
  10.  
  11. }

  

(4)、根据config,调用p, err := newProcess(config),生成process实例

(5)、最后调用c.createCmd(InitProcessID, cmd, p),并返回 return p, nil

5、containerd/runtime/process.go

func newProcess(config *processConfig) (*process, error)

(1)、根据config生成process实例,p := &process{root: config.root, id: config.id, container: config.c, ....., cmdDoneCh: make(chan struct{}), state: Running,}

(2)、创建状态文件os.Create(filepath.Join(config.root, "process.config")),生成ps := ProcessState{...},并将ps的内容写入状态文件中

(3)、调用exit, err := getExitPipe(filepath.Join(config.root, ExitFile))和control ,err := getControlPipe(filepath.Join(config.root, ControlFile))生成两个pipe文件,并分别将exit和control赋值给p.exitPipe和p.controlPipe,最后 return p

6、containerd/runtime/process.go

getExitPipe和getControlPipe生成两个FIFO文件,其中Exit函数中的FIFO是只读的,而Control函数中的FIFO是读写的

7、containerd/runtime/container.go

func (c *container) createCmd(pid string, cmd *exec.Cmd, p *process)

(1)、p.cmd = cmd, 再调用 cmd.Start()

(2)、构建defer函数,其中生成一个goroutine,其中调用p.cmd.Wait(),再调用same, err := p.isSameProcess(),如果same为true并且p.pid > 0则再进行一些处理

(3)、调用c.waitForCreate(p, cmd),c.processes[pid] = p

8、containerd/runtime/container.go

func (c *container) waitForCreate(p *process, cmd *exec.Cmd) error

(1)、该函数先启动一个goroutine用于从pidfile中读取pid

(2)、select,从(1)中的goroutine接收结果,或者超时,当超时时,调用cmd.Process.Kill()和cmd.Wait()

docker containerd 中的create 容器操作的更多相关文章

  1. JAVA中的集合容器操作类

    目录 JAVA中的集合容器操作类 List集合 ArrayList的操作方法说明 LinkedList Stack Set Map Queue 总结 JAVA中的集合容器操作类 Java容器类库总共分 ...

  2. docker学习笔记2:容器操作

    一.列出主机上已经创建的容器 docker ps -a 二.创建交互式容器 命令: docker run -i -t ubuntu /bin/bash 其中-i -t 表示创建一个提供交互式shell ...

  3. docker containerd中的容器操作

    containerd的中的各种操作都是通过Task来进行的,因此对于容器的create, start, delete等等操作其实都是一个个的Task而已. Task的数据结构如下所示: type Ta ...

  4. 实例解析Docker数据卷+数据卷容器+flocker数据共享+DockerHub操作

    Docker内部数据管理和Docker之间的数据共享为数据卷和数据卷容器,实例解析1.将本地的文件作为容器的数据卷,2.数据卷flocker插件实现容器集群(或者Docker Swarm)的数据共享3 ...

  5. docker的安装和基本的docker命令、镜像和容器的操作

    1.yum 包更新到最新 yum update 2.安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的 yum insta ...

  6. centos7下安装docker(11容器操作总结)

    这段时间主要是学习了对容器的操作,包括:容器的状态:start,stop,restart,rename,pause,unpause,rm,attach,exec,kill,logs:还学习了对容器的资 ...

  7. 【Docker】容器操作(转)

    来自:https://www.cnblogs.com/zydev/p/5803461.html 列出主机上的容器 列出正在运行的容器:   docker ps 列出所有容器:  docker ps - ...

  8. docker 容器操作( 以 tomcat 为例 )

    一.容器操作 一个镜像可以启动多个容器.比如一个 tomcat 镜像,可以启动多个tomcat 容器,启动后的这些 tomcat 都是各自独立的 二.步骤 1.搜索镜像 [root@localhost ...

  9. Docker.[4].容器操作.

    Docker.[4].容器操作. 熟悉的指令: 启动容器 docker run 交互式启动容器 docker run -i -t IMAGENAME /bin/bash 停止容器 exit 停止容器 ...

随机推荐

  1. fibonacci数列从a到b的个数

    Description 我们定义斐波那契数列如下: f1=1 f2=2 f(n)=f(n-1)+f(n-2)(n>=3)   现在,给定两个数a和b,计算有多少个斐波那契数列中的数在a和b之间( ...

  2. 泛函编程(12)-数据流-Stream

    在前面的章节中我们介绍了List,也讨论了List的数据结构和操作函数.List这个东西从外表看上去挺美,但在现实中使用起来却可能很不实在.为什么?有两方面:其一,我们可以发现所有List的操作都是在 ...

  3. spring事件通知机制详解

    优势 解耦 对同一种事件有多种处理方式 不干扰主线(main line) 起源 要讲spring的事件通知机制,就要先了解一下spring中的这些接口和抽象类: ApplicationEventPub ...

  4. 编译安装memcached扩展记要

    编译memcached扩展的时候,得指定libmemcached库的位置 --with-libmemcached-dir=DIR 来指定路径.这个路径就是安装libmemcached时指定的prefi ...

  5. 移动端H5---页面适配问题详谈(一)

    一.前言 昨天唠叨了哈没用的,今天说点有用的把.先说一下响应式布局吧,我一直认为响应式布局的分项目,一下布局简单得项目做响应式还是可以可以得.例如博客.后台管理系统等.但是有些会认为响应式很牛逼,尤其 ...

  6. ASP.NET控件绑定数据源

    DataList/GridView/Repeater DataSet表示数据集,其中包含表,约束和表之间的关系.与现有数据源的交互通过DataAdapter来控制. 源代码示例: SqlDataAda ...

  7. SharePoint 使用代码为页面添加WebPart

    传统的SharePoint实施中,我们通常会创建SharePoint页面,然后添加webpartzone,而后在上面添加webpart:但是有些情况下,也要求我们使用代码,将webpart添加到相应w ...

  8. The URL "filename" is invalid. It may refer to a nonexistent file or folder, or refer to a valid file or folder that is not in the current Web

    Sharepoint Error : The URL "filename" is invalid. It may refer to a nonexistent file or fo ...

  9. PHP读取Excel文件内容

    PHP读取Excel文件内容   项目需要读取Excel的内容,从百度搜索了下,主要有两个选择,第一个是PHPExcelReader,另外一个是PHPExcel.   PHPExcelReader比较 ...

  10. Objective-C

    1.OC基础 第一个OC的类 Objective-C: 字符串NSString与NSMutableString iOS开发的入门总结的第一篇 iOS开发的入门总结的第二篇