Featured image of post Containerd 实战:手动安装 / 镜像加速 / 客户端工具

Containerd 实战:手动安装 / 镜像加速 / 客户端工具

Containerd 是 K8s 1.20+ 推荐的容器运行时,比 Docker 轻量、比 CRI-O 生态全。本文覆盖离线包安装、cri-containerd 完整包、CNI 插件、镜像加速器配置、ctr/crictl/nerdctl 三大客户端。

写于 2019-12,背景:K8s 1.20 宣布弃用 dockershim(K8s 1.24 正式移除),社区全面转向 containerd / CRI-O。Containerd 成为 K8s 容器运行时的事实标准。

一、为什么选 Containerd

Docker 的架构是"客户端 docker + 守护进程 dockerd + 容器运行时 containerd"。K8s 实际只需要 containerd,于是社区开始鼓励直接用 containerd,跳过 dockerd:

维度DockerContainerd
体积~1GB~200MB
启动速度较慢更快
与 K8s 集成需要 dockershim(已废弃)原生 CRI 支持
镜像构建内置 docker build需要 buildkit / nerdctl
生态完整偏运行时,缺少 CLI

结论:跑 K8s,选 containerd;本机玩镜像构建,继续用 docker。

二、Containerd 安装

2.1 推荐:完整包(cri-containerd-cni)

cri-containerd-cni 一个 tar 包就包含 containerd + runc + CNI 插件 + systemd 配置文件:

1
2
3
4
5
6
# 下载(version 1.7.11)
curl -L -o cri-containerd-cni-1.7.11-linux-amd64.tar.gz \
  https://github.com/containerd/containerd/releases/download/v1.7.11/cri-containerd-cni-1.7.11-linux-amd64.tar.gz

# 解压到根目录(包含 etc/systemd、usr/local/bin、opt/cni 等)
tar Cxzvf / cri-containerd-cni-1.7.11-linux-amd64.tar.gz

解压后的目录结构:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
/
├── etc
│   ├── cni/net.d/10-containerd-net.conflist
│   ├── crictl.yaml
│   └── systemd/system/containerd.service
├── opt
│   ├── cni/bin/      # CNI 插件(bridge/host-local/loopback 等 16 个)
│   └── containerd/cluster/  # GCE cloud-init 模板
└── usr/local
    ├── bin/containerd, containerd-shim, containerd-shim-runc-v1/v2,
    │        ctr, crictl, critest, ctd-decoder
    └── sbin/runc

2.2 单独装 runc

如果只用 containerd 不需要 runc 二进制,可以单独装:

1
2
3
4
5
wget https://github.com/opencontainers/runc/releases/download/v1.1.11/runc.amd64
mv runc.amd64 /usr/sbin/runc
chmod +x /usr/sbin/runc
runc -v
# runc version 1.1.11 ...

2.3 单独装 CNI 插件

1
2
3
4
5
6
# 下载
wget https://github.com/containernetworking/plugins/releases/download/v1.4.0/cni-plugins-linux-amd64-v1.4.0.tgz

# 解压到 /opt/cni/bin
mkdir -p /opt/cni/bin
tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.4.0.tgz

CNI 插件(16 个)包括:bandwidth / bridge / dhcp / firewall / host-device / host-local / ipvlan / loopback / macvlan / portmap / ptp / sbr / static / tuning / vlan / vrf。

三、生成配置文件

Containerd 默认不带配置文件,需要手动生成:

1
2
3
4
5
# 创建配置目录
mkdir /etc/containerd

# 生成默认配置
containerd config default > /etc/containerd/config.toml

关键配置项

1. 镜像加速(国内必须):

1
2
[plugins."io.containerd.grpc.v1.cri".registry]
      config_path = "/etc/containerd/certs.d"

2. sandbox_image(K8s 启动 Pod 用的 pause 镜像):

1
2
[plugins."io.containerd.grpc.v1.cri"]
  sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"

3. SystemdCgroup(K8s 推荐用 systemd cgroup driver):

1
2
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
  SystemdCgroup = true

启动服务

1
2
3
systemctl daemon-reload
systemctl enable --now containerd
systemctl status containerd

四、镜像加速配置

Containerd 的镜像加速基于 hosts.toml 机制,类似 nginx 的 upstream。/etc/containerd/certs.d/ 下的每个域名一个目录:

4.1 docker.io 加速

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
mkdir -p /etc/containerd/certs.d/docker.io
cat > /etc/containerd/certs.d/docker.io/hosts.toml << EOF
server = "https://docker.io"
[host."https://dockerproxy.com"]
  capabilities = ["pull", "resolve"]
[host."https://docker.m.daocloud.io"]
  capabilities = ["pull", "resolve"]
[host."https://reg-mirror.qiniu.com"]
  capabilities = ["pull", "resolve"]
[host."https://registry.docker-cn.com"]
  capabilities = ["pull", "resolve"]
[host."http://hub-mirror.c.163.com"]
  capabilities = ["pull", "resolve"]
EOF

4.2 K8s 官方镜像加速

