Cilium 容器镜像构建实战:从开发镜像到官方发布镜像的完整机制解析
2026/9/13 3:32:27 网站建设 项目流程

Cilium 容器镜像构建实战:从开发镜像到官方发布镜像的完整机制解析

【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium

本文围绕 Cilium 官方开发文档《Building Container Images》(Documentation/contributing/development/images.rst)展开,系统讲解如何在本地基于当前检出的代码分支构建 cilium-agent 与 cilium-operator 的开发者镜像、如何构建官方发布镜像,以及 cilium-builder/cilium-runtime 两个基础镜像的完整更新流程。读完本文,你将能够独立完成 Cilium 容器镜像的本地构建、推送,并深入理解镜像仓库划分、多平台构建、镜像摘要钉扎(digest pinning)与 CI 镜像生命周期管理的源码级实现细节。

一、Cilium 官方镜像仓库体系

Cilium 团队的镜像仓库遵循统一的构建与发布规范:所有镜像均通过 GitHub Actions 从对应的 GitHub 仓库自动构建,且全部是多平台镜像(multi-platform),同时支持linux/amd64linux/arm64两种架构。

各 GitHub 仓库与镜像仓库的对应关系如下(继承自官方文档):

GitHub 仓库Dockerfile容器镜像仓库
github.com/cilium/ciliumimages/builder/Dockerfilequay.io/cilium/cilium-builder
images/cilium/Dockerfile[quay|docker].io/cilium/cilium
images/clustermesh-apiserver/Dockerfile[quay|docker].io/cilium/clustermesh-apiserver
images/hubble-relay/Dockerfile[quay|docker].io/cilium/hubble-relay
images/operator/Dockerfile[quay|docker].io/cilium/operator
[quay|docker].io/cilium/operator-alibabacloud
[quay|docker].io/cilium/operator-aws
[quay|docker].io/cilium/operator-azure
[quay|docker].io/cilium/operator-generic
images/runtime/Dockerfilequay.io/cilium/cilium-runtime
github.com/cilium/cilium-cliDockerfilequay.io/cilium/cilium-cli
github.com/cilium/image-toolsimages/bpftool/Dockerfilequay.io/cilium/cilium-bpftool
images/compilers/Dockerfilequay.io/cilium/image-compilers
images/llvm/Dockerfilequay.io/cilium/cilium-llvm
images/maker/Dockerfilequay.io/cilium/image-maker
images/startup-script/Dockerfilequay.io/cilium/startup-script
github.com/cilium/proxyDockerfile.builderquay.io/cilium/cilium-envoy-builder
Dockerfilequay.io/cilium/cilium-envoy

其中 builder、runtime、cilium、operator、hubble-relay 这几个核心镜像的定义文件与说明文档就在本仓库中,各镜像的职责描述见 images/README.md:

  • builder 镜像:基于 Ubuntu,提供protoc及插件、Go 工具链、交叉编译工具链,以及用于编译 BPF 数据面的clang编译器(来自 cilium-llvm 镜像);
  • runtime 镜像:提供cilium-agent运行所需的全部用户态依赖——网络工具(iproute2iptablesipsetkmod)、clang/llc工具链、bpftool(两者均来自 cilium/image-tools),以及 CNI loopback 插件;另含gops与 Ubuntu 用户态环境用于排障;
  • cilium 镜像:包含cilium-agent及其他二进制(cilium-dbgenvoycilium-healthhubble-cli),基于 runtime 镜像;
  • operator 镜像:只包含cilium-operator二进制与 CA 证书,不引入其他二进制或库。同一个 Dockerfile 依据OPERATOR_VARIANT构建参数的取值构建 alibabacloud、aws、azure、generic 等变体;
  • hubble-relay 镜像:只包含hubble-relay二进制与 CA 证书。

镜像依赖树

镜像之间并非彼此独立,官方文档给出了清晰的依赖结构:

cilium/cilium ├── cilium/cilium-builder │ └── cilium/cilium-llvm └── cilium/cilium-runtime ├── cilium/cilium-bpftool └── cilium/cilium-llvm cilium/cilium-envoy └── cilium/cilium-envoy-builder cilium/operator └── cilium/cilium-builder └── cilium/cilium-llvm

也就是说,最终的cilium/ciliumcilium/operator应用镜像分别依赖cilium-buildercilium-runtime两个"底座"镜像,而这两个底座又共享cilium-llvmcilium-bpftool等更底层的工具链镜像。理解这棵依赖树是理解后续"更新基础镜像"流程的关键。

二、构建本地开发者镜像(Developer Images)

仓库提供了两个 make 目标,可以基于本地检出的分支自动构建包含你本地改动的容器镜像。

