docker不同版本之间容器运行时的差异

Posted by Hao Liang's Blog on Saturday, January 8, 2022

参考文章:

K8s 终将废弃 docker,TKE 早已支持 containerd

在containerd集群中使用docker做镜像构建服务

1、背景

对比 Kubernetes 集群使用不同的 docker 版本(1.18、1.19)作为容器运行时,发现底层实现上有些差异,在这里做个记录

2、现象分析

docker 1.18

容器进程树:

containerd 不是 system service,而是靠 dockerd 拉起的进程

kubelet 控制容器的路径:

kubelet —— docker-shim.sock —— dockerd —— containerd —(ttrpc通信)— containerd-shim —— 容器1号进程

各进程退出的影响:

  • dockerd、containerd 进程退出会让 containerd-shim 直接被 systemd 1号进程接管,不影响容器进程

  • containerd-shim 进程退出会导致它的容器进程被回收

  • 容器进程退出会导致它的父进程 containerd-shim 也被回收

  • docker restart 容器会让 containerd 重新创建 containerd-shim 进程和容器1号进程

docker 1.19

containerd 是单独的 system service

kubelet 控制容器的路径和1.18版本相同:

kubelet —— docker-shim.sock —— dockerd —— containerd —(ttrpc通信)— containerd-shim —— 容器1号进程

  • dockerd 重启不影响 pstree,不影响容器进程

  • containerd 进程退出会让 containerd-shim 直接被 systemd 1号进程接管,不影响容器进程

  • containerd-shim 进程退出会导致它的容器进程被回收

  • 容器进程退出会导致它的父进程 containerd-shim 也被回收

  • docker restart 容器会让 containerd 重新创建 containerd-shim 进程和容器1号进程

3、补充说明

本文主要说明了 dockerd、docker-shim、containerd、containerd-shim 的关系。

除此之外,还有 runc 和 cotainerd-ctr 没有提到。

runc

containerd 是通过 containerd-shim 去调用 runc 来启动容器的,runc 启动完容器后本身会直接退出,containerd-shim 则会成为容器进程的父进程, 负责收集容器进程的状态, 上报给 containerd, 并在容器中 pid 为 1 的进程退出后接管容器中的子进程进行清理, 确保不会出现僵尸进程。

可以理解为 runc 是 containerd-shim 的 CLI 工具。

containerd-ctr

像 Docker CLI 工具一样,containerd 同样也提供一个对应的 CLI 工具:ctr,不过 ctr 的功能目前还没有 docker 完善,只有关于镜像和容器的基本功能。

  • 镜像操作:

# 拉镜像(docker pull)
ctr image pull docker.io/library/nginx:alpine

# 查看镜像(docker images)
ctr image ls

# 删镜像(docker rmi)
ctr image rm docker.io/library/nginx:alpine
  • 容器操作:

# 创建容器
# 创建后容器并没有处于运行状态,只是一个静态的容器。一个 container 对象只是包含了运行一个容器所需的资源及相关配置数据,表示 namespaces、rootfs 和容器的配置都已经初始化成功了,只是用户进程还没有启动。
ctr container create docker.io/library/nginx:alpine nginx

# 查看容器
ctr container ls

# 查看容器信息(docker inspect)
ctr container info nginx

# 删除容器(docker rm)
ctr container rm nginx
  • 任务操作:

# 开始真正运行容器(docker run -d)
ctr task start -d nginx

# 查看容器进程(docker ps)
ctr -n moby task ls

# 进入容器(docker exec)
ctr task exec --exec-id 0 -t nginx sh
  • 命名空间操作:
# 查看命名空间
ctr namespace ls

# 创建命名空间
ctr namespace create test

# 查看 docker 启动的容器(默认在 moby 命名空间下)
ctr -n moby container ls