07 容器引擎 containerd 落地实践

Docker 公司从 2013 年发布容器引擎 Docker 后,就被全球开发者使用并不断改进它的功能。随着容器标准的建立,Docker 引擎架构也从单体走向微服务结构,剥离出 dontainerd 引擎。它在整个容器技术架构中的位置如下:

containerd-arch

图 6-1 containerd 架构图,版权源自 https://containerd.io/

containerd 使用初体验

从官方仓库可以下载最新的 containerd 可执行文件,因为依赖 runc,所以需要一并下载才能正常使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 下载 containerd 二进制文件

wget -q --show-progress --https-only --timestamping \

https://github.com/opencontainers/runc/releases/download/v1.0.0-rc10/runc.amd64 \

https://github.com/containerd/containerd/releases/download/v1.3.4/containerd-1.3.4.linux-amd64.tar.gz \

https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.18.0/crictl-v1.18.0-linux-amd64.tar.gz

sudo mv runc.amd64 runc



# 安装二进制文件

tar -xvf crictl-v1.18.0-linux-amd64.tar.gz

chmod +x crictl runc

sudo cp crictl runc /usr/local/bin/

mkdir containerd

tar -xvf containerd-1.3.4.linux-amd64.tar.gz -C containerd

sudo cp containerd/bin/* /bin/


containerd 提供了默认的配置文件 config.toml,默认放在 /etc/containerd/config.toml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[plugins]

[plugins.cri.containerd]

snapshotter = "overlayfs"

[plugins.cri.containerd.default_runtime]

runtime_type = "io.containerd.runtime.v1.linux"

runtime_engine = "/usr/local/bin/runc"

runtime_root = ""


containerd 服务一般采用后台守护进程方式运行,在 Linux 中使用 systemd 运行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# 配置 containerd.service

sudo cat <<EOF | sudo tee /etc/systemd/system/containerd.service

[Unit]

Description=containerd container runtime

Documentation=https://containerd.io

After=network.target

[Service]

ExecStartPre=/sbin/modprobe overlay

ExecStart=/bin/containerd

Restart=always

RestartSec=5

Delegate=yes

KillMode=process

OOMScoreAdjust=-999

LimitNOFILE=1048576

LimitNPROC=infinity

LimitCORE=infinity

[Install]

WantedBy=multi-user.target

EOF



#启动

sudo systemctl daemon-reload

sudo systemctl enable containerd

sudo systemctl start containerd



#配置 crictl 客户端

sudo crictl config runtime-endpoint unix:///var/run/containerd/containerd.sock


至此,containerd 的使用流程就体验完成了。

通过客户端深入了解 containerd

containerd 启动后,我们需要使用客户端命令行工具来了解下容器运行的情况。这个时候,我们手上有 2 个工具可以使用。一个是 crictl 这个是 Kubernetes 社区提供的操作容器接口标准的客户端工具,另外一个是 ctr 这是 containerd 自带的客户端工具,ctr 是测试使用的工具,在日常工作中推荐使用 crictl 工具来管理容器。

ctr 工具运行如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
   ctr - 

__

_____/ /______

/ ___/ __/ ___/

/ /__/ /_/ /

\___/\__/_/



containerd CLI



USAGE:

ctr [global options] command [command options] [arguments...]



VERSION:

v1.3.4



DESCRIPTION:

ctr is an unsupported debug and administrative client for interacting

with the containerd daemon. Because it is unsupported, the commands,

options, and operations are not guaranteed to be backward compatible or

stable from release to release of the containerd project.



COMMANDS:

plugins, plugin provides information about containerd plugins

version print the client and server versions

containers, c, container manage containers

content manage content

events, event display containerd events

images, image, i manage images

leases manage leases

namespaces, namespace, ns manage namespaces

pprof provide golang pprof outputs for containerd

run run a container

snapshots, snapshot manage snapshots

tasks, t, task manage tasks

install install a new package

shim interact with a shim directly

help, h Shows a list of commands or help for one command



GLOBAL OPTIONS:

--debug enable debug output in logs

--address value, -a value address for containerd's GRPC server (default: "/run/contai

nerd/containerd.sock")

--timeout value total timeout for ctr commands (default: 0s)

--connect-timeout value timeout for connecting to containerd (default: 0s)

--namespace value, -n value namespace to use with commands (default: "default") [$CONTA

INERD_NAMESPACE]

--help, -h show help

--version, -v print the version


crictl 运行命令如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
NAME:

crictl - client for CRI



USAGE:

crictl [global options] command [command options] [arguments...]



VERSION:

v1.18.0



COMMANDS:

attach Attach to a running container

create Create a new container

exec Run a command in a running container

version Display runtime version information

images, image, img List images

inspect Display the status of one or more containers

inspecti Return the status of one or more images

imagefsinfo Return image filesystem info

inspectp Display the status of one or more pods

logs Fetch the logs of a container

port-forward Forward local port to a pod

ps List containers

pull Pull an image from a registry

run Run a new container inside a sandbox

runp Run a new pod

rm Remove one or more containers

rmi Remove one or more images

rmp Remove one or more pods

pods List pods

start Start one or more created containers

info Display information of the container runtime

stop Stop one or more running containers

stopp Stop one or more running pods

update Update one or more running containers

config Get and set crictl options

inspecti Return the status of one or more images

imagefsinfo Return image filesystem info

inspectp Display the status of one or more pods

logs Fetch the logs of a container

port-forward Forward local port to a pod

ps List containers

pull Pull an image from a registry

run Run a new container inside a sandbox

runp Run a new pod

rm Remove one or more containers

rmi Remove one or more images

rmp Remove one or more pods

pods List pods

start Start one or more created containers

info Display information of the container runtime

stop Stop one or more running containers

stopp Stop one or more running pods

update Update one or more running containers

config Get and set crictl options

stats List container(s) resource usage statistics

completion Output shell completion code

help, h Shows a list of commands or help for one command



GLOBAL OPTIONS:

--config value, -c value Location of the client config file. If not specified

and the default does not exist, the program's directory is searched as well (default: "/et

c/crictl.yaml") [$CRI_CONFIG_FILE]

--debug, -D Enable debug mode (default: false)

--image-endpoint value, -i value Endpoint of CRI image manager service [$IMAGE_SERVIC

E_ENDPOINT]

--runtime-endpoint value, -r value Endpoint of CRI container runtime service (default:

"unix:///var/run/dockershim.sock") [$CONTAINER_RUNTIME_ENDPOINT]

--timeout value, -t value Timeout of connecting to the server (default: 2s)

--help, -h show help (default: false)

--version, -v print the version (default: false)


从 2 个命令参数对比参照可以得知,crictl 的功能是比 ctr 要丰富很多的。为了日常使用方便,这里我把 crictl 和 Docker 命令做一个对比,方便大家参照使用:

镜像相关功能DockerContainerd
显示本地镜像列表docker imagescrictl images
下载镜像docker pullcrictl pull
上传镜像docker push
删除本地镜像docker rmicrictl rmi
查看镜像详情docker inspect IMAGE-IDcrictl inspecti IMAGE-ID

注意:上传镜像功能属于和镜像仓库服务的交互,crictl 没有提供此功能可以减轻不少代码逻辑负担。

容器相关功能DockerContainerd
显示容器列表docker pscrictl ps
创建容器docker createcrictl create
启动容器docker startcrictl start
停止容器docker stopcrictl stop
删除容器docker rmcrictl rm
查看容器详情docker inspectcrictl inspect
attachdocker attachcrictl attach
execdocker execcrictl exec
logsdocker logscrictl logs
statsdocker statscrictl stats

看到以上清单,cotnainerd 和 Docker 的功能是一脉相承。因此在生产环境使用 containerd 可以减少很多调用依赖。

Docker 作为 K8s 容器运行时,调用关系如下:

1
2
3
kubelet --> docker shim (在 kubelet 进程中) --> dockerd --> containerd


Containerd 作为 K8s 容器运行时,调用关系如下:

1
2
3
kubelet --> cri plugin(在 containerd 进程中) --> containerd


dockerd 是 Docker 原生容器应用引擎提供的代理服务,内置了 swarm cluster、docker build、docker push、docker api 等扩展功能,但是在生产环境默认都是 Kubernetes 集群环境,所以这块的功能可以直接去掉。

对于 Docker 容器日志、网络配置

日志对比

对比项DockerContainerd
存储路径如果 Docker 作为 Kubernetes 容器运行时,容器日志的落盘将由 docker 来完成,保存在类似/var/lib/docker/containers/$CONTAINERID 目录下。Kubelet 会在 /var/log/pods/var/log/containers 下面建立软链接,指向 /var/lib/docker/containers/$CONTAINERID 该目录下的容器日志文件。如果 Containerd 作为 Kubernetes 容器运行时, 容器日志的落盘由 Kubelet 来完成,保存至 /var/log/pods/$CONTAINER_NAME 目录下,同时在 /var/log/containers 目录下创建软链接,指向日志文件。

CNI 网络对比

对比项DockerContainerd
谁负责调用 CNIKubelet 内部的 docker-shimContainerd 内置的 cri-plugin(containerd 1.1 以后)
如何配置 CNIKubelet 参数 --cni-bin-dir--cni-conf-dirContainerd 配置文件(toml): [plugins.cri.cni]bin_dir = "/opt/cni/bin"conf_dir = "/etc/cni/net.d"

总结

containerd 是 Docker 容器落地实践过程中标准化的产物,经过了全球无数企业应用场景的锤炼。所以它的稳定性是值得开发者信赖的工具。虽然当前业界对 Docker 公司的产品采取回避策略,但是 containerd 是当前最佳的生产环境的容器引擎,值得继续关注场景的使用和支持。