Cilium Service Mesh:从 CNI、eBPF 到 Envoy、GAMMA 与安全退出
订单接口开始间歇性返回超时后,平台同学先看了节点:Cilium agent 全部 Ready,Service 的后端也健康,Hubble 里还能看到 client 发往 orders 的 TCP 流。可一加上“只允许 GET /orders”的规则,部分请求就消失在应用日志之前。有人据此断言 eBPF 丢了包,另一个人却在 cilium-envoy 看到了 HTTP policy deny。两边看到的仍然都是真的:L3/L4 路径主要在内核 eBPF,选中 L7 规则的流量却会被透明送进用户态 Envoy。
回滚方案暴露了更大的误解。团队准备执行 Helm uninstall,以为这只会撤掉一组服务网格组件,却发现 Cilium 同时承担 CNI、Service 负载均衡、NetworkPolicy 和节点路由;直接删 agent 会让新 Pod 无法联网,旧 Pod 还可能残留 BPF、tc、route 与 CNI 状态。Cilium Service Mesh 的价值来自网络、安全和观测的一体化,退出成本也来自同一件事。可靠落地必须从 CNI 生命周期开始,而不是从一条 HTTPRoute 开始。
一条请求会跨过内核与用户态两种执行面
Cilium 首先是 Kubernetes CNI、网络、安全和可观测平台,Service Mesh 是建立在这些能力上的一组流量治理入口。每个节点运行高权限 cilium-agent DaemonSet,负责 endpoint、security identity、策略、Service 负载均衡、eBPF 程序和 Hubble 事件;cilium-operator 处理需要集群协调的资源、IPAM 和 Gateway API reconciliation。它们不是业务 HTTP 请求的通用中转站。
普通 Pod-to-Pod、Service、TCP/UDP 与 L3/L4 policy 主要由挂在内核网络位置的 eBPF 程序处理,不需要向每个应用 Pod 注入 sidecar。但 eBPF 不负责完整解析 HTTP、gRPC、Kafka 或 DNS 语义。L7 Policy、Ingress、Gateway API、GAMMA 或直接的 CiliumEnvoyConfig 会让选中流量通过 eBPF/TPROXY 转到 Envoy。新安装通常启用独立的 cilium-envoy DaemonSet,目标集群仍应从 Helm values、Pod 和 agent 状态确认实际模式,不能从“无 per-Pod sidecar”推出“无代理”。
故障定位因此要先问“这一跳在哪执行”。eBPF policy map 的 allow/drop、Envoy 的 route/policy、应用状态码和 operator 写入的 resource condition 是不同证据。cilium status --wait 说明组件就绪,Accepted=True 说明控制器接受对象,Hubble 看到 TCP 说明某段流存在;它们都不能单独证明 HTTP 请求按预期命中后端。
安装前先决定 CNI 归属和回头路
安装前从 系统要求 核对 CPU 架构、Linux kernel、BTF/Kconfig、cgroup、bpffs 和发行版差异,再从 Kubernetes 要求 核对目标发行线。基础内核门槛不代表所有高级能力都可用;kube-proxy replacement、WireGuard/IPsec、BGP、云 IPAM 和 host network Gateway 各有额外条件。
还要明确 Cilium 是新集群的唯一 CNI、替换现有 CNI,还是暂时 chaining。三条路径决定 IPAM、路由、NetworkPolicy 语义、Pod 是否要重建和卸载顺序。现有集群迁移应先阅读官方 CNI migration,建立节点批次、旧新 CNI 共存窗口、不可调度/排空策略和回滚点。不能把 generic values 直接套到 GKE、AKS、EKS、OpenShift、RKE、k3s 或 Talos。
在 mesh-lab 所在隔离集群记录基线:
kubectl get nodes -o wide
kubectl get pods -A -o wide
kubectl get networkpolicy -A
kubectl -n kube-system get daemonset
kubectl -n kube-system get configmap cilium-config -o yaml 2>/dev/null || true基线要能回答旧 CNI 写了哪些 /etc/cni/net.d 配置、PodCIDR 由谁分配、kube-proxy 是否存在、已有 NetworkPolicy 由谁执行、节点与 Pod 路由如何建立。回滚不是“Helm release 回到上一版”,而是旧 CNI 重新具备为新 Pod 建网的能力。
固定 chart、镜像与平台 values
Quick Installation 适合受支持的默认集群,规模较大或网络模型特殊时应进入平台专用安装。Cilium CLI 的安装内部也使用 Helm;需要可审计和 GitOps 时,可直接使用官方推荐的 OCI chart,并固定 chart version、镜像 digest 和平台 values:
helm template cilium oci://quay.io/cilium/charts/cilium \
--version 1.19.6 \
--namespace kube-system \
-f cilium-values.yaml > cilium-rendered.yaml
kubectl diff -f cilium-rendered.yaml
helm upgrade --install cilium oci://quay.io/cilium/charts/cilium \
--version 1.19.6 \
--namespace kube-system \
-f cilium-values.yaml
cilium status --wait
cilium connectivity test命令将 chart 固定为 1.19.6,避免安装过程跟随浮动版本;部署时应从 release 页面 获取签名 tag 与镜像摘要,并按 升级指南 判断是否改用同发行线更合适的 patch。OCI chart 支持签名验证和 digest pinning,生产流水线应保留验证结果与 SBOM。
一个面向 Service Mesh 实验的 values 需要显式表达关键开关,而不是依赖操作者记忆:
kubeProxyReplacement: true
envoy:
enabled: true
l7Proxy: true
gatewayAPI:
enabled: true
hubble:
enabled: true
relay:
enabled: true
ui:
enabled: false
prometheus:
enabled: true
rollOutCiliumPods: true这些字段直接改变运行成本与故障面:
| 字段 | 影响 | 错误判断 |
|---|---|---|
kubeProxyReplacement | Service LB、GAMMA 前提和节点数据路径 | 只看 kube-proxy Pod 是否存在就判断替换完成 |
l7Proxy / envoy.enabled | L7 redirect 与 Envoy 部署 | 认为 eBPF 能独自执行 HTTP path policy |
gatewayAPI.enabled | operator 是否 reconcile Gateway API | CRD 已安装就认为 controller 已启用 |
hubble.enabled、Relay/UI | 节点流事件、跨节点查询和界面 | agent 有 Hubble server 就认为 Relay、长期存储都存在 |
prometheus.enabled 与 Hubble metrics | 组件指标和流量指标 | 没有 HTTP 时序就断言没有 HTTP 流量 |
rollOutCiliumPods | values 变化后的 agent/operator 滚动 | 修改 ConfigMap 后假设所有配置即时热生效 |
Gateway API CRD 要由明确的平台 owner 预安装。TLSRoute 使用 experimental CRD;缺少时相应能力会被禁用。Cilium 1.19.6 的 GAMMA 还要求 kubeProxyReplacement=true 与 L7 proxy,就绪前先检查 feature 状态:
cilium config view
cilium features status
kubectl -n kube-system get pods -l k8s-app=cilium -o wide
kubectl -n kube-system get pods -l k8s-app=cilium-envoy -o wide让 mesh-lab 成为可观察的 Cilium endpoint
部署 client、orders-v1、orders-v2 时分别使用 client 与 orders ServiceAccount,并让两个订单 Pod 带 role: orders、version: v1|v2。Cilium identity 来自一组与安全相关的 labels,不来自 Pod IP;Pod 重建换地址后策略语义仍可保持,但高基数标签会制造大量 identity,不能把请求 ID、时间戳或任意发布哈希都纳入身份相关集合。下面用公开测试镜像建立可执行骨架;进入团队环境时应同步到受控仓库并固定 digest。
kubectl create namespace mesh-lab
kubectl -n mesh-lab create serviceaccount client
kubectl -n mesh-lab create serviceaccount orders
kubectl -n mesh-lab create deployment orders-v1 \
--image=hashicorp/http-echo:1.0.0 --port=8080 -- \
'-listen=:8080' -text=v1
kubectl -n mesh-lab create deployment orders-v2 \
--image=hashicorp/http-echo:1.0.0 --port=8080 -- \
'-listen=:8080' -text=v2
kubectl -n mesh-lab create deployment client \
--image=curlimages/curl:8.14.1 -- sleep infinity
kubectl -n mesh-lab set serviceaccount deployment/orders-v1 orders
kubectl -n mesh-lab set serviceaccount deployment/orders-v2 orders
kubectl -n mesh-lab set serviceaccount deployment/client client
kubectl -n mesh-lab patch deployment orders-v1 --type=merge \
-p '{"spec":{"template":{"metadata":{"labels":{"role":"orders","version":"v1"}}}}}'
kubectl -n mesh-lab patch deployment orders-v2 --type=merge \
-p '{"spec":{"template":{"metadata":{"labels":{"role":"orders","version":"v2"}}}}}'
kubectl -n mesh-lab expose deployment orders-v1 --port=8080 --target-port=8080
kubectl -n mesh-lab expose deployment orders-v2 --port=8080 --target-port=8080
kubectl -n mesh-lab create service clusterip orders --tcp=8080:8080
kubectl -n mesh-lab patch service orders --type=merge \
-p '{"spec":{"selector":{"app":"orders-v1"}}}'
kubectl -n mesh-lab rollout status deploy/client
kubectl -n mesh-lab rollout status deploy/orders-v1
kubectl -n mesh-lab rollout status deploy/orders-v2
kubectl -n mesh-lab exec deploy/client -- curl -fsS http://orders:8080/orders
cilium endpoint list
cilium identity list
cilium connectivity test基础请求应返回 v1;若 endpoint、identity、DNS 或 Service 仍不稳定,不要继续加策略。这里的稳定入口先选择 v1,后续 GAMMA Route 接管后再分流到两个版本 Service。
接入证据至少包括:Pod 已由 Cilium CNI 建网,agent 中存在 endpoint,security identity 与预期 labels 对应,Pod-to-Pod、Service、DNS、跨节点请求可用。再用 Hubble 查看流,而不是只看 endpoint 状态:
hubble status
hubble observe --namespace mesh-lab --followHubble server 位于每个 agent 内,只完整观察由 Cilium 管理的 endpoint;Relay 聚合多节点,CLI/UI 是消费者。没有流事件可能是 Relay、过滤器、buffer 或 event rate limit 问题,不自动等于没有网络通信。
正向实验:从 L3/L4 allow 走到 HTTP L7 allow
先建立纯 L3/L4 规则,只允许 client ServiceAccount 访问带 role: orders 的 endpoint 及 TCP 8080。namespace-scoped CiliumNetworkPolicy 的 endpoint selector 只选择本 namespace,来源 ServiceAccount 则是可审计的工作负载属性:
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: orders-l4
namespace: mesh-lab
spec:
endpointSelector:
matchLabels:
role: orders
ingress:
- fromEndpoints:
- matchLabels:
io.cilium.k8s.policy.serviceaccount: client
toPorts:
- ports:
- port: "8080"
protocol: TCP把对象保存为 orders-l4.yaml 并执行 kubectl apply -f orders-l4.yaml。从正确 client 请求应成功;再创建使用 default ServiceAccount 的临时来源,预期请求在 eBPF policy 点被 drop:
kubectl -n mesh-lab exec deploy/client -- curl -fsS http://orders:8080/orders
kubectl -n mesh-lab create deployment wrong-client \
--image=curlimages/curl:8.14.1 -- sleep infinity
kubectl -n mesh-lab rollout status deployment/wrong-client
kubectl -n mesh-lab exec deploy/wrong-client -- \
curl --connect-timeout 3 -sS http://orders:8080/orders保存 Hubble 的 source/destination identity、verdict、drop reason,以及目标应用是否收到请求。若错误客户端仍成功,先确认目标 endpoint 是否被 policy 选中、policy enforcement mode 是否为 default/always、label 键是否与实际 identity 一致。取证后执行 kubectl -n mesh-lab delete deployment wrong-client,再进入 L7 实验。
然后用 HTTP rule 替换 纯 L4 allow,只允许 GET /orders。Cilium 的 allow policy 会合并;若 orders-l4 与下面的规则同时选择同一来源和端口,纯 L4 allow 会使 L7 限制失效。先删除旧规则,再应用新规则:
kubectl -n mesh-lab delete ciliumnetworkpolicy orders-l4一旦使用 L7 rule,选中的连接会产生 Envoy redirect:
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: orders-http
namespace: mesh-lab
spec:
endpointSelector:
matchLabels:
role: orders
ingress:
- fromEndpoints:
- matchLabels:
io.cilium.k8s.policy.serviceaccount: client
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: GET
path: /orders把对象保存为 orders-http.yaml 并执行 kubectl apply -f orders-http.yaml。正向请求应出现应用 200、Hubble L7 flow 和 Envoy HTTP 指标;同时检查 endpoint policy revision 与 cilium-envoy 日志。Hubble metrics 还需单独配置静态或动态 exporter;没有 L7 redirect 时也不会凭空产生 HTTP 事件,因此“只有 TCP flow”首先提示执行路径或观测配置不同,而不是观测后端坏了。
反向实验:错误方法必须在应用之前被拒绝
让同一 client 发 POST /orders,再发 GET /admin。两者身份和端口都正确,却不匹配 HTTP rule:
kubectl -n mesh-lab exec deploy/client -- \
curl -sS -D - -o /dev/null -X POST http://orders:8080/orders
kubectl -n mesh-lab exec deploy/client -- \
curl -sS -D - -o /dev/null http://orders:8080/admin预期由 Envoy 返回协议级拒绝,HTTP 通常表现为代理生成的 403,订单应用日志中不应出现请求。必须用响应头、Envoy/Hubble 记录和应用访问日志判断 403 的生产者;不能仅凭状态码把它归给应用。若 Hubble 只有 L3 drop,说明可能连来源或端口都没通过;若连接 reset,需结合 Envoy 日志判定 listener、route 或上游连接故障。
hubble observe --namespace mesh-lab --protocol http --since 5m
kubectl -n kube-system logs daemonset/cilium-envoy --since=5m
kubectl -n mesh-lab logs deploy/orders-v1 --since=5mL7 policy 会引入用户态解析、连接重建与额外资源,升级 Envoy 时长连接也可能中断。只需要服务身份与端口隔离时,应保留在 L3/L4;只有 path、method、header 或协议语义确实构成安全边界时才支付 L7 成本。直接编写 CiliumEnvoyConfig 能获得更细的 Envoy 能力,但 schema、升级耦合和错误半径更大,优先用 Cilium policy 或 Gateway API 的可移植模型。
用 GAMMA 把 Service 变成 east-west 路由附着点
Cilium 同时支持 north-south Gateway API 和 east-west GAMMA。GAMMA 不要求为了服务间路由创建外部 LoadBalancer Gateway;producer HTTPRoute 的 parentRefs 直接指向 Kubernetes Service,访问该 Service 的流量经每节点 Envoy执行 L7 路由。
先创建稳定入口 orders,以及 selector 分离的 orders-v1、orders-v2 Service,再提交同 namespace producer route:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: orders-split
namespace: mesh-lab
spec:
parentRefs:
- group: ""
kind: Service
name: orders
port: 8080
rules:
- matches:
- path:
type: PathPrefix
value: /orders
backendRefs:
- name: orders-v1
port: 8080
weight: 90
- name: orders-v2
port: 8080
weight: 10检查链路不能停在 YAML:
kubectl -n mesh-lab get httproute orders-split -o yaml
kubectl get ciliumenvoyconfig -A
cilium status --verbose
hubble observe --namespace mesh-lab --protocol http --follow把对象保存为 orders-route.yaml 并执行 kubectl apply -f orders-route.yaml。读取 Route 的 Accepted、ResolvedRefs、reason/message 和 observed generation,再确认 operator 生成的 Cilium Envoy 配置、agent/Envoy 已编程、两个后端有 endpoint。最后发送足够样本,统计响应版本与 Hubble L7 flow。权重不是每十个请求必有一个 v2,连接复用和随机选择会影响有限样本。
路由生效后,再把 orders-v2 缩容到零但保留指向它的 backendRef:
kubectl -n mesh-lab scale deployment orders-v2 --replicas=0
kubectl -n mesh-lab get endpointslice -l kubernetes.io/service-name=orders-v2
kubectl -n mesh-lab get httproute orders-split -o yamlRoute 可能仍为 Accepted=True、ResolvedRefs=True,因为 Service 引用合法;被分到 v2 的请求却应由 Envoy 返回 503 或等价的 no healthy upstream,本次请求不应出现在 v2 应用日志。恢复 orders-v2 为一个副本并等待 ready,确认错误消失,才能结束反例。这个实验把“引用可解析、配置已接受、数据面有健康 endpoint”拆成三层证据。
Cilium 1.19.6 的 GAMMA 支持是有限且实验性的:只支持 producer HTTPRoute 与 ReferenceGrant,Route 与父 Service 必须同 namespace,不支持 consumer route/MeshConsumerRoute,conformance 也不是完整 Extended Mesh。故意创建跨 namespace consumer route 时,预期应从 status 读到不支持或未接受,而不是把请求失败归为网络故障。GAMMA 文档 是每次升级前必须重查的能力表。
north-south Gateway 还多一层身份转换:外部通常先以 world identity 到 Envoy,经过 Envoy 后以特殊 ingress identity 访问后端。策略必须分别允许 world -> ingress 和 ingress -> backend;缺任何一段都会在不同执行点拒绝。Route 的 Accepted/ResolvedRefs、Gateway 的 Programmed 与真实请求属于不同对象和证据层,不能要求某一个对象同时出现三种 condition。
Mutual Authentication Beta 不等于业务流已加密
Cilium security identity 的 label 模型用于策略;Mutual Authentication 则在 policy 中额外要求经过认证的身份。1.19.6 的 Mutual Authentication 明确为 Beta 且能力未完整。受支持的方案使用官方验证过的 SPIRE:SPIRE server 管 trust domain,per-node SPIRE agent 完成 attestation,Cilium agent 代表 workload 请求 SVID。
当前常规连接的认证握手在 Cilium agent 之间带外进行,不是每条业务连接都由 per-Pod sidecar 执行传统 mTLS。这个握手为策略建立“远端 identity 已认证”的缓存结论,但业务数据包不会因此自动进入该 TLS 会话;要获得业务数据机密性,还要启用 WireGuard 或 IPsec transparent encryption,并分别验证实际覆盖范围。Hubble Relay API 自身的 mTLS 只保护观测平面,也不能证明 workload 流量已认证或加密。
实验只能在隔离集群按官方示例逐步进行:固定 SPIRE chart/镜像与 trust domain,检查 server/agent attestation;为 client -> orders policy 的 ingress 或 egress rule 增加 authentication.mode: required;观察正确身份 allow、错误身份 deny、认证缓存和 agent 认证日志。策略删除或认证缓存过期后还要复验连接,确认旧 allow 不再被误当成永久授权。随后在两套可重建基线中分别验证“未启用透明加密”和“启用 WireGuard 或 IPsec”,用 cilium encryption status --per-node-details、cilium-dbg debuginfo --output json、节点接口状态与受控包捕获区分“认证握手成功”与“业务包已透明加密”。WireGuard 与 IPsec 是替代方案,不在同一活动集群里来回切换,也不把 Hubble 中缺少某类事件当成认证失败的唯一证据。
WireGuard 默认保护 Cilium 管理 endpoint 之间的跨节点流量,同节点 Pod 流量不会进入 WireGuard 隧道;host、NodePort、DSR、native routing、L7 proxy 与外部客户端的覆盖还会随模式变化。正向实验必须强制 client 与 orders 分布在不同节点,并把远端 peer、allowed IP、握手时间和密文包对应起来;反向实验放在同节点,预期看不到 WireGuard 封装,却仍应受 CiliumNetworkPolicy 约束。若把“抓不到 WireGuard 包”直接判为明文泄漏,会把设计边界误报成故障;若只看 encryption status 为 enabled,又会漏掉未被覆盖的流向。
生产决策还必须接受当前限制:Cluster Mesh 不能与该 Mutual Authentication 组合成单一 trust domain,外部 mTLS 方案不兼容,其他 SPIFFE 实现未受支持,per-connection handshake 和部分安全模型仍在演进。需要稳定、默认的每工作负载 mTLS 时,不应把 Beta 能力包装成既成基线;可以先使用成熟的透明加密加 L3/L4/L7 policy,或者选择身份能力更成熟的网格。
Hubble 是取证入口,不是无限容量的事实仓库
Cilium metrics 观察 agent/operator/Envoy 自身,Hubble flow 与 metrics 观察工作负载网络行为,两者要一起看。cilium_ 指标可解释 policy regeneration、endpoint 和 datapath 健康;envoy_/envoy_cilium_ 解释 listener、cluster、upstream 与 L7;Hubble 则给出 source/destination identity、verdict、drop reason、DNS 和协议元数据。
完整排障顺序可以固定为:
cilium status --verbose 判断 agent、operator、Envoy、Hubble 是否健康。cilium endpoint list 与 identity/policy 状态确认 workload 是否真正纳管。Hubble 从 DNS、TCP、policy verdict 到 HTTP 逐层定位第一处失败。
Gateway/Route status 检查 generation、conditions 和引用解析。Envoy listener/route/cluster 与日志确认 L7 配置和 upstream。应用日志确认请求是否真正抵达,响应由谁产生。
需要跨组件材料时生成 cilium sysdump,按敏感资产限制访问和保留。
高基数 context labels、HTTP labels、DNS/IP context 和 exemplars 会放大 Prometheus series。Hubble event map 还可能受 rate/burst limit、采样和 buffer pressure 影响;“没有事件”只有在自身 drop/pressure 指标正常时才有意义。长期容量应同时监控 agent CPU、事件丢失、Relay 队列、active series、日志字节、存储保留和查询延迟。
项目接入、权限和敏感数据
项目仓库版本化 ServiceAccount、稳定 labels、CiliumNetworkPolicy、HTTPRoute 和回滚清单;平台仓库持有 Cilium Helm values、Gateway API CRD、clusterwide policy、CNI/IPAM、加密和 Hubble 后端。namespace 团队只能修改本 namespace 的 CNP 与 Route,CiliumClusterwideNetworkPolicy、CiliumEnvoyConfig、CNI 和节点加密由平台角色管理。Kubernetes RBAC 的“能改策略”与数据面的“能访问服务”必须各做一组反例:低权限发布身份创建本 namespace CNP 成功、创建 clusterwide policy 失败;随后让同一身份对应的 workload 访问未授权服务仍被 drop。控制面写权限与数据面身份不是同一个授权域。
cilium-agent 需要 host network、加载 BPF 和修改节点网络的高权限,这是主机安全边界。节点池隔离、Pod Security 例外、镜像签名、agent API 与 RBAC 都应接受安全评审。SPIRE keys、WireGuard/IPsec key、Hubble Relay 证书、sysdump、flow log、Envoy config dump 和拓扑会暴露身份、服务关系与内部地址,不能提交 Git 或放在无审计的共享对象存储。cilium sysdump 应写入权限受限的临时目录,生成后记录摘要、访问者和保留期限,交付前清除 Secret data、证书私钥、Authorization/Cookie 与业务 payload;关闭工单时删除本地和对象存储副本,并用不存在或生命周期删除日志作为清理证据。
egress 也不能只靠 L7 声明。即使通过 Envoy 或 egress gateway 访问 example.test,恶意或未纳管 workload 仍可能尝试直连 IP。需要 CiliumNetworkPolicy、路由或防火墙把底层出口封住,并用“批准域名成功、错误 SNI/CA 失败、直连 IP 被 drop、出口不可用时 fail-close”建立正反证据。网格路由与底层网络共同封口,才称得上出口治理。
容量和架构选择要测双数据面
Cilium 减少了 per-Pod sidecar 的 L3/L4 资源,但成本没有消失:每节点 agent/Envoy、eBPF maps、identity、policy regeneration、Hubble 事件和控制器状态都需要容量。测试至少覆盖 Pod/Service/identity/policy 数量、节点密度、RPS、连接数、payload、纯 L3/L4 与 L7 redirect、Gateway/GAMMA、透明加密、遥测基数和故障恢复。
数据面记录 p50/p99、CPU/RSS、BPF map pressure、connection/reset/drop、Envoy queue/upstream;控制面记录 operator reconcile、policy regeneration、API QPS 与状态收敛;观测面记录 Relay/Prometheus 的丢样、active series 和存储费用。大批 Pod rollout、identity churn、策略更新、Envoy 重启和节点故障同时发生时的长尾,比空闲平均值更有选型价值。
当团队愿意让 Cilium 成为 CNI 和节点网络底座,希望用一套 identity/policy/Hubble 贯通 L3 到 L7,并能承担内核与节点运维时,它的整合收益最大。已有稳定 CNI、不愿扩大节点特权或首要目标是成熟的自动工作负载 mTLS 时,专用 sidecar 网格可能更稳妥。用户态组件主要采用 Apache License 2.0,BPF code templates 还有 GPL-2.0-only 与 BSD-2-Clause 双许可;开源许可同样不代表商业支持、认证与 SLA。
升级必须把 agent、Envoy 和 L7 连接放在一起
Cilium 只测试相邻 minor 的升级与回滚。每一跳先把当前 minor 升到最新 patch,保存旧 values,检查 renamed/deprecated 字段与 upgradeCompatibility。跨 chart 版本不要使用 --reuse-values,它会遗漏新 chart 默认值。agent、operator、Envoy 与 Hubble 应保持受支持的版本组合。
helm get values cilium -n kube-system -o yaml > cilium-values-before.yaml
cilium status --verbose
cilium connectivity test
NEXT_CILIUM_VERSION="<相邻 minor 的目标 patch>"
helm diff upgrade cilium oci://quay.io/cilium/charts/cilium \
--version "${NEXT_CILIUM_VERSION}" -n kube-system -f cilium-values-next.yaml
helm upgrade cilium oci://quay.io/cilium/charts/cilium \
--version "${NEXT_CILIUM_VERSION}" -n kube-system -f cilium-values-next.yaml
cilium status --wait
cilium connectivity test纯 L3/L4 连接在受支持升级中通常追求最小中断,经过 userspace proxy 的 L7 Policy、Gateway API/GAMMA 流量却可能中断并要求重连。混合版本窗口要分别验证同节点、跨节点、L3/L4、L7、DNS、policy deny 和 Hubble;回滚前确认没有启用旧版本无法解释的新 CRD 或字段。Helm rollback 让 Pod 镜像回退,不保证新状态自动兼容旧控制器。
CNI 迁移和卸载是最后一场网络变更
退出先盘点 Cilium 当前承担的职责:CNI/IPAM、kube-proxy replacement、NetworkPolicy、Gateway/GAMMA、Ingress、egress、加密、BGP/Cluster Mesh 和 Hubble。为每项建立替代设施,并在一批隔离节点上安装替代 CNI、迁移或重建 Pod。迁移期间若临时把 policy enforcement 设为 never,完成后必须恢复并验证 deny;遗留这个值会悄悄拆掉安全边界。
每个节点批次都必须重建 Pod,因为既有 Pod sandbox 不会因节点默认 CNI 改变而自动换网;再验证新 Pod 由替代 CNI 获得地址、Pod-to-Pod/Service/DNS 可用、旧新 NetworkPolicy 语义符合预期,然后才处理下一批。业务流量、Gateway、Hubble 告警与替代观测保留重叠窗口。确认所有业务 Pod 已重建且不再有 Cilium 管理的 workload 后,才执行 cilium uninstall 或 Helm uninstall;cni.uninstall 默认 false 是为了防止普通升级误删 CNI,不应在尚未准备替代网络时强行开启。
卸载后节点可能仍有 CNI config/binary、attached BPF programs、bpffs、tc filters、routes、links 与 named network namespaces。cilium-dbg post-uninstall-cleanup 是破坏性节点操作,只能在已排空、替代 CNI 已验证的 worker 上按 命令说明 逐台执行;绝不能在共享节点把 --all-state 当成普通清理参数。
最终证据不是 Helm release 消失,而是:全部业务 Pod 都已由替代 CNI 重建并稳定建网,Cilium endpoint 与流量归零,旧 Gateway/GAMMA 路由无消费者,NetworkPolicy 替代语义通过正反请求,节点无遗留 CNI/BPF/tc/route,SPIRE 与加密凭据已撤销,Hubble 后端不再抓取旧目标,相关 LB、Secret、CRD/CR 和云资源均已核销。隔离实验完成后先恢复反例,再只删除测试对象,不触碰共享 Gateway API CRD 或 Cilium 控制面:
kubectl -n mesh-lab scale deployment orders-v2 --replicas=1
kubectl -n mesh-lab rollout status deployment/orders-v2
kubectl delete namespace mesh-lab --wait=true
kubectl get namespace mesh-lab最后一条命令预期返回 NotFound;若 namespace 卡在 Terminating,先检查 finalizer,不能用强制删除掩盖残留。只有业务迁移证据和测试清理都闭环,Cilium 才真正从网络路径中退出。