构建 cilium-agent 镜像

运行make dev-docker-image构建包含本地变更的 cilium-agent Docker 镜像:

ARCH=amd64 DOCKER_DEV_ACCOUNT=quay.io/myaccount DOCKER_IMAGE_TAG=jane-developer-my-fix make dev-docker-image

构建 cilium-operator 镜像

运行make docker-operator-generic-image(或对应的docker-operator-aws-imagedocker-operator-azure-image)构建 cilium-operator Docker 镜像:

ARCH=amd64 DOCKER_DEV_ACCOUNT=quay.io/myaccount DOCKER_IMAGE_TAG=jane-developer-my-fix make docker-operator-generic-image

以上命令假定你在quay.io上的用户名是myaccount

环境变量在源码中的解析逻辑

这些环境变量的处理逻辑可以直接在 Makefile.docker 中找到:

DOCKER_REGISTRY ?= quay.io ifeq ($(findstring /,$(DOCKER_DEV_ACCOUNT)),/) # DOCKER_DEV_ACCOUNT already contains '/', assume it specifies a registry IMAGE_REPOSITORY := $(DOCKER_DEV_ACCOUNT) else IMAGE_REPOSITORY := $(DOCKER_REGISTRY)/$(DOCKER_DEV_ACCOUNT) endif
  • DOCKER_DEV_ACCOUNT:若值中包含/,则被整体视为"registry/用户名"形式的镜像仓库前缀;否则自动拼接默认 registryquay.io。这就是为什么示例中要写成quay.io/myaccount
  • DOCKER_IMAGE_TAG:镜像 tag,示例中的jane-developer-my-fix便于区分不同开发者的构建;
  • ARCH:控制构建平台。当指定ARCH时,Makefile.docker 会走 docker buildx 的多平台路径:
ifdef ARCH # Default to multi-arch builds, always create the builder for all the platforms we support DOCKER_PLATFORMS := linux/arm64,linux/amd64 ... # Override default for a single platform ifneq ($(ARCH),multi) DOCKER_PLATFORMS := linux/$(ARCH) endif DOCKER_FLAGS += --push --platform $(DOCKER_PLATFORMS)

即指定ARCH=amd64只构建 amd64 单平台并推送;ARCH=multi(或配合支持双平台的 builder)则同时构建linux/arm64,linux/amd64;不指定ARCH时,构建回落到--load模式——只在本机加载镜像、不推送,模拟普通docker build的行为。

每个镜像目标由统一的模板DOCKER_IMAGE_TEMPLATE生成,模板会注入以下构建参数:

  • CILIUM_SHA:当前 git 版本;
  • MODIFIERS:把NOSTRIPNOOPTLOCKDEBUGRACEV等构建修饰符透传给容器内的 make;
  • OPERATOR_VARIANT:operator 镜像的变体标识;
  • --target:release 或 debug 两种构建目标(见下文 cilium 镜像的 debug 阶段)。

模板还定义了-unstripped变体(NOSTRIP=1+-unstripped后缀),用于保留完整调试符号的镜像,例如dev-docker-image-unstripped

重定向基础镜像的拉取源

设置BASE_IMAGE_REGISTRY可以重定向基础镜像(cilium-buildercilium-runtimecilium-envoy)的拉取地址。这样既能保持 Dockerfile 中的 tag/digest 钉扎不变,又可以在构建时使用自定义 registry:

$(if $(BASE_IMAGE),--build-arg BASE_IMAGE=$(BASE_IMAGE),)

带竞态检测的镜像

若需要构建开启 Go 竞态检测的镜像,参考官方文档中 compile Cilium with race detection 一节的做法,通过构建修饰符传入RACE=1即可(与源码make RACE=1等价)。

三、构建官方发布镜像(Official Release Images)

任何人都可以使用下面的 make 目标构建官方发布镜像:

DOCKER_IMAGE_TAG=v1.4.0 make docker-images-all

从 Makefile.docker 可以看到docker-images-all实际展开为:

docker-images-all: docker-cilium-image docker-hubble-relay-image \ docker-clustermesh-apiserver-image docker-operator-images-all \ docker-standalone-dns-proxy-image docker-operator-images-all: docker-operator-image docker-operator-aws-image \ docker-operator-azure-image docker-operator-alibabacloud-image \ docker-operator-generic-image

也就是说,docker-images-all一次性覆盖 cilium、hubble-relay、clustermesh-apiserver、standalone-dns-proxy 以及全部 5 个 operator 变体,这正是 CI 使用的目标(注释标明docker-*-all targets are mainly used from the CI)。

四、核心 Dockerfile 的多平台构建机制

cilium 镜像:builder 增量构建 + 调试符号分离

