Cilium 在 kind 集群中的镜像预加载(Preload):原理、完整部署流程与故障排查
【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium
导读
本指南围绕 Cilium 官方文档中“在 kind 集群每个 worker 节点预加载cilium镜像”这一关键步骤展开,讲解为什么需要在 kind 集群里预加载镜像、如何通过docker pull与kind load docker-image完成预加载,并串起从依赖安装、kind 配置、建集群、Helm 部署到连通性验证的完整落地流程。读完本文,你将掌握在本地多节点 kind 环境(尤其是离线或受限网络环境)中快速、可靠地部署 Cilium 的完整实战方案,并理解镜像预加载与image.pullPolicy=IfNotPresent之间的配合关系。
说明:本文所有文件路径均以当前仓库根目录为起点。核心操作依据见 Documentation/installation/kind.rst 及其引用的 Documentation/installation/kind-preload.rst。
为什么需要预加载 Cilium 镜像
kind(Kubernetes in Docker)会在 Docker 上以容器方式模拟多节点 Kubernetes 集群。这意味着每个“节点”本质上是一个 Docker 容器,节点内的容器运行时(containerd)与宿主机上的 Docker 是隔离的:
- 宿主机 Docker 拉取的镜像,并不会自动出现在kind 节点容器内;
- kind 节点内的 containerd 如果需要拉取镜像,会直接从远端镜像仓库(如
quay.io)拉取; - 在本地开发、内网或离线(air-gapped)场景下,直接从
quay.io/cilium/cilium拉取镜像可能缓慢、不稳定甚至不可达。
因此,Cilium 官方在 kind 部署流程中专门设计了**预加载(preload)**环节:先在宿主机上用 Docker 拉取 Cilium 镜像,再通过kind load docker-image把它导入每个 kind 节点的 containerd,从而让集群内的镜像分发不再依赖外部网络。该环节在文档中位于 “Install Cilium” 一节,紧跟在 Helm 仓库准备之后、helm install之前,见 Documentation/installation/kind.rst。
核心操作:预加载 Cilium 镜像
Documentation/installation/kind-preload.rst 给出的完整操作只有两条命令:
docker pull quay.io/cilium/cilium:<IMAGE_TAG> kind load docker-image quay.io/cilium/cilium:<IMAGE_TAG>下面逐一拆解其含义与注意事项。
第一步:docker pull拉取镜像到宿主机
docker pull quay.io/cilium/cilium:<IMAGE_TAG>- 镜像仓库为
quay.io/cilium/cilium,即 Cilium 的官方镜像仓库; <IMAGE_TAG>是版本占位符,由文档系统在渲染时替换为当前文档对应版本的标签;- 在仓库中,当前版本号记录在根目录的 VERSION 文件,
stable.txt则记录稳定版本信息。实际部署时,请将<IMAGE_TAG>替换为你希望安装的版本标签(例如v1.x.y),并保证与后续 Helm chart 使用的镜像版本一致。
这一步骤把镜像放进宿主机 Docker 的本地镜像缓存,为下一步导入做准备。如果你的网络能正常访问quay.io,此步即可完成;若身处受限网络,则需要提前在可达环境中完成 pull 并导出/导入镜像。
第二步:kind load docker-image导入每个节点
kind load docker-image quay.io/cilium/cilium:<IMAGE_TAG>- 该命令会把宿主机 Docker 中的镜像导入 kind 集群所有节点(包括 control-plane 与全部 worker)的 containerd;
- 默认作用于当前
kubectlcontext 指向的 kind 集群;若存在多个 kind 集群,可结合kind get clusters确认,并使用--name指定目标集群; - 也可以使用
--nodes参数只向部分节点导入,但默认的“全部节点”行为恰好满足 Cilium DaemonSet 在每个节点运行 agent 的诉求。
执行成功后,kind 节点内的 containerd 已拥有该镜像,后续创建 Pod 时无需再从远端拉取,从而显著缩短部署时间并规避网络不稳定带来的失败。
预加载在整个 kind 部署流程中的位置
预加载并非孤立步骤,它位于 Cilium kind 安装流程的“Install Cilium”阶段。完整流程按 Documentation/installation/kind.rst 的编排如下:
1. 安装依赖(Install Dependencies)
按 Documentation/installation/kind-install-deps.rst 要求准备:
docker稳定版;kubectl>= v1.14.0;helm>= v3.13.0;kind>= v0.7.0。
2. 配置 kind(Configure kind)
kind 集群的创建通过 YAML 配置完成。这一步必须禁用默认 CNI,否则无法替换为 Cilium。仓库提供了可直接下载的模板 Documentation/installation/kind-config.yaml:
kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane - role: worker - role: worker - role: worker networking: disableDefaultCNI: true该配置会创建 1 个 control-plane + 3 个 worker 的 4 节点集群。详见 Documentation/installation/kind-configure.rst。
注意子网冲突:kind 默认 Pod 子网为
10.244.0.0/16、Service 子网为10.96.0.0/12。若与本地网络冲突,务必在networking段显式指定不冲突的podSubnet与serviceSubnet,否则部署 Cilium 后可能出现连通性问题。例如:networking: disableDefaultCNI: true podSubnet: "10.10.0.0/16" serviceSubnet: "10.11.0.0/16"
3. 创建集群(Create a cluster)
按 Documentation/installation/kind-create-cluster.rst 执行:
kind create cluster --config=kind-config.yaml等待数十秒到数分钟后,一个 4 节点集群即创建完成。此时会新增名为kind-kind的kubectlcontext(写入KUBECONFIG,未设置时写入~/.kube/config),可用以下命令确认:
kubectl cluster-info --context kind-kind注意:在 Cilium 部署完成前,节点会一直处于
NotReady状态,这是预期行为,无需惊慌。
4. 安装 Cilium(Install Cilium)
这是预加载步骤所在的阶段。完整顺序为:
a. 配置 Helm 仓库(见 Documentation/installation/k8s-install-download-release.rst):
helm repo add cilium https://helm.cilium.io/Cilium chart 也同时发布在 Quay.io 与 Docker Hub 的 OCI Registry 上,可直接使用oci://协议安装,无需先添加仓库。
b. 预加载镜像(本文核心,见 Documentation/installation/kind-preload.rst):
docker pull quay.io/cilium/cilium:<IMAGE_TAG> kind load docker-image quay.io/cilium/cilium:<IMAGE_TAG>c. 通过 Helm 安装:
helm install cilium cilium/cilium --namespace kube-system \ --set image.pullPolicy=IfNotPresent \ --set ipam.mode=kubernetes这里有两个关键配置与预加载步骤紧密配合:
image.pullPolicy=IfNotPresent:告知 kubelet“镜像已存在于节点时不要重新拉取”。由于镜像已经通过kind load docker-image注入每个节点,使用该策略可确保 Pod 直接使用本地预加载的镜像,避免因尝试再次访问远端仓库而失败或变慢;ipam.mode=kubernetes:使用 Kubernetes 原生的 Pod IP 分配(默认的 CRD 模式在 kind 场景下也可用,此处按官方 kind 指南明确指定)。
5. 验证安装(Validate the Installation)
安装后可用两种方式验证(详见 Documentation/installation/k8s-install-validate.rst)。
方式一:Cilium CLI
先按 Documentation/installation/cli-status.rst 检查集群状态,再运行连通性测试(见 Documentation/installation/cli-connectivity-test.rst):
cilium connectivity test正常情况下输出类似:
✅ 69/69 tests successful (0 warnings)方式二:kubectl 手动验证
先观察组件是否就绪(见 Documentation/installation/kubectl-status.rst):
kubectl -n kube-system get pods --watch所有cilium-*与coredns-*Pod 变为Running即说明安装成功(通常需要几分钟)。
随后部署官方连通性检查清单(见 Documentation/installation/kubectl-connectivity-test.rst):
kubectl create ns cilium-test kubectl apply -n cilium-test -f examples/kubernetes/connectivity-check/connectivity-check.yaml清单会部署一系列覆盖“带/不带 Service 负载均衡”“多种网络策略组合”等连通路径的 Pod;Pod 名称标识测试变体,READY/STATUS即结果:
kubectl get pods -n cilium-test提示:若在单节点kind 集群中部署,涉及多节点的 Pod 会一直停留在
Pending,这是预期行为(多节点测试至少需要 2 个节点才能调度成功)。另外,若 Pod 因 “too many open files” 部署失败,可在宿主机上调大inotify资源限制。测试完成后清理:
kubectl delete ns cilium-test进阶:Socket LB 在 kind 下的 cgroup 前提
如果你希望在 kind 中启用 Cilium 的 Socket LB(即 kubeproxy-free 模式),Documentation/installation/kind.rst 明确列出了三个前提条件:
- 必须启用cgroup v2(例如内核参数
systemd.unified_cgroup_hierarchy=1); - kind 节点必须运行在独立的 cgroup namespace中,且与宿主机底层 cgroup namespace 不同,这样 Cilium 才能在正确的 cgroup 层级上挂载 BPF 程序。可用以下命令验证三个值互不相同:
docker exec kind-control-plane ls -al /proc/self/ns/cgroup docker exec kind-worker ls -al /proc/self/ns/cgroup ls -al /proc/self/ns/cgroup- 在 Docker 中需设置
dockerd --default-cgroupns-mode=private以启用 cgroup namespace;同时要求禁用 cgroup v1 的net_cls/net_prio控制器(或直接cgroup_no_v1="all"),或宿主内核 >= 5.14(含相关修复)。
故障排查
无法连接 k8s api-server
若 Cilium agent 日志中出现:
level=error msg="Unable to contact k8s api-server" error="Get https://10.96.0.1:443/api/v1/namespaces/kube-system: dial tcp 10.96.0.1:443: connect: no route to host"原因通常是:kind 节点是 Docker 容器、与宿主机共享内核,若 Socket LB 未被禁用,Cilium 挂载的 eBPF 程序可能已过期,不再把 api-server 请求路由到当前的kind-control-plane容器。解决办法是重建 kind 集群并重新执行本文的 Helm 安装命令,以分离过期的 eBPF 程序。
Cilium agent Pod 持续崩溃
若 agent Pod 崩溃且日志中出现:
level=warning msg="+ bpftool cgroup attach /var/run/cilium/cgroupv2 connect6 pinned /sys/fs/bpf/tc/globals/cilium_cgroups_connect6" subsys=datapath-loader level=warning msg="Error: failed to attach program" subsys=datapath-loader这通常说明你正在一个已经运行着 Cilium 的环境(例如 Cilium 开发 VM)里再部署 kind 集群,或父级 cgroup 层级上存在重叠的 BPF cgroup 程序。此时应停止原有 Cilium,或按 bpftool 文档手动分离父级 cgroup 层级上的重叠 BPF cgroup 程序,参见 Documentation/installation/kind.rst 的 Troubleshooting 章节。
扩展:用 kind 模拟 Cluster Mesh
预加载的思路同样适用于更复杂的场景——官方文档还演示了如何用 kind 在沙箱中模拟Cluster Mesh(见 Documentation/installation/kind.rst):创建两份不重叠子网的 kind 配置(如集群 1 用podSubnet: "10.0.0.0/16"、serviceSubnet: "10.1.0.0/16",集群 2 用10.2.0.0/16、10.3.0.0/16),分别执行:
kind create cluster --name=cluster1 --config=kind-cluster1.yaml kind create cluster --name=cluster2 --config=kind-cluster2.yaml随后在两个集群中分别完成镜像预加载与 Cilium 部署,再按 Cluster Mesh 指南进行配置(kind 场景下需将NodePortService 部署到kube-system命名空间)。多个集群并存时,记得为kind load docker-image使用--name指定目标集群,这正是预加载命令在多集群场景下的正确用法。
小结
镜像预加载(docker pull+kind load docker-image)是 Cilium 官方 kind 部署流程中承上启下的关键一步:它让 Cilium 镜像在无外部网络依赖的情况下抵达每个 kind 节点,配合image.pullPolicy=IfNotPresent实现本地快速部署,并在多集群(Cluster Mesh)场景下同样适用。按本文梳理的“依赖 → 配置 → 建集群 → 预加载 → Helm 安装 → 验证”流程执行,即可获得一个稳定、可复现的本地 Cilium 多节点环境。
【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考