registry.k8s.iok8s.gcr.io 是 K8s 组件(apiserver、controller-manager、coredns、metrics-server)默认镜像源,国内必须加速:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# registry.k8s.io
mkdir -p /etc/containerd/certs.d/registry.k8s.io
cat > /etc/containerd/certs.d/registry.k8s.io/hosts.toml << EOF
server = "https://registry.k8s.io"
[host."https://k8s.m.daocloud.io"]
  capabilities = ["pull", "resolve", "push"]
EOF

# k8s.gcr.io(部分旧镜像)
mkdir -p /etc/containerd/certs.d/k8s.gcr.io
cat > /etc/containerd/certs.d/k8s.gcr.io/hosts.toml << EOF
server = "https://k8s.gcr.io"
[host."https://k8s-gcr.m.daocloud.io"]
  capabilities = ["pull", "resolve", "push"]
EOF

4.3 其他常用仓库加速

按需配置 docker.elastic.co(ES 镜像)、gcr.io(Google 容器)、ghcr.io(GitHub 容器)、quay.io(Red Hat 镜像)、nvcr.io(NVIDIA GPU 镜像)、mcr.microsoft.com(微软镜像)等等。模板都是一样的:

1
2
3
4
5
6
7
# 通用模板
mkdir -p /etc/containerd/certs.d/<REGISTRY>
cat > /etc/containerd/certs.d/<REGISTRY>/hosts.toml << EOF
server = "https://<REGISTRY>"
[host."https://<REGISTRY>.m.daocloud.io"]
  capabilities = ["pull", "resolve", "push"]
EOF

重启生效systemctl restart containerd

五、客户端工具三件套

Containerd 自带 3 个客户端,各有分工:

5.1 ctr(containerd 自带)

Containerd 原生 CLI,功能最全但最不友好:

1
2
3
4
5
6
7
8
# 拉镜像
ctr -n k8s.io images pull docker.io/library/nginx:1.25

# 跑容器(无 namespace)
ctr run -d docker.io/library/redis:7 redis-server

# 列出镜像
ctr images ls

ctr 没有 docker CLI 的 run / ps / exec 那种"一体化"体验,调试不直观。

5.2 crictl(K8s 调试专用)

K8s 官方推荐 的 CRI 客户端,专用于排查 K8s 节点问题

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 配置 runtime endpoint
crictl config runtime-endpoint unix:///var/run/containerd/containerd.sock
# 生成的配置在 /etc/crictl.yaml

# 列出 Pod/容器/镜像
crictl pods -A
crictl ps -a
crictl images

# 拉镜像
crictl pull nginx:1.25

# 看容器日志
crictl logs <container-id>

# exec 进容器
crictl exec -it <container-id> sh

什么时候用 crictl? 当你 SSH 进 K8s worker 节点,Pod 起不来,需要直接查 containerd 里的容器状态。

5.3 nerdctl(Docker 体验,containerd 后端)

nerdctl 是 containerd 官方的"Docker 兼容"客户端,命令几乎和 docker 一致:

1
2
3
4
5
6
7
8
9
# 安装
wget https://github.com/containerd/nerdctl/releases/download/v1.7.6/nerdctl-1.7.6-linux-amd64.tar.gz
tar xf nerdctl-1.7.6-linux-amd64.tar.gz -C /usr/local/bin

# 用法跟 docker 几乎一样
nerdctl run -d -p 80:80 nginx:alpine
nerdctl ps
nerdctl logs <container>
nerdctl exec -it <container> sh

nerdctl vs ctr:ctr 是给 containerd 开发者用的,nerdctl 是给应用运维用的,学习曲线 = docker 经验

六、Containerd 在 K8s 中的角色

K8s 1.24+ 不再内置 dockershim,需要 containerd / CRI-O / Docker Engine (with cri-dockerd) 三选一:

1
2
3
4
5
kubelet (K8s 节点)
   ↓ CRI (gRPC)
containerd
   ↓ OCI
runc → 容器进程

kubelet 通过 CRI(Container Runtime Interface)调用 containerd,containerd 内部用 runc 启动容器。用户不需要再写 docker build——镜像可以用 buildah、buildkit、kaniko 在 CI 里构建。

七、常见坑

  1. 镜像加速不生效:hosts.toml 路径错了(应是 /etc/containerd/certs.d/<registry>/ 不是 /etc/docker/
  2. crictl 报 connection refused:runtime-endpoint 没配对,crictl 默认走 dockershim,现在要改成 unix:///var/run/containerd/containerd.sock
  3. SystemdCgroup 没开:cgroup driver 不一致,kubelet 起不来,日志里能看到 “cgroup driver “cgroupfs” differs from kubelet”
  4. pause 镜像拉不到:sandbox_image 默认是 k8s.gcr.io/pause:3.5,国内必须改成阿里云

八、前置知识 / 下一步

前置:Docker 基础、K8s 集群架构(参考 2017-06-15《Kubernetes 入门》

下一步

  1. K8s 二进制部署(2020-03-15)—— Containerd 作为容器运行时的完整部署
  2. K8s 集群管理(2021-12-15)—— 升级 / 节点隔离 / 排错

参考资料

使用 Hugo 构建
主题 StackJimmy 设计