images/cilium/Dockerfile 开头钉扎了三个基础镜像,tag 与 sha256 digest 同时锁定:

ARG CILIUM_BUILDER_IMAGE=quay.io/cilium/cilium-builder:be12da3a...@sha256:969449d0bc... ARG CILIUM_RUNTIME_IMAGE=quay.io/cilium/cilium-runtime:c9cad76d...@sha256:d05d3500fc... ARG CILIUM_ENVOY_IMAGE=quay.io/cilium/cilium-envoy:v1.38.4-...@sha256:1b958363...

构建流程分为几个关键阶段:

  1. builder 阶段FROM --platform=${BUILDPLATFORM}):在构建机本征平台上挂载仓库源码与 BuildKit 缓存,执行make GOARCH=${TARGETARCH} ... build-container install-container-binary,实现一次构建、跨架构安装;
  2. 调试符号提取:所有可执行文件先用objcopy --only-keep-debug抽取.debug符号文件到/tmp/debug,随后在NOSTRIP未设置时执行--strip-all并回写--add-gnu-debuglink
  3. release 阶段FROM ${CILIUM_RUNTIME_IMAGE},从 builder 拷贝安装产物,设置HUBBLE_SERVER=unix:///var/run/cilium/hubble.sock(容器内 Hubble CLI 走本地 unix socket 而非 Relay),CMDcilium-dbg
  4. debug 阶段:在 release 镜像之上安装 delve,并用debug-wrapper脚本包装cilium-agent,在专用端口自动挂载调试器,供dev-docker-image-debug-debug目标使用。

runtime 镜像:用户态依赖的"最小完整集"

images/runtime/Dockerfile 基于 Ubuntu 26.04 与 golang 1.27.1,从cilium-llvm:21.1.8cilium-bpftool:7.7.0镜像中提取编译器与 bpftool:

ENV FORCE_BUILD=4 # Change the number to force the generation of a new git-tree SHA. Useful when # we want to re-run 'apt-get upgrade' for stale images.

其中FORCE_BUILD变量值得注意:runtime 镜像以目录的git tree hash作为 tag,目录内容不变时 tree hash 也不变、缓存不会失效。当需要强制重新执行apt-get upgrade刷新过时的系统包时,只需手工修改FORCE_BUILD的数值,使 tree hash 变化即可触发全量重建。此外该镜像还构建了gops、CNI loopback 插件与iptables-wrapper(首次调用时自动探测宿主机的 legacy/nft iptables 后端并重置符号链接)。

builder 镜像:编译工具链的"全家桶"

images/builder/Dockerfile 安装了 amd64/arm64 双向交叉编译工具链、Go 工具链、protoc及插件、delve,并从 cilium-llvm 镜像只拷贝clangllvm-objcopyllvm-strip(注释说明 BPF 构建是 clang-only,verifier 测试从 cilium-llvm 镜像提取工具链而非此镜像)。镜像构建还接入了container-structure-testtest阶段)做结构校验,测试清单见 images/builder/test/spec.yaml。

五、更新 cilium-builder 与 cilium-runtime 镜像的标准流程

这是官方文档中操作性最强的章节,完整继承其七步流程,并补充源码层面的机制说明。

前提:流程的起点是一个"更新镜像版本号"的本地提交(即把新镜像的 tag/digest 写入各 Dockerfile),完成下述步骤后会生成第二个提交,包含所有随镜像更新需要联动的代码库变更。官方明确要求两个提交必须保持分离,以便日后 backport。若只是想让这两个镜像内的软件包升级,可以手工修改 images/runtime/Dockerfile 中的FORCE_BUILD变量为不同的值,然后按相同步骤走。

  1. 提交变更并在 cilium/cilium 上创建 PR

    $ git commit -sam "images: update cilium-{runtime,builder}"
  2. 请 team/build 成员批准:PR 提交后,GitHub Actions 的 "Base Image Release Build" 工作流会自动构建基础镜像,需要该团队成员批准。

  3. 等待构建完成:若 PR 来自外部 fork,构建在推送镜像时会失败——这是预期行为

  4. 外部 fork 场景:本地回写镜像引用并重新推送

    $ make -C images/ update-runtime-image $ git commit -sam "images: update cilium-{runtime,builder}" --amend $ make -C images/ update-builder-image $ git commit -sam "images: update cilium-{runtime,builder}" --amend
  5. 主仓库场景:构建会自动生成一个提交并推送到你的分支,包含仓库内所有文件的联动修改。

  6. 运行完整 CI 并确保通过。

  7. 合并 PR。

更新脚本的源码机制

上一步的update-runtime-image/update-builder-image目标定义在 images/Makefile 中:

