告别Docker守护进程:在Containerd生态中构建镜像的现代实践
如果你最近将Kubernetes集群升级到了1.24或更高版本,或者正在构建一个全新的云原生环境,那么很可能已经与Docker守护进程说再见了。随着containerd成为Kubernetes默认的容器运行时,一个现实的问题摆在面前:在没有docker build命令的世界里,我们该如何构建容器镜像?
这不仅仅是命令的简单替换,而是一次工作流的根本性转变。过去几年,我见证了多个团队从Docker迁移到containerd的过程,发现最大的障碍往往不是运行时本身,而是镜像构建这个看似简单却至关重要的环节。今天,我将分享在containerd生态中构建镜像的完整方案,从基础工具选择到生产环境的最佳实践。
1. 理解containerd镜像构建的生态格局
在Docker时代,镜像构建是一个"全家桶"式的体验——docker build命令背后集成了构建引擎、镜像格式转换、本地存储等一系列功能。containerd采取了不同的设计哲学:它专注于容器运行时和镜像管理,将构建功能委托给专门的工具。
这种设计带来了更高的模块化和灵活性,但也意味着我们需要重新认识构建工具链。目前,containerd生态中主要有三种构建方案:
| 方案 | 核心工具 | 适用场景 | 优势 |
|---|---|---|---|
| BuildKit原生方案 | buildctl + buildkitd | 生产环境CI/CD、高性能构建 | 并行构建、增量缓存、安全沙箱 |
| Docker兼容方案 | nerdctl + buildkitd | 开发者迁移、现有工作流兼容 | 命令语法与Docker高度一致 |
| 直接导入方案 | ctr + skopeo | 镜像迁移、离线环境部署 | 无需构建,直接导入现有镜像 |
注意:无论选择哪种方案,都需要理解一个关键概念——containerd的命名空间(namespace)。默认情况下,Kubernetes使用的镜像是存储在
k8s.io命名空间中的,而BuildKit构建的镜像可能位于buildkit或其他命名空间。这是与Docker最大的不同之一。
我在实际项目中发现,大多数团队最终会采用BuildKit + nerdctl的组合方案。BuildKit提供高性能的构建引擎,而nerdctl则提供熟悉的命令行体验。接下来,我将详细介绍这个组合的完整配置流程。
2. BuildKit深度配置:超越基础安装
BuildKit是Docker公司开源的下一代镜像构建工具,现在已经成为containerd生态中的标准构建引擎。它的架构设计非常现代化,采用了客户端-服务器模式,支持多种后端worker。
2.1 生产级安装与配置
很多教程只介绍如何下载二进制文件并启动服务,但在生产环境中,我们需要更细致的配置。以下是我推荐的完整安装流程:
# 1. 下载最新版本的BuildKit
# 建议总是从官方GitHub Releases获取最新稳定版
BUILDKIT_VERSION="v0.12.0"
wget https://github.com/moby/buildkit/releases/download/${BUILDKIT_VERSION}/buildkit-${BUILDKIT_VERSION}.linux-amd64.tar.gz
# 2. 解压到系统目录
tar -xzf buildkit-${BUILDKIT_VERSION}.linux-amd64.tar.gz -C /usr/local/
# 3. 创建符号链接,确保所有二进制文件都在PATH中
ln -sf /usr/local/bin/* /usr/bin/
# 4. 验证安装
buildctl --version
buildkitd --version
安装完成后,关键的步骤是配置systemd服务。我建议不要直接使用命令行参数,而是创建配置文件,这样更易于管理和维护:
# 创建配置目录
mkdir -p /etc/buildkit
# 编写主配置文件
cat > /etc/buildkit/buildkitd.toml << 'EOF'
# BuildKit主配置文件
debug = false
# 网络监听配置
[grpc]
address = ["unix:///run/buildkit/buildkitd.sock", "tcp://0.0.0.0:1234"]
uid = 0
gid = 0
max_recv_message_size = 16777216
max_send_message_size = 16777216
# Worker配置 - 使用containerd作为后端
[worker.containerd]
enabled = true
address = "/run/containerd/containerd.sock"
namespace = "k8s.io" # 重要:与Kubernetes使用相同的命名空间
gc = true
gckeepstorage = 9000 # 保留9GB的构建缓存
# 禁用OCI worker(runc后端)
[worker.oci]
enabled = false
# 私有仓库配置示例
[registry."harbor.example.com"]
http = true
insecure = true
# 如果需要TLS但使用自签名证书
# ca = ["/etc/containerd/certs.d/harbor.example.com/ca.crt"]
EOF
提示:
namespace = "k8s.io"这个配置项非常重要。如果不设置,BuildKit构建的镜像会默认放在buildkit命名空间,而Kubernetes无法直接使用,需要额外导入操作。
接下来创建systemd服务文件:
cat > /etc/systemd/system/buildkit.service << 'EOF'
[Unit]
Description=BuildKit Daemon
Documentation=https://github.com/moby/buildkit
After=network.target containerd.service
Requires=containerd.service
[Service]
Type=notify
ExecStart=/usr/local/bin/buildkitd --config /etc/buildkit/buildkitd.toml
ExecReload=/bin/kill -s HUP $MAINPID
Restart=always
R


被折叠的 条评论
为什么被折叠?



