Docker架构分析
|
|
大家一定很困惑 dockerd, containerd, ctr,shim, runc,等这几个进程的关系到底是啥
初窥得出的结论是:
docker是cli没啥可说的
dockerd是docker engine守护进程,dockerd启动时会启动containerd子进程。
dockerd与containerd通过rpc进行通信(待验证,可能是通过ctr)
ctr是containerd的cli
containerd通过shim操作runc,runc真正控制容器生命周期
启动一个容器就会启动一个shim进程
shim直接调用runc的包函数,shim与containerd之前通过rpc通信
真正用户想启动的进程由runc的init进程启动,即
runc init [args ...]
进程关系模型:
|
|
|
|
dockerd 与 containerd 之间的基情
首先dockerd的main函数相信你能找到cmd/dockerd/docker.go
其它的先略过,直接进start看一看:
|
|
这函数里我们先去关注两件事:
创建了多个Hosts,这是给client去连接的,dockerd启动时用-H参数指定,可以是多个,如指定一个tcp 指定一个unix sock( -H unix:///var/run/docker.sock)
创建了containerd子进程
这个New很重要
|
|
进去看看:
|
|
启动了一个containerd进程,并与之建立连接。通过protobuf进行rpc通信, grpc相关介绍看这里
具体如何创建containerd进程的可以进入runContainerDaemon里细看
|
|
看不明白的话,去标准库里恶补一下cmd怎么用。 cmd.Start()异步创建进程,创建完直接返回
所以创建一个协程等待子进程退出
|
|
docker-containerd-shim是何方神圣 与containerd和runc又有什么关系?
代码中的一句话解释:shim for container lifecycle and reconnection
, 容器生命周期和重连, 所以可以顺着这个思路去看。
先看containerd/linux/runtime.go里的一段代码: Runtime 的Create方法里有这一行,这里的Runtime对象也是注册到register里面的,可以看init函数,然后containerd进程启动时去加载了这个Runtime
|
|
缩减版内容:
|
|
再去看看shim的代码: shim进程启动干的最主要的一件事就是启动一个grpc server:
|
|
进去一探究竟:
|
|
我曾经因为这个os.NewFile(3, "socket")
看了半天看不懂,为啥是3?联系cmd.ExtraFiles = append(cmd.ExtraFiles, f)
创建shim进程时的这句,问题解决了。
这个3的文件描述符,就是containerd用于创建UnixSocket的文件,这样containerd的client刚好与这边启动的 grpc server连接上了,可以远程调用其接口了:
|
|
再看shim与runc的关系,这个比较简单了,直接进入shim service 实现的Create方法即可
|
|
|
|
进入到newInitProcess里面:
|
|
可以看到,在这里调用了runc的API去真正执行创建容器的操作。其本质是调用了runc create --bundle [bundle] [containerid]
命令,在此不多作介绍了
shim进程与runc进程之间
上文可知,shim进程创建runc子进程。
runc 与 容器内第一个进程 init进程
看docker创建了这么多子进程,然后到了runc我们期待的自己Dockerfile中的CMD进程就要被创建了,想想都有点小激动,然而。。。
runc进程启动后会去启动init进程,去创建容器,然后在容器中创建进程,那才是真正我们需要的进程
关于runc init进程关键看StartInitialization方法(main_unix.go)
docker-containerd-ctr 与 docker-containerd
ctr 是一个containerd的client,之间通过proto rpc通信, containerd监听了unix:///run/containerd/containerd.sock。
|
|
|
|
runc 架构破析
比较复杂也比较重要,所以我将单独写一篇相关的介绍 这里
使用runc直接创建容器
|
|
容器状态文件
默认存在/run/runc目录下,不管是docker engine创建的容器还是通过runc直接创建的容器都会在/run/runc目录下创建一个以容器名命名的目录,下面有个state.json文件用于存储文件状态
广告 kubernetes集群三步安装
公众号:
www.sealyun.com