update-runtime-image: scripts/update-cilium-runtime-image.sh $(RUNTIME_IMAGE) $(RUNTIME_DIRECTORY) update-builder-image: scripts/update-cilium-builder-image.sh

以 runtime 为例,images/scripts/update-cilium-runtime-image.sh 做了三件事:

  1. 通过make-image-tag.shimages/runtime目录计算新的git tree hash作为 tag;
  2. 调用get-image-digest.sh从 registry 拉取该镜像的 sha256 摘要,拼成image:tag@sha256:...形式;
  3. 把完整的引用回写给 images/runtime/update-cilium-runtime-image.sh,后者用sed批量替换所有引用CILIUM_RUNTIME_IMAGE=的 Dockerfile 及 GitHub Actions 文件:
used_by=($(git grep -l "${image}:" .github/actions/; find . -type f -name 'Dockerfile*' -print0 \ | xargs -0 git grep -l CILIUM_RUNTIME_IMAGE= | sort -u)) for i in "${used_by[@]}" ; do sed -E "s#${image}:.*#${image_full}#" "${i}" > "${i}.sedtmp" && mv "${i}.sedtmp" "${i}" done

builder 侧的 images/builder/update-cilium-builder-image.sh 同理,额外覆盖.devcontainer/devcontainer.json中的镜像引用。

tag 生成规则:tree hash、-dev 与 -wip

images/scripts/make-image-tag.sh 实现了两套打标策略,值得单独说明:

  • 子目录镜像(runtime、builder):使用git ls-tree --full-tree HEAD -- <dir>得到的tree hash作为 tag。这样做的好处是——用git show <tree-hash>可以直接看到构建该镜像时的目录内容,消除"这个镜像到底用了什么输入构建"的疑问;
  • 全树镜像:优先使用符合vX.Y.Z格式的版本 tag;否则用短 commit hash。若当前提交不在origin/main祖先链上(开发分支),追加-dev后缀;若工作区有未提交改动,追加-wip后缀,明确标识非权威构建。

另外,images/Makefile还提供check-runtime-image/check-builder-image目标(CHECK=true模式):脚本会执行git diff --exit-code校验各 Dockerfile 中的引用是否与 registry 实际镜像一致,不一致即报错提示参考本流程——这是 CI 中防止"镜像引用漂移"的守门检查。

六、CI 中的镜像构建与生命周期管理

所有镜像由 GitHub Actionbuild-images自动创建:

  • 该 Action 对所有Pull Request 自动运行,包括来自 fork 仓库的 PR;
  • 构建产物推送到quay.io/cilium/*-ci命名空间;
  • 这些 CI 镜像保留 1 周,之后由ci-images-garbage-collect工作流清理;
  • 镜像被清理后,开发者必须重新推送 PR(如 push 一个空提交),以触发新的镜像构建。

这套机制保证了评审过程中任何时刻使用的镜像都是"PR 当时代码"对应的产物,且不会无限占用 registry 空间。

七、本地直接构建底座镜像(images 子目录)

除了顶层make dev-docker-image,也可以在images/子目录内直接构建与推送底座镜像,其目标是独立的一套(见 images/Makefile 与 images/README.md):

# 构建 runtime 镜像(linux/amd64 + linux/arm64) make -C images runtime-image # 推送到指定 registry make -C images runtime-image PUSH=true REGISTRIES=docker.io/<username>

make -C images all-images会依次完成 lint、runtime-image、builder-image、cilium-image、operator-image、hubble-relay-image 的全量构建。需要注意:新构建的 runtime/builder 镜像若要被 cilium 镜像消费,必须按第五节的流程把 images/cilium/Dockerfile 中的CILIUM_RUNTIME_IMAGE/CILIUM_BUILDER_IMAGE引用更新为新 tag+digest(或借助 update 脚本自动完成)。

八、小结

Cilium 的容器镜像体系可以归纳为三层:

  1. 底座层cilium-llvmcilium-bpftool(来自 cilium/image-tools 仓库)提供编译工具链;
  2. 平台层cilium-builder(编译环境)与cilium-runtime(运行依赖),以 git tree hash 打标、digest 钉扎,通过 update 脚本与CHECK=true校验保证全仓库引用一致;
  3. 应用层ciliumcilium/operator*hubble-relayclustermesh-apiserverstandalone-dns-proxy,由 Makefile.docker 的统一模板驱动,支持多平台构建、release/debug 双目标与竞态检测等构建修饰符。

掌握这套机制后,无论是日常开发中的make dev-docker-image、发布流程中的DOCKER_IMAGE_TAG=vX.Y.Z make docker-images-all,还是基础镜像的例行升级,都有了清晰可操作的命令入口与源码级依据。

【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询