nerdctl + buildkitd 构建容器镜像

时间:2023-02-22 17:00:51

一、背景

在 k8s 1.24,Dockershim 组件正式从 kubelet 中移除,默认将无法直接使用 Docker Engine 作为容器运行时,而直接使用 containerd 作为容器运行时。

虽然 containerd 自带的 crictl 和 ctr 命令能够进行一些简单的管理,但是并不好用,比如说不支持build镜像。因此使用nerdctl + buildkitd  来管理。

Nerdclt 兼容原来 docker 的大部分命令,还实现了很多 docker 不具备的功能,例如延迟拉取镜像(lazy-pulling),镜像加密(imgcrypt)等。

BuildKit 是由 Docker 公司开发的 下一代 docker build 工具,具有更高效、更安全、易于扩展等特点。BuildKit 是由 buildkitd 守护程序和 buildctl 客户端组成。

  • buildkitd 作为服务端,连接容器运行时,目前支持 runc(or crun)和 containerd 作为镜像构建环境,默认是 runc。
  • buildctl 作为客户端,负责解析Dockerfile文件,并向buildkitd发出构建请求。由于命令较为复杂,使用 nerdclt 替代。

二、安装

2.1 安装 buildkitd

# 下载二进制文件
wget https://github.com/moby/buildkit/releases/download/v0.11.3/buildkit-v0.11.3.linux-amd64.tar.gz

# 解压
tar xf buildkit-v0.11.3.linux-amd64.tar.gz

# 复制 buildkitd 和 buildctl 到 /usr/local/bin/
cp bin/buildkitd bin/buildctl /usr/local/bin/

# 编写 buildkit 套接字文件
cat >> /lib/systemd/system/buildkit.socket << EOF
[Unit]
Description=BuildKit
Documentation=https://github.com/moby/buildkit

[Socket]
ListenStream=%t/buildkit/buildkitd.sock

[Install]
WantedBy=sockets.target

EOF

# 编写 buildkit 服务文件,指定使用 containerd
cat >> /lib/systemd/system/buildkitd.service << EOF
[Unit]
Description=BuildKit
Requires=buildkitd.socket
After=buildkit.socketDocumentation=https://github.com/moby/buildkit

[Service]
ExecStart=/usr/local/bin/buildkitd --oci-worker=false --containerd-worker=true

[Install]
WantedBy=multi-user.target

EOF

# 启动 buildkitd 守护进程
systemctl daemon-reload
systemctl enable --now buildkit
systemctl status buildkit

2.2 安装 nerdclt

# 下载二进制文件
wget https://github.com/containerd/nerdctl/releases/download/v1.2.0/nerdctl-1.2.0-linux-amd64.tar.gz

# 解压
tar xf nerdctl-1.2.0-linux-amd64.tar.gz

mv nerdctl /usr/local/bin/

三、构建镜像

# 测试镜像的 Dockerfile
cat >> Dockerfile << EOF
FROM nginx:1.22.1-alpine
RUN apk add --no-cache tzdata ca-certificates \
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
EOF

# 拉取 dockerhub 上的镜像
nerdctl pull nginx:1.22.1-alpine

# 构建镜像
nerdctl build -t harbor.belkuy.top/base/nginx:1.22.1-alpine .

# 登陆镜像仓库,并推送镜像
nerdctl login harbor.belkuy.top
nerdctl push harbor.belkuy.top/base/nginx:1.22.1-alpine

k8s 默认使用 k8s.io namespace,而 nerdctl 默认使用 default namspace。如果需要查看 k8s 相关镜像需要加上“--namespace=k8s.io”来指定。

nerdctl images --namespace=k8s.io

或者在 nerdctl 配置文件中指定 nerdctl 默认使用 k8s.io namespace。

mkdir  /etc/nerdctl/
cat >> /etc/nerdctl/nerdctl.toml << EOF
namespace = "k8s.io"
EOF