docker containerd shim分析

// containerd-shim is a small shim that sits in front of a runtime implementation that allows it to be reparented to init and handle reattach from the caller.docker

// the cwd of the shim should be the path to the state directory where the shim can locate fifos and other information\json

// Arg0: id of the containerbash

// Arg1: bundle pathapp

// Arg2: runtime binaryide

在啓動容器時,containerd-shim的命令行格式以下所示:函數

docker-containerd-shim 9decb150527a3b64a86b85cfc6faeb09f786dcb2f4e668611418280c75755539 
/var/run/docker/libcontainerd/9decb150527a3b64a86b85cfc6faeb09f786dcb2f4e668611418280c75755539 docker-runc

  

一、containerd/containerd-shim/main.goui

func main()spa

(1)、建立log文件,f, err := os.OpenFile(filepath.Join(cwd, "shim-log.json") ...)命令行

(2)、調用err := start(f)函數,若err不爲nil,當err爲errRuntime的時候,直接關閉f並返回,不然將錯誤記錄到shim-log.json中orm

 

二、containerd/containerd-shim/main.go

// start handling signals as soon as possible so that things are properly reaped

// or if runtime exits before we hit the handler

func start(log *os.File) error

(1)、set the shim as the subreaper for all orphaned processes created by the container,err := osutils.SetSubreaper(1)

(2)、打開exit pipe和control pipe

(3)、調用p, err := newProcess(flag.Arg(0), flag.Arg(1), flag.Arg(2)),加載process實例,再調用p.create()

(4)、msgC := make(chan controlMesage, 32),建立一個goroutine,從control pipe中不斷讀取controlMessage

(5)、最後,一個無限for循環,對來自signal的信號和controlMessage進行處理

(6)、當從signal中得到的信號爲SIGCHLD時,當退出的進程爲runtime時,退出shim

(7)、對來此control pipe的controlMessage進行處理,當msg的Type爲0時,關閉stdin,當Type爲1時,且p.console不爲nil,則調整tty的窗口大小

 

三、containerd/containerd-shim/process.go

func newProcess(id, bundle, runtimeName string)

(1)、p := &process{id: id, bundle: bundle, runtime: runtimeName}

(2)、調用s, err := loadProcess(),從process.json文件中加載state,p.state = s

(3)、調用p.openIO(),最後,返回p

 

四、containerd/containerd-shim/process.go

// openIO opens the pre-created fifo's for use with the container in RDWR so that they remain open if the other side stops listening

func (p *process) openIO() error

(1)、先建立一個goroutine,打開p.state.Stdin, p.stdinCloser = os.openFile(p.state.Stdin, syscall.O_WRONLY)

// NewConsole returns an initialized console that can be used within a container by copying bytes from the master side to the slave that is attached as the tty for the container's init process

(2)、若是p.state.Terminal爲true,調用master, console, err := newConsole(uid, gid),p.console = master, p.consolePath = console,再打開p.state.Stdin和p.state.Stdout,最後調用io.Copy將stdin/stdout與master相連

(3)、對於非tty的狀況,調用i, err := p.initializeIO(uid),p.shimIO = i,再打開p.state.Stdout和p.state.Stderr(方式爲可讀寫)分別與i.Stdou和i.Stderr相連。接着打開p.state.Stdin爲只讀模式,再將i.Stdin和p.state.Stdin相連

 

五、containerd/containerd-shim/process.go

func (p *process) initializeIO(rootuid int) 

該函數生成三個os.Pipe()並分別將一端賦給i = &IO{},再將另外一端賦給p.stdio

 

六、containerd/containerd-shim/process.go

func (p *process) create() error

(1)、獲取當前目錄,建立logPath := filepath.Join(cwd, "log.json"),再擴展args := append([]string{"--log", logPath, "--log-format", "json"}, p.state.RuntimeArgs...)

(2)、對exec,checkpoint,create進行不一樣的處理,這裏只討論create的狀況,繼續擴展args = append(args, "create", "--bundle", p.bundle, "--console", p.consolepath)

(3)、擴展參數--pid-file,cmd := exec.Command(p.runtime, args...),而且將cmd的stdio設置爲p.stdio

(4)、調用cmd.Start(),再調用p.stdio.stdout.Close()和p.stdio.stderr.Close()(why????)

(5)、cmd.Wait(),從pid文件中讀出pid,而且將p.containerPid 設置爲pid

相關文章
相關標籤/搜索