自从 Kubernetes 宣布在 v1.20 之后弃用 Docker 作为容器运行时,而改用 containerd 之后,大家对 containerd 的关注度越来越高。近些年 CNCF 社区一直在不断完善 containerd,其定位也发生了改变,由原来的系统嵌入组件,变成了今天的“工业级标准的容器运行时”。
而对于我们习惯使用的 Docker CLI 的用户来说,Containerd 虽然提供的 CLI( ctr 和 crictl ),但设计对人类非常不友好,它无法像 Docker 一样去全生命周期的管理容器。
还好,另外一个命令行工具项目 nerdctl 可供我们选择。nerdctl 是一个与 docker CLI 风格兼容的 containerd 的 CLI 工具,使用体验和 docker 基本一致。 nerdctl 已经作为子项目加入了 containerd 项目,它的 github 地址是 https://github.com/containerd/nerdctl。
Nerdctl 基本涵盖了 docker CLI 的所有功能,同时,它还实现了很多 docker 中不具备的功能,比如:延迟拉取镜像(lazy-pulling)、镜像加密(imgcrypt)等。
K3s 默认都使用的 containerd 作为容器运行时,下文将给大家介绍如何在 K3s 中使用 nerdctl 轻松管理容器。
安装 k3s
root@k3s:~# curl -sfL https://get.k3s.io | sh -
[INFO] Finding release for channel stable
[INFO] Using v1.21.5+k3s1 as release
[INFO] Downloading hash https://github.com/k3s-io/k3s/releases/download/v1.21.5+k3s1/sha256sum-amd64.txt
[INFO] Downloading binary https://github.com/k3s-io/k3s/releases/download/v1.21.5+k3s1/k3s
[INFO] Verifying binary download
[INFO] Installing k3s to /usr/local/bin/k3s
[INFO] Creating /usr/local/bin/kubectl symlink to k3s
[INFO] Creating /usr/local/bin/crictl symlink to k3s
[INFO] Creating /usr/local/bin/ctr symlink to k3s
[INFO] Creating killall script /usr/local/bin/k3s-killall.sh
[INFO] Creating uninstall script /usr/local/bin/k3s-uninstall.sh
[INFO] env: Creating environment file /etc/systemd/system/k3s.service.env
[INFO] systemd: Creating service file /etc/systemd/system/k3s.service
[INFO] systemd: Enabling k3s unit
Created symlink /etc/systemd/system/multi-user.target.wants/k3s.service → /etc/systemd/system/k3s.service.
[INFO] systemd: Starting k3s
安装并配置 Nerdctl
从 nerdctl 的 release(https://github.com/containerd/nerdctl/releases) 中下载二进制文件,然后将 nerdctl
移动到/usr/local/bin
下即可完成安装。
因为上一步安装的 K3s 中已经包含了 containerd,所以只需要下载
nerdctl-<VERSION>-<OS>-<ARCH>.tar.gz
即可,否则需要安装nerdctl-full-<VERSION>-<OS>-<ARCH>.tar.gz
如果要使用 nerdctl 管理 K3s 环境中的容器,还需要手动指定 containerd socket
:
root@k3s:~# export CONTAINERD_ADDRESS="unix:///run/k3s/containerd/containerd.sock"
接下来,就可以使用 nerdctl 来查询 K3s 中的容器了:
root@k3s:~# nerdctl -n k8s.io ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
19a2751ecaf2 docker.io/rancher/pause:3.1 "/pause" 24 minutes ago Up
1fb15a152a65 docker.io/rancher/coredns-coredns:1.8.3 "/coredns -conf /etc…" 24 minutes ago Up
3005a774e1c1 docker.io/rancher/library-traefik:2.4.8 "/entrypoint.sh --gl…" 23 minutes ago Up
364c9f6a7a5a docker.io/rancher/pause:3.1 "/pause" 24 minutes ago Up
46aac7428aec docker.io/rancher/klipper-lb:v0.2.0 "entry" 23 minutes ago Up
6442944d5514 docker.io/rancher/pause:3.1 "/pause" 23 minutes ago Up
6f2a5e9a955c docker.io/rancher/local-path-provisioner@sha256:9666b1635fec95d4e2251661e135c90678b8f45fd0f8324c55db99c80e2a958c "local-path-provisio…" 24 minutes ago Up
758b0400700f docker.io/rancher/klipper-lb:v0.2.0 "entry" 23 minutes ago Up
808fdd380c8b docker.io/rancher/pause:3.1 "/pause" 24 minutes ago Up
8421cc3f260d docker.io/rancher/pause:3.1 "/pause" 23 minutes ago Up
c16c1a7560e8 docker.io/rancher/metrics-server:v0.3.6 "/metrics-server" 24 minutes ago Up
root@k3s:~#
通过 nerdctl 创建容器
如果要使用 nerdctl 创建容器,需要提前配置 CNI Plugins:
root@k3s:~# mkdir -p /opt/cni/bin
root@k3s:~# wget -c https://github.com/containernetworking/plugins/releases/download/v1.0.1/cni-plugins-linux-amd64-v1.0.1.tgz -O - | tar -xz -C /opt/cni/bin/
使用 nerdctl 运行容器:
root@k3s:~# nerdctl run -d --name nginx -p 8000:80 nginx:alpine
docker.io/library/nginx:alpine: resolved |++++++++++++++++++++++++++++++++++++++|
index-sha256:686aac2769fd6e7bab67663fd38750c135b72d993d0bb0a942ab02ef647fc9c3: done |++++++++++++++++++++++++++++++++++++++|
manifest-sha256:af466e4f12e3abe41fcfb59ca0573a3a5c640573b389d5287207a49d1324abd8: done |++++++++++++++++++++++++++++++++++++++|
config-sha256:513f9a9d8748b25cdb0ec6f16b4523af7bba216a6bf0f43f70af75b4cf7cb780: done |++++++++++++++++++++++++++++++++++++++|
elapsed: 4.8 s total: 3.1 Ki (669.0 B/s)
4dbc8925dcb69082c9a4c9959853280a9154d2b42cbbf4ce3bdb846b955d34c1
查看创建的容器:
root@k3s:~# nerdctl ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4dbc8925dcb6 docker.io/library/nginx:alpine "/docker-entrypoint.…" About a minute ago Up 0.0.0.0:8000->80/tcp nginx
Build 镜像
Nerdctl 构建镜像需要结合 buildkit (https://github.com/moby/buildkit),所以,我们需要先安装并启动 buildkit:
root@k3s:~# wget -c https://github.com/moby/buildkit/releases/download/v0.9.0/buildkit-v0.9.0.linux-amd64.tar.gz -O - | tar -xz -C /usr/local/
root@k3s:~# buildkitd --containerd-worker-addr="/run/k3s/containerd/containerd.sock" --oci-worker=false --containerd-worker=true &
接下来,我们就可以使用 nerdctl 构建容器镜像:
root@k3s:~# nerdctl build -t "nginx:t1" .
[+] Building 7.6s (4/6)
[+] Building 7.9s (4/6)
[+] Building 8.2s (4/6)
[+] Building 8.4s (4/6)
[+] Building 9.1s (4/6)
[+] Building 9.5s (4/6)
[+] Building 14.6s (7/7) FINISHED
=> [internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 93B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/nginx:alpine 6.4s
=> [internal] load build context 0.1s
=> => transferring context: 652B 0.0s
=> [1/2] FROM docker.io/library/nginx:alpine@sha256:686aac2769fd6e7bab67663fd38750c135b72d993d0bb0a942ab02ef647fc9c3 4.2s
=> => resolve docker.io/library/nginx:alpine@sha256:686aac2769fd6e7bab67663fd38750c135b72d993d0bb0a942ab02ef647fc9c3 0.1s
=> => sha256:61074acc7dd227cfbeaf719f9b5cdfb64711bc6b60b3865c7b886b7099c15d15 0B / 1.39kB 7.3s
=> => sha256:969825a5ca61c8320c63ff9ce0e8b24b83442503d79c5940ba4e2f0bd9e34df8 0B / 663B 7.3s
=> => sha256:3e72c40d0ff43c52c5cc37713b75053e8cb5baea8e137a784d480123814982a2 0B / 891B 7.2s
=> => sha256:c1368e94e1ec563b31c3fb1fea02c9fbdc4c79a95e9ad0cac6df29c228ee2df3 0B / 602B 7.3s
=> => sha256:a0d0a0d46f8b52473982a3c466318f479767577551a53ffc9074c9fa7035982e 2.81MB / 2.81MB 6.9s
=> => sha256:4dd4efe90939ab5711aaf5fcd9fd8feb34307bab48ba93030e8b845f8312ed8e 6.29MB / 7.15MB 6.7s
=> => extracting sha256:a0d0a0d46f8b52473982a3c466318f479767577551a53ffc9074c9fa7035982e 0.7s
=> => extracting sha256:4dd4efe90939ab5711aaf5fcd9fd8feb34307bab48ba93030e8b845f8312ed8e 1.4s
=> => extracting sha256:c1368e94e1ec563b31c3fb1fea02c9fbdc4c79a95e9ad0cac6df29c228ee2df3 0.0s
=> => extracting sha256:3e72c40d0ff43c52c5cc37713b75053e8cb5baea8e137a784d480123814982a2 0.0s
=> => extracting sha256:969825a5ca61c8320c63ff9ce0e8b24b83442503d79c5940ba4e2f0bd9e34df8 0.0s
=> => extracting sha256:61074acc7dd227cfbeaf719f9b5cdfb64711bc6b60b3865c7b886b7099c15d15 0.0s
=> [2/2] ADD index.html /usr/share/nginx/html/ 0.3s
=> exporting to oci image format 2.8s
=> => exporting layers 0.4s
=> => exporting manifest sha256:b9bd561041b26c433f0d556c9b14496a543746cc6ffceaa5d86efcaae8fd60e3 0.0s
=> => exporting config sha256:016a6b9885092667ab5418dbad43f3d1ac35056452431fe8d1a4b0e895ad76f3 0.0s
=> => sending tarball 2.4s
unpacking docker.io/library/nginx:t1 (sha256:b9bd561041b26c433f0d556c9b14496a543746cc6ffceaa5d86efcaae8fd60e3)...done
查看构建镜像:
root@k3s:~# nerdctl images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx alpine 686aac2769fd About an hour ago 26.0 MiB
nginx t1 b9bd561041b2 2 minutes ago 26.0 MiB
总结
实际上,nerdctl 的使用方式和 docker cli 几乎一致,我们也很容易的从 docker 过渡到 nerdctl+containerd。 如果你是因为习惯了 docker cli 才在 K3s 集群中使用 docker 容器运行时的话,那么现在借住 nerdctl 管理 containerd 也许是更好的选择。
本文只是给大家 demo 了如何在 K3s 中借住 nerdctl 管理本地容器,如果你使用的是 RKE2 集群,你也可以参考本文的说明来在 RKE2 集群中使用 nerdctl 来管理 containerd。