• docker containerd中的容器操作


    containerd的中的各种操作都是通过Task来进行的,因此对于容器的create, start, delete等等操作其实都是一个个的Task而已。

    Task的数据结构如下所示:

    type Task interface {
    
      Errorch() chan error
    
    }
    
    
    
    type baseTask struct {
    
      errCh    chan error
      mu      sync.Mutex
    }
    

      

    container的数据结构如下所示,而container对外暴露的interface是Container,其中包含了对container的各种操作,包括ID(), Delete()等等。

    type container struct {
    
      // path to store runtime state information
    
      root    string
      id     string
      bundle   string
      runtime    string
      runtimeArgs []string
      shim    string
      processes  map[string]*process
      labels    []string
      oomFds   []int
      noPivotRoot bool
      timeout   time.Duration
    }
    

      

    容器的delete操作

    DeleteTask的数据结构如下所示:

    // DeleteTask holds needed paramaters to remove a container
    
    type DeleteTask struct {
    
      baseTask
    
      ID    string
      Status  uint32
      PID    string
      NoEvent  bool
      Process  runtime.Process
    }
    

      

    -2、containerd/supervisor/monitor_linux.go

    func (m *Monitor) start()对获取到的syscall.EpollEvent进行处理,当获取的event的id指向的是一个runtime.Process并且event的Events类型为syscall.EPOLLHUP时,先对该process从events中删除,进行epoll相关的清理操作,最后调用m.exits <- t

    -1、containerd/supervisor/supervisor.go

    func (s *Supervisor) exitHandler()

    (1)、在启动daemon的时候,启动过一个exitHandler的goroutine,该函数主要的作用就是从s.monitor.exits这个runtime.Process类型的channel中获取退出的process。

    (2)、对于每个退出的process,创建 e := &ExitTask{Process: p,},最后s.SendTask(e),最终经过taskHandler的调度,最终会在exit()函数进行处理

    0、containerd/supervisor/exit.go

    func (s *Supervisor) exit(t *ExitTask) 

    (1)、调用`proc := t.Process `, `status, err := proc.ExitStatus()`获取进程的退出码

    (2)、如果proc.ID()不是runtime.InitProcessID,则说明只是一个exec的进程退出,则创建一个ne := &ExecExitTask{},再调用s.execExit()进行处理

    (3)、若为退出的是init进程,则创建一个ne := &DeleteTask{},再调用s.delete(ne)进行处理

    1、containerd/supervisor/delete.go

    func (s *Supervisor) delete(t *DeleteTask) error

    (1)、调用i, ok := s.containers[t.ID]获取容器实例,再调用s.deleteContainer(i.container)

    (2)、当t.Process 不为nil 时,调用t.Process.Wait()

    (3)、当t.NoEvent为false时,则调用s.notifySubscribers(Event{Type: StateExit, Timestamp: time.Now(), ID: t.ID, Status: t.status, PID: t.PID,})

    (4)、更新supervisor的container信息,调用ContainersCounter.Dec(1)和ContainerDeleteTimer.UpdateSince(start)

    2、containerd/supervisor/delete.go

    func (s *Supervisor) deleteContainer(container runtime.Container) error

    该函数很简单,先调用delete(s.containers, container.ID()),再调用return container.Delete()

    3、containerd/runtime/container.go

    首先调用os.RemoveAll(filepath.Join(c.root, c.id)),删除目录/var/run/docker/libcontainerd/containerd/container-id,接着利用exec.Command直接调用调用命令行`docker-runc delete contain-id。

    容器的kill操作

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

    func (s *apiServer) Signal(ctx context.Context, r *types.SignalRequest) (*types.SignalResponse)

    这个函数就是根据r中的内容对supervisor.SignalTask进行填充,最后调用s.sv.SendTask(e),再返回return &types.SignalResponse{}, nil

    2、containerd/supervisor/signal.go

    func (s *Supervisor) signal(t *SignalTask) error

    (1)、首先调用i, ok := s.containers[t.ID]获取container实例

    (2)、再调用processes, err := i.container.Processes()获取容器中所有的process实例

    (3)、最后遍历processes,找到t.PID对应的process,调用return p.Signal(t.Signal)

    3、containerd/runtime/process.go

    func (p *process) Signal(s os.Signal) error

    该函数只是简单地调用return syscall.Kill(p.pid, s.(syscall.Signal)),给相应的进程发送信号。

  • 相关阅读:
    taro clock组件
    创建taro项目
    ts声明各种变量类型
    ts的数组/元组/type/interface
    使用styled-components初始化css
    Oracle profile含义、修改、新增
    JDK bin指令
    Nginx 设置忽略favicon.ico文件的错误日志
    nginx: [error] CreateFile() "D: ginx-1.14.2/logs/nginx.pid" failed 解决办法
    Nginx Windows详细安装部署教程
  • 原文地址:https://www.cnblogs.com/YaoDD/p/5996809.html
Copyright © 2020-2023  润新知