zoukankan      html  css  js  c++  java
  • 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)),给相应的进程发送信号。

  • 相关阅读:
    AtCoder Grand Contest 015 题解
    AtCoder Grand Contest 014 题解
    AtCoder Grand Contest 013 题解
    AtCoder Grand Contest 012 题解
    AtCoder Grand Contest 011 题解
    AtCoder Grand Contest 010 题解
    AtCoder Grand Contest 009 题解
    NOIP2017 Day2 题解
    博客园主题备份
    多项式全家桶
  • 原文地址:https://www.cnblogs.com/YaoDD/p/5996809.html
Copyright © 2011-2022 走看看