Cilium 运维学习与实验手册¶
适用对象:已经搭建过 Cilium VXLAN、Native Routing、Hubble 的 Kubernetes 运维人员。
0. 接下来到底要学什么¶
已经做过:
- VXLAN 模式:理解跨节点 Pod 流量可以通过 overlay 封装转发。
- Native Routing 模式:理解 PodCIDR 可以直接通过底层网络路由转发。
- Hubble:能观察 Pod 间、Pod 到外部、Service 相关流量。
接下来建议按这个顺序学:
- Cilium Network Policy:会做默认拒绝、精确放行、DNS/FQDN、HTTP L7。
- 排障命令体系:会用
cilium status、cilium connectivity test、hubble observe、cilium-dbg monitor。 - 升级与回滚:会看 Helm values、preflight、版本路径、风险点。
- kube-proxy replacement:理解 Service、NodePort、LoadBalancer 由谁处理。
- 监控告警:Prometheus/Grafana/Hubble metrics。
- Egress Gateway:固定出口 IP,满足防火墙白名单和审计需求。
- 裸金属入口:LB IPAM、L2 Announcements、BGP Control Plane,根据环境选择。
官方文档入口:
- Cilium 文档首页:https://docs.cilium.io/
- Network Policy:https://docs.cilium.io/en/stable/security/policy/
- Deny Policy:https://docs.cilium.io/en/stable/security/policy/deny/
- L7/DNS/FQDN Policy:https://docs.cilium.io/en/stable/security/policy/layer7/
- Troubleshooting:https://docs.cilium.io/en/stable/operations/troubleshooting/
- Hubble Setup:https://docs.cilium.io/en/stable/observability/hubble/setup/
- Metrics:https://docs.cilium.io/en/stable/observability/metrics/
- Upgrade:https://docs.cilium.io/en/stable/operations/upgrade/
- kube-proxy replacement:https://docs.cilium.io/en/stable/network/kubernetes/kubeproxy-free/
- Egress Gateway:https://docs.cilium.io/en/stable/network/egress-gateway/egress-gateway/
- BGP Control Plane:https://docs.cilium.io/en/stable/network/bgp-control-plane/bgp-control-plane/
- L2 Announcements:https://docs.cilium.io/en/stable/network/l2-announcements/
- LB IPAM:https://docs.cilium.io/en/stable/network/lb-ipam/
1. 实验前提¶
1.1 集群要求¶
建议用测试集群做实验,至少 2 个节点更好:
- Kubernetes 集群已安装 Cilium。
- 你有
kubectl管理权限。 - 已安装
ciliumCLI。 - 已安装
hubbleCLI,或者能进入 Cilium Pod 内执行 Hubble 相关命令。 - Cilium agent 状态正常。
检查:
kubectl get nodes -o wide
kubectl get pods -n kube-system -l k8s-app=cilium -o wide
cilium version
cilium status
预期:
cilium status显示 Cilium、Operator 正常。- 每个节点有一个 Cilium agent Pod。
- 如果启用了 Hubble,状态里能看到 Hubble OK。
1.2 不建议直接在生产做的实验¶
以下内容可能影响集群转发路径或生产流量,优先在测试/预发环境执行:
- 升级、降级、回滚。
- kube-proxy replacement 开关调整。
- Egress Gateway 全局启用。
- BGP Control Plane、L2 Announcements。
- Clusterwide 默认拒绝策略。
1.3 创建实验命名空间¶
部署基础服务:
kubectl -n cilium-lab run client --image=swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/curlimages/curl:8.8.0 --labels=app=client -- sleep 365d
kubectl -n cilium-lab run client2 --image=swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/curlimages/curl:8.8.0 --labels=app=client2 -- sleep 365d
kubectl -n cilium-lab create deployment web --image=swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io/nginx-slim:0.21
kubectl -n cilium-lab label deployment web app=web
kubectl -n cilium-lab expose deployment web --port=80 --target-port=80
kubectl -n cilium-lab get pods -o wide
kubectl -n cilium-lab get svc
验证没有策略时的默认连通性:
kubectl -n cilium-lab exec deploy/web -- sh -c 'echo ok > /usr/share/nginx/html/index.html'
kubectl -n cilium-lab exec client -- curl -sS --max-time 3 http://web
kubectl -n cilium-lab exec client2 -- curl -sS --max-time 3 http://web
预期:
理论点:
- Cilium 没有匹配策略时,默认允许 Pod 通信。
- 一旦某个 Pod 被 ingress 或 egress policy 选中,它会进入对应方向的 default-deny。
- Cilium 的 identity 基于标签,不是简单基于 Pod IP。Pod 重建后 IP 变了,只要标签没变,策略仍然有效。
2. 实验一:L3/L4 Ingress Policy¶
2.1 理论目标¶
你要掌握:
endpointSelector选择被保护的目标 Pod。fromEndpoints选择允许访问的来源 Pod。toPorts限制端口和协议。- 只要策略选中了目标 Pod,未显式允许的同方向流量就会被拒绝。
运维场景:
- 只允许某个业务访问数据库。
- 只允许网关访问后端服务。
- 阻断同命名空间内非授权横向访问。
2.2 应用策略¶
创建只允许 app=client 访问 app=web 的 80/TCP 策略:
kubectl apply -f - <<'EOF'
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-client-to-web
namespace: cilium-lab
spec:
endpointSelector:
matchLabels:
app: web
ingress:
- fromEndpoints:
- matchLabels:
app: client
toPorts:
- ports:
- port: "80"
protocol: TCP
EOF
2.3 验证¶
kubectl -n cilium-lab exec client -- curl -sS --max-time 3 http://web
kubectl -n cilium-lab exec client2 -- curl -sS --max-time 3 http://web
预期:
client成功。client2超时或连接失败。
进一步观察策略映射:
2.4 Hubble 验证¶
另开一个终端:
再执行:
你应该能看到 DROPPED 或 policy denied 相关记录。
2.5 结论¶
这个实验支撑的理论:
- 策略不是绑定 IP,而是绑定标签身份。
- Ingress policy 选中服务端 Pod 后,默认拒绝未匹配来源。
- L4 端口必须显式写清楚,否则容易出现“能 ping 但 curl 不通”或“同服务不同端口不通”。
3. 实验二:Egress Default Deny 与 DNS 放行¶
3.1 理论目标¶
你要掌握:
- Egress 策略保护的是“从 Pod 发出去”的方向。
- 一旦 Pod 被 egress policy 选中,未允许的外联会被拒绝。
- 很多外联依赖 DNS,放行 HTTP/HTTPS 但忘了 DNS,是常见故障。
运维场景:
- 限制业务 Pod 只能访问指定外部域名。
- 防止 Pod 随意访问公网。
- 排查“外网不通但 Service 正常”的问题。
3.2 先验证当前外联¶
kubectl -n cilium-lab exec client -- nslookup cilium.io
kubectl -n cilium-lab exec client -- curl -I --max-time 5 https://cilium.io
如果 curlimages/curl 镜像没有 nslookup,可用:
3.3 应用只允许 DNS 的 egress 策略¶
下面策略只允许 client 查询 kube-dns,不允许真正访问外部 HTTP/HTTPS:
kubectl apply -f - <<'EOF'
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: client-egress-dns-only
namespace: cilium-lab
spec:
endpointSelector:
matchLabels:
app: client
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s:k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
- port: "53"
protocol: TCP
rules:
dns:
- matchPattern: "*"
EOF
验证:
预期:
- DNS 可能解析成功。
- 连接
https://cilium.io失败,因为 443/TCP 没放行。
3.4 放行指定 FQDN 的 HTTPS¶
kubectl apply -f - <<'EOF'
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: client-egress-cilium-io
namespace: cilium-lab
spec:
endpointSelector:
matchLabels:
app: client
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s:k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
- port: "53"
protocol: TCP
rules:
dns:
- matchPattern: "*"
- toFQDNs:
- matchName: cilium.io
toPorts:
- ports:
- port: "443"
protocol: TCP
EOF
验证:
kubectl -n cilium-lab exec client -- curl -I --max-time 5 https://cilium.io
kubectl -n cilium-lab exec client -- curl -I --max-time 5 https://example.com
预期:
https://cilium.io成功。https://example.com失败。
3.5 结论¶
这个实验支撑的理论:
- Egress default-deny 后,DNS 和目标连接要分别放行。
toFQDNs依赖 DNS 代理学习域名解析结果。- 官方文档提醒,DNS L7 策略应优先拦截集群 DNS 服务,避免把不可信 DNS 响应纳入策略决策。
清理:
kubectl -n cilium-lab delete cnp client-egress-dns-only client-egress-cilium-io allow-client-to-web --ignore-not-found
4. 实验三:HTTP L7 Policy¶
4.1 理论目标¶
你要掌握:
- Cilium 可以在 L7 HTTP 层按方法和路径放行。
- L7 policy 会通过 Envoy 代理相关流量。
- HTTP L7 不匹配通常返回应用层拒绝,比如 HTTP 403,而不是简单网络超时。
运维场景:
- 只允许调用
/healthz、/public。 - 内部服务之间按 API 路径做最小权限。
- 审计某个接口是否被非授权服务访问。
4.2 准备测试页面¶
kubectl -n cilium-lab exec deploy/web -- sh -c 'echo public > /usr/share/nginx/html/public'
kubectl -n cilium-lab exec deploy/web -- sh -c 'echo private > /usr/share/nginx/html/private'
4.3 应用 L7 策略¶
只允许 app=client 对 app=web 执行 GET /public:
kubectl apply -f - <<'EOF'
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-client-get-public
namespace: cilium-lab
spec:
endpointSelector:
matchLabels:
app: web
ingress:
- fromEndpoints:
- matchLabels:
app: client
toPorts:
- ports:
- port: "80"
protocol: TCP
rules:
http:
- method: "GET"
path: "/public"
EOF
4.4 验证¶
kubectl -n cilium-lab exec client -- curl -i --max-time 3 http://web/public
kubectl -n cilium-lab exec client -- curl -i --max-time 3 http://web/private
kubectl -n cilium-lab exec client2 -- curl -i --max-time 3 http://web/public
预期:
client访问/public成功。client访问/private返回 403 或被拒绝。client2访问/public失败,因为来源身份不匹配。
4.5 结论¶
这个实验支撑的理论:
- L3/L4 决定谁可以连接到哪个端口。
- L7 决定连接到端口后可以访问哪个 HTTP 方法和路径。
- L7 policy 会引入代理链路,排障时要关注 Cilium Envoy 状态。
清理:
4.6 只允许baidu出战¶
client -->baidu
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: client-egress-fqdn-only
namespace: cilium-lab
spec:
endpointSelector:
matchLabels:
app: client
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s:k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
- port: "53"
protocol: TCP
rules:
dns:
- matchPattern: "*"
- toFQDNs:
- matchPattern: "*.baidu.com" #- matchName: baidu.com 为匹配单个不可以泛匹配
- matchPattern: "baidu.com"
toPorts:
- ports:
- port: "443"
protocol: TCP
4.7验证¶
kubectl -n cilium-lab exec client -- curl -sS --max-time 3 https://jd.com
curl: (28) Connection timed out after 3001 milliseconds
command terminated with exit code 28
kubectl -n cilium-lab exec client -- curl -sS --max-time 3 https://baidu.com
<a href="https://www.baidu.com/">Moved Permanently</a>.
5. 实验四:Deny Policy 优先级¶
5.1 理论目标¶
你要掌握:
- Deny policy 优先级高于 allow policy。
- Deny policy 适合做明确禁止,例如禁止来自 world、禁止某个命名空间访问敏感服务。
- 官方文档说明 Deny policy 不支持 L7 deny 和
toFQDNsdeny。
运维场景:
- 明确阻断某类东西,即使其它 allow policy 放行了。
- 做临时封禁。
- 做安全兜底。
5.2 先放行 client 和 client2 到 web¶
kubectl apply -f - <<'EOF'
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-all-lab-clients-to-web
namespace: cilium-lab
spec:
endpointSelector:
matchLabels:
app: web
ingress:
- fromEndpoints:
- matchLabels:
app: client
- matchLabels:
app: client2
toPorts:
- ports:
- port: "80"
protocol: TCP
EOF
验证两者都能访问:
kubectl -n cilium-lab exec client -- curl -sS --max-time 3 http://web
kubectl -n cilium-lab exec client2 -- curl -sS --max-time 3 http://web
5.3 增加 Deny Policy 禁止 client2¶
kubectl apply -f - <<'EOF'
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: deny-client2-to-web
namespace: cilium-lab
spec:
endpointSelector:
matchLabels:
app: web
ingressDeny:
- fromEndpoints:
- matchLabels:
app: client2
EOF
验证:
kubectl -n cilium-lab exec client -- curl -sS --max-time 3 http://web
kubectl -n cilium-lab exec client2 -- curl -sS --max-time 3 http://web
预期:
client成功。client2失败。
5.4 结论¶
这个实验支撑的理论:
- 多条 allow policy 不能覆盖 deny policy。
- 当你看到“明明有 allow 但流量还是被拒绝”,要检查是否存在 deny。
清理:
kubectl -n cilium-lab delete cnp allow-all-lab-clients-to-web deny-client2-to-web --ignore-not-found
6. 实验五:Hubble 观测与排障¶
6.1 理论目标¶
你要掌握:
- Hubble 看的是 Cilium 管理端点的 flow。
- 它可以告诉你流量方向、来源 identity、目标 identity、协议、端口、是否转发、是否丢弃、被什么策略影响。
- 官方排障文档强调,Pod 必须由 Cilium 管理才可被 Hubble 观测。
运维场景:
- 业务报“服务不通”,你要判断是 DNS、策略、Service、节点、外部网络哪一层。
- 安全报“某 Pod 访问外网”,你要快速定位来源和目的地。
6.2 基础状态¶
如果本地 hubble 无法连接 Relay:
6.3 观察 namespace 流量¶
指定 Pod:
只看 drop:
只看 HTTP:
6.4 制造一次策略拒绝¶
应用只允许 client 到 web,然后用 client2 访问:
kubectl apply -f - <<'EOF'
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: hubble-drop-demo
namespace: cilium-lab
spec:
endpointSelector:
matchLabels:
app: web
ingress:
- fromEndpoints:
- matchLabels:
app: client
toPorts:
- ports:
- port: "80"
protocol: TCP
EOF
观察:
触发:
6.5 Cilium agent 本地观察¶
进入任意 Cilium Pod:
kubectl -n kube-system exec ds/cilium -- cilium-dbg status --verbose
kubectl -n kube-system exec ds/cilium -- cilium-dbg endpoint list
kubectl -n kube-system exec ds/cilium -- cilium-dbg monitor --type drop
说明:
hubble observe更适合日常按 namespace/pod/service 过滤。cilium-dbg monitor --type drop更底层,适合确认 datapath 丢包原因。
6.6 结论¶
这个实验支撑的理论:
- Cilium 排障不要只看 Kubernetes Event。
- 先看 flow verdict,再看策略,再看 endpoint identity,再看 datapath drop reason。
- Hubble 能把“网络不通”转换成“谁访问谁、在哪一层被拒绝”。
清理:
7. 实验六:标准连通性测试¶
7.1 理论目标¶
你要掌握:
cilium connectivity test是 Cilium 官方推荐的连通性验证工具。- 它会自动创建测试 workload,覆盖 Pod-to-Pod、Service、DNS、NetworkPolicy、NodePort 等场景。
- 升级前后、变更前后都应该跑。
7.2 执行测试¶
如果你的集群没有公网访问,部分镜像拉取或外部访问测试可能失败。可以先记录失败项,区分是环境限制还是 Cilium 问题。
7.3 变更前后对比¶
建议每次重大变更都记录:
cilium status > cilium-status-before.txt
cilium connectivity test | tee cilium-connectivity-before.txt
变更后:
cilium status > cilium-status-after.txt
cilium connectivity test | tee cilium-connectivity-after.txt
7.4 结论¶
这个实验支撑的理论:
- 运维变更需要可重复验证,而不是凭感觉。
- connectivity test 可以作为升级、参数调整、内核升级后的冒烟测试。
8. 实验七:升级与回滚演练¶
风险等级:高。只建议测试/预发环境执行。
官方升级文档要求先完整阅读目标版本升级说明,并执行 preflight。官方文档也说明,经过测试的升级/回滚路径通常是相邻 minor 版本。
8.1 理论目标¶
你要掌握:
- Cilium 升级不只是换镜像,还涉及 CRD、agent、operator、Envoy、Helm values。
- 升级前要保存现有 values。
- 不应盲目使用
helm upgrade --reuse-values,因为旧 values 可能与新 chart 行为不匹配。 - kube-proxy-free 集群生成 preflight 时需要设置 Kubernetes API Server 地址和端口。
8.2 记录当前状态¶
cilium version
cilium status
helm -n kube-system list
helm -n kube-system get values cilium -o yaml > cilium-values-current.yaml
helm -n kube-system get manifest cilium > cilium-manifest-current.yaml
kubectl get ciliumnetworkpolicies --all-namespaces
kubectl get ciliumclusterwidenetworkpolicies
cilium connectivity test | tee cilium-connectivity-before-upgrade.txt
8.3 查看当前 Helm values 中的关键项¶
重点检查:
grep -E "tunnel|routingMode|kubeProxyReplacement|hubble|ipam|bpf|egressGateway|operator|envoy" cilium-values-current.yaml
如果 PowerShell:
Select-String -Path .\cilium-values-current.yaml -Pattern "tunnel|routingMode|kubeProxyReplacement|hubble|ipam|bpf|egressGateway|operator|envoy"
8.4 Preflight¶
示例,实际版本请替换为目标版本:
helm repo add cilium https://helm.cilium.io/
helm repo update
helm install cilium-preflight cilium/cilium \
--version <target-version> \
--namespace kube-system \
--set preflight.enabled=true \
--set agent=false \
--set operator.enabled=false
检查:
kubectl -n kube-system get ds cilium cilium-pre-flight-check
kubectl -n kube-system get deploy cilium-pre-flight-check
预期:
cilium-pre-flight-checkDaemonSet READY 数量等于 Cilium DaemonSet READY 数量。- preflight Deployment READY 为
1/1。
清理 preflight:
8.5 升级演练¶
不要直接复制这条命令到生产。先根据你的 cilium-values-current.yaml 和目标版本 release notes 修正 values。
helm upgrade cilium cilium/cilium \
--version <target-version> \
--namespace kube-system \
-f cilium-values-current.yaml
观察:
kubectl -n kube-system rollout status ds/cilium
kubectl -n kube-system rollout status deploy/cilium-operator
cilium status
cilium connectivity test | tee cilium-connectivity-after-upgrade.txt
8.6 回滚思路¶
生产前必须准备:
- 当前 chart 版本。
- 当前 image 版本。
- 当前 Helm values。
- 当前 Cilium CRD 版本和备份。
- 回滚验证命令。
回滚一般使用:
helm -n kube-system history cilium
helm -n kube-system rollback cilium <revision>
kubectl -n kube-system rollout status ds/cilium
cilium status
cilium connectivity test
8.7 结论¶
这个实验支撑的理论:
- Cilium 是集群网络平面,升级失败影响面很大。
- 升级必须可验证、可回滚、可对比。
- 版本路径和 preflight 不是形式主义,是为了提前发现镜像、CRD、策略兼容问题。
9. 实验八:kube-proxy replacement¶
风险等级:中到高。不要在生产临时开关。
如果你的集群已经开启 kube-proxy replacement,本实验只做验证;如果没开启,先在测试集群安装或重装时启用。
9.1 理论目标¶
你要掌握:
- kube-proxy 原本处理 Kubernetes Service 转发。
- Cilium kube-proxy replacement 开启后,ClusterIP、NodePort、LoadBalancer、externalIPs、HostPort 等 Service 行为由 Cilium eBPF datapath 处理。
- Service 故障排查时,要同时看 Kubernetes Service/EndpointSlice 和 Cilium service map。
9.2 查看是否启用¶
PowerShell:
kubectl -n kube-system exec ds/cilium -- cilium-dbg status --verbose | Select-String -Pattern "kube|proxy|replacement"
9.3 ClusterIP 验证¶
kubectl -n cilium-lab get svc web -o wide
kubectl -n cilium-lab get endpoints web -o wide
kubectl -n cilium-lab get endpointslice -l kubernetes.io/service-name=web -o wide
kubectl -n cilium-lab exec client -- curl -sS --max-time 3 http://web
查看 Cilium service:
9.4 NodePort 验证¶
创建 NodePort:
kubectl -n cilium-lab patch svc web -p '{"spec":{"type":"NodePort"}}'
kubectl -n cilium-lab get svc web
拿到 Node IP 和 NodePort 后,从集群外或节点上访问:
观察:
hubble observe --namespace cilium-lab --service web
kubectl -n kube-system exec ds/cilium -- cilium-dbg service list
清理:
9.5 结论¶
这个实验支撑的理论:
- Service 不通时不要只查 Pod。
- 需要按
Service -> EndpointSlice -> Cilium service map -> Hubble flow -> node datapath顺序定位。 - kube-proxy replacement 开启后,节点内核、Cilium 配置和 Service 类型都会影响结果。
10. 实验九:Prometheus Metrics 与告警¶
10.1 理论目标¶
你要掌握:
- Hubble 用于实时流量观察,Prometheus 用于长期趋势和告警。
- Cilium agent、operator、Hubble 都可以暴露 metrics。
- 生产中要监控 agent 健康、drop、policy verdict、endpoint 数量、IPAM、API 延迟、Hubble flow。
10.2 查看是否启用 metrics¶
PowerShell:
10.3 Helm values 示例¶
不同版本 values 可能有差异,先以 helm show values cilium/cilium --version <version> 为准。常见启用方式:
helm upgrade cilium cilium/cilium \
--namespace kube-system \
--version <your-version> \
-f cilium-values-current.yaml \
--set prometheus.enabled=true \
--set operator.prometheus.enabled=true \
--set hubble.metrics.enabled="{dns,drop,tcp,flow,port-distribution,icmp,http}"
10.4 验证 metrics service¶
kubectl -n kube-system get svc | grep -E "cilium|hubble"
kubectl -n kube-system get pods -l k8s-app=cilium -o wide
PowerShell:
如果你使用 Prometheus Operator,还需要确认是否创建 ServiceMonitor:
10.5 建议告警项¶
生产建议至少覆盖:
- Cilium agent Pod 非 Ready。
- Cilium operator 非 Ready。
- Cilium endpoint regeneration 失败。
- Drop 流量突增。
- Policy denied 突增。
- Hubble Relay 不可用。
- IPAM 可用地址不足。
- Cilium API error 或 Kubernetes API client error 突增。
- 节点上 Cilium DaemonSet desired 与 ready 不一致。
10.6 实验验证告警数据¶
复用实验五制造 drop:
然后查询 Prometheus 中 Hubble/Cilium drop 相关指标。指标名随版本和启用项可能变化,原则是用 Prometheus UI 搜索:
10.7 结论¶
这个实验支撑的理论:
- Hubble 适合现场分析,Prometheus 适合趋势和告警。
- 运维不能只在故障发生后手动
hubble observe,要提前把关键指标接入告警。
11. 实验十:Egress Gateway 固定出口 IP¶
风险等级:中到高。需要测试集群。
官方文档说明 Egress Gateway 需要启用 BPF masquerading 和 kube-proxy replacement;并且 gateway node 上的 egress IP 必须真实配置在网卡上。
11.1 理论目标¶
你要掌握:
- Egress Gateway 可以让指定 Pod 访问指定外部 CIDR 时,从指定节点和指定源 IP 出口。
- 它适合对接传统防火墙白名单。
- 如果没有匹配 gateway node,或 egress IP 不存在,匹配流量可能被丢弃。
- 新 Pod 创建后,策略生效有短暂延迟,刚启动瞬间的流量可能还没有按 gateway 出口。
11.2 检查前置条件¶
cilium status
helm -n kube-system get values cilium -o yaml | grep -E "egressGateway|bpf.masquerade|kubeProxyReplacement"
PowerShell:
helm -n kube-system get values cilium -o yaml | Select-String -Pattern "egressGateway|bpf.masquerade|kubeProxyReplacement"
预期:
egressGateway.enabled=truebpf.masquerade=truekubeProxyReplacement=true或对应版本支持的开启值
11.3 标记 gateway node¶
选择一个节点作为出口:
确认该节点有可用于出口的 IP:
如果你指定 egressIP,该 IP 必须已经配置在该节点网卡上。
11.4 部署外部回显服务¶
你需要一个能显示来源 IP 的外部服务。可以使用:
- 公司测试机上的 nginx,记录
$remote_addr。 - 云主机上运行
tcpdump或简单 HTTP 服务。 - 测试环境可访问的
ifconfig.me、icanhazip.com等公网服务。
示例:
记录未启用 Egress Gateway policy 前的出口 IP。
11.5 创建 Egress Gateway Policy¶
以下示例把 app=client 访问 203.0.113.0/24 的流量经由带 egress-gw=true 标签的节点出口。请替换目的 CIDR 和 egress IP。
kubectl apply -f - <<'EOF'
apiVersion: cilium.io/v2
kind: CiliumEgressGatewayPolicy
metadata:
name: client-egress-gateway
spec:
selectors:
- podSelector:
matchLabels:
app: client
namespaceSelector:
matchLabels:
purpose: cilium-lab
destinationCIDRs:
- "203.0.113.0/24"
egressGateway:
nodeSelector:
matchLabels:
egress-gw: "true"
egressIP: "192.0.2.10"
EOF
注意:
203.0.113.0/24和192.0.2.10是文档示例地址,不能直接用于真实环境。- 如果不指定
egressIP,Cilium 会使用默认路由接口上的地址,具体行为以版本文档为准。
11.6 验证¶
从 client 访问目标外部服务:
在外部服务上确认来源 IP 是指定 egress IP。
Hubble 观察:
如果不通,检查:
kubectl get ciliumegressgatewaypolicies
kubectl describe ciliumegressgatewaypolicy client-egress-gateway
kubectl get nodes --show-labels | grep egress-gw
kubectl -n kube-system exec ds/cilium -- cilium-dbg monitor --type drop
11.7 结论¶
这个实验支撑的理论:
- Egress Gateway 是“哪些 Pod 到哪些外部 CIDR 从哪个节点哪个 IP 出去”。
- 它不是简单的 NetworkPolicy,也不是 Service。
- 出口 IP 必须和底层网络真实匹配,Cilium 不能凭空让上游网络认识一个不存在的源 IP。
12. 实验十一:裸金属入口流量选择¶
这部分取决于你的环境。你不是网工,但需要能和网络同事讲清楚你需要什么。
12.1 三种常见方案¶
方案 A:云厂商 LoadBalancer¶
适合:
- EKS、GKE、AKS 或私有云 CCM。
- 你创建
type: LoadBalancer,云平台分配 LB。
你要学:
- Service annotations。
- 安全组/防火墙。
- 后端健康检查。
方案 B:LB IPAM + L2 Announcements¶
适合:
- 小型裸金属。
- 没有 BGP。
- 同一个二层网络内通过 ARP/NDP 宣告 LoadBalancer IP。
风险:
- L2 Announcements 在部分版本中仍有 beta 特性,生产前要验证 failover。
- 不适合复杂三层网络。
方案 C:LB IPAM + BGP Control Plane¶
适合:
- 裸金属机房。
- 上游交换机/路由器支持 BGP。
- 希望 LoadBalancer IP 或 PodCIDR 被网络设备学习。
你要和网工确认:
- ASN。
- peer IP。
- 宣告哪些 CIDR。
- 是否需要 BGP password。
- 路由收敛时间。
- 网络设备是否过滤前缀。
12.2 LB IPAM 实验¶
创建一个 LoadBalancer IP Pool。请使用你测试网络中真实可用、不会冲突的地址段。
kubectl apply -f - <<'EOF'
apiVersion: cilium.io/v2alpha1
kind: CiliumLoadBalancerIPPool
metadata:
name: lab-lb-pool
spec:
blocks:
- cidr: "192.168.5.200/28"
EOF
把 web 改成 LoadBalancer:
kubectl -n cilium-lab patch svc web -p '{"spec":{"type":"LoadBalancer"}}'
kubectl -n cilium-lab get svc web -w
预期:
-
Service 获得一个 EXTERNAL-IP。
-
是否能从外部访问,取决于你是否配置了 L2 Announcements、BGP 或云 LB。
L2 宣告策略
#lab-l2-announcement.yaml
apiVersion: cilium.io/v2alpha1
kind: CiliumL2AnnouncementPolicy
metadata:
name: lab-lb-l2
spec:
serviceSelector:
matchLabels:
app: web
nodeSelector:
matchLabels:
kubernetes.io/os: linux
interfaces:
- "^ens18$"
loadBalancerIPs: true
这个策略表示:
- 只为 app=web 的 Service 宣告 VIP
- 只在 Linux 节点上宣告
- 通过 ens18 网卡发送 ARP
- 宣告 LoadBalancer IP
给 Cilium Agent 增加 Lease 权限
L2 leader election 需要访问 Kubernetes Lease。执行下面这个 JSON Patch:
kubectl patch clusterrole cilium \
--type=json \
--patch '[
{
"op": "add",
"path": "/rules/-",
"value": {
"apiGroups": ["coordination.k8s.io"],
"resources": ["leases"],
"verbs": ["create", "get", "update", "patch"]
}
}
]'
可以检查权限:
kubectl auth can-i get leases \
--as=system:serviceaccount:kube-system:cilium \
-n kube-system
应该返回:
yes
———
### 6. 重启 Cilium 使配置生效
kubectl -n kube-system rollout restart daemonset/cilium
kubectl -n kube-system rollout status daemonset/cilium \
--timeout=180s
———
### 7. 完整验证
kubectl -n cilium-lab get svc web
kubectl get ciliuml2announcementpolicy
kubectl -n kube-system get lease \
cilium-l2announce-cilium-lab-web \
-o jsonpath='{.spec.holderIdentity}{"\n"}'
curl -i --connect-timeout 3 http://192.168.5.192/
预期:
HTTP/1.1 200 OK
清理:
kubectl -n cilium-lab patch svc web -p '{"spec":{"type":"ClusterIP"}}'
kubectl delete ciliuml2announcementpolicy lab-l2-policy --ignore-not-found
kubectl delete ciliumbgpclusterconfig lab-bgp --ignore-not-found
kubectl delete ciliumloadbalancerippool lab-lb-pool --ignore-not-found
12.3 L2 Announcements 理论验证¶
如果你要走 L2 Announcements,需要创建 CiliumL2AnnouncementPolicy。实际字段请按当前版本官方文档确认。
验证思路:
kubectl get ciliuml2announcementpolicies
kubectl -n cilium-lab get svc web -o wide
arp -a | grep <loadbalancer-ip>
curl -sS --max-time 3 http://<loadbalancer-ip>
重点观察:
- 哪个节点响应 ARP。
- 节点故障后,LoadBalancer IP 是否切换到其它节点。
- 切换期间客户端是否短暂中断。
12.4 BGP Control Plane 理论验证¶
如果你要走 BGP,需要网络设备配合。你的目标不是精通 BGP,而是能交付一张变更表:
Kubernetes cluster name:
Cilium version:
Cilium node IPs:
Local ASN:
Peer ASN:
Peer IP:
Advertised LB CIDR:
Advertised PodCIDR:
BGP password:
Expected route next-hop:
Rollback method:
验证:
kubectl get ciliumbgpclusterconfig
kubectl get ciliumbgpadvertisements
kubectl get ciliumbgppeerconfigs
kubectl -n cilium-lab get svc web -o wide
在网络设备侧验证:
12.5 结论¶
这个实验支撑的理论:
- LB IPAM 只负责给 Service 分配 IP,不负责让外部网络一定能访问这个 IP。
- L2 Announcements 通过二层邻居发现解决入口可达。
- BGP 通过三层路由宣告解决入口可达。
- 运维要能判断“IP 已分配但外部不通”到底是 Cilium、L2、BGP、ACL 还是防火墙问题。
13. 运维排障路径¶
13.1 Pod 到 Pod 不通¶
按顺序查:
kubectl get pods -n <ns> -o wide
kubectl get svc,endpoints,endpointslice -n <ns>
cilium status
hubble observe --namespace <ns> --follow
hubble observe --namespace <ns> --verdict DROPPED
kubectl get cnp,ccnp --all-namespaces
kubectl -n kube-system exec ds/cilium -- cilium-dbg endpoint list
kubectl -n kube-system exec ds/cilium -- cilium-dbg monitor --type drop
判断:
- 没有 flow:请求可能没发出,或 Pod 不由 Cilium 管理。
DROPPED且 policy denied:查 NetworkPolicy/CNP/CCNP。- Service 有问题:查 EndpointSlice、selector、Cilium service list。
- 跨节点才不通:查 tunnel/native routing、节点防火墙、MTU、路由。
13.2 Pod 到外网不通¶
按顺序查:
kubectl -n <ns> exec <pod> -- nslookup <domain>
kubectl -n <ns> exec <pod> -- curl -v --max-time 5 https://<domain>
hubble observe --namespace <ns> --pod <pod> --follow
hubble observe --namespace <ns> --pod <pod> --verdict DROPPED
kubectl get cnp,ccnp --all-namespaces
判断:
- DNS 不通:查 DNS egress policy、CoreDNS、kube-dns 标签。
- DNS 通但 TCP 不通:查 egress 443/TCP、toFQDNs、NAT、Egress Gateway。
- 只有特定域名不通:查 FQDN 解析、TTL、Cilium DNS proxy。
- 外部只允许固定源 IP:查 Egress Gateway 或节点 SNAT。
13.3 Service 不通¶
按顺序查:
kubectl -n <ns> get svc <svc> -o yaml
kubectl -n <ns> get endpoints <svc> -o wide
kubectl -n <ns> get endpointslice -l kubernetes.io/service-name=<svc> -o yaml
kubectl -n kube-system exec ds/cilium -- cilium-dbg service list
hubble observe --namespace <ns> --service <svc> --follow
判断:
- Service selector 错:EndpointSlice 为空。
- Endpoint 有但不通:查策略、Pod readiness、Cilium service map。
- NodePort/LoadBalancer 不通:查 kube-proxy replacement、LB IPAM、L2/BGP、节点防火墙。
13.4 策略生效不符合预期¶
按顺序查:
kubectl get networkpolicy --all-namespaces
kubectl get cnp --all-namespaces
kubectl get ccnp
kubectl describe cnp -n <ns> <name>
kubectl -n kube-system exec ds/cilium -- cilium-dbg endpoint list
hubble observe --namespace <ns> --verdict DROPPED --follow
重点:
- 标签是否匹配。
- namespace label 是否匹配。
- 是否有 deny policy。
- ingress 和 egress 是否只写了一边。
- DNS 是否被遗漏。
- CNP 与 Kubernetes NetworkPolicy 是否叠加。
14. 生产上线检查清单¶
14.1 安装模式¶
- 明确使用 VXLAN、Geneve、Native Routing 或云厂商 ENI/IPAM。
- 记录关键 Helm values。
- 记录 PodCIDR、ServiceCIDR、节点网段。
- 明确 MTU。
- 明确是否启用 kube-proxy replacement。
14.2 策略¶
- 是否存在默认拒绝策略。
- 是否有 DNS 放行模板。
- 是否区分 namespace 边界。
- 是否允许必要的 kube-system 流量。
- 是否有 deny policy。
- 是否有策略变更审批和回滚方式。
14.3 观测¶
- Cilium status 可采集。
- Hubble Relay 正常。
- Prometheus metrics 已启用。
- Grafana dashboard 已导入。
- drop/policy denied 有告警。
- Cilium agent/operator Ready 有告警。
14.4 变更¶
- 变更前保存 Helm values。
- 变更前跑 connectivity test。
- 变更后跑 connectivity test。
- 有 rollback 命令和 values。
- 知道哪些变更会滚动重启 Cilium agent。
14.5 外部访问¶
- LoadBalancer IP 从哪里分配。
- 外部网络如何到达这个 IP。
- L2/BGP/云 LB 哪个组件负责可达性。
- 节点防火墙是否允许。
- 上游 ACL 是否允许。
14.6 出口访问¶
- 普通 SNAT 还是 Egress Gateway。
- 固定出口 IP 是否真实配置在节点上。
- 外部防火墙是否放行该 IP。
- 出口策略是否覆盖 DNS 和目标端口。
15. 建议学习路线¶
第一周:
- 重做实验一到实验六。
- 目标:能解释 default-deny、allow、deny、DNS/FQDN、L7、Hubble drop。
第二周:
- 做升级演练和 connectivity test。
- 目标:能写出 Cilium 升级 SOP。
第三周:
- 做 kube-proxy replacement 验证和 Service 排障。
- 目标:能处理 ClusterIP、NodePort、LoadBalancer 不通。
第四周:
- 根据公司环境选择 Egress Gateway、L2 Announcements 或 BGP。
- 目标:能处理固定出口和入口 IP 可达性。
16. 最终能力标准¶
你学完后应该能做到:
- 看一条 Hubble flow,判断来源、目标、协议、端口、结果。
- 写一个 namespace 级别的默认拒绝策略,并放行必要 DNS 和业务访问。
- 解释为什么
toFQDNs需要 DNS 策略配合。 - 判断 deny policy 为什么覆盖 allow policy。
- 在升级 Cilium 前保存 values、跑 preflight、跑 connectivity test。
- 判断 Service 不通是 selector、EndpointSlice、策略、Cilium service map 还是外部网络问题。
- 知道什么时候该找网工:BGP peer 不起来、上游路由没收到、ACL 拦截、二层 ARP/NDP 异常。
- 知道什么时候不用找网工:标签写错、策略 default-deny、DNS 没放行、Service selector 错、Cilium agent 异常。
17. 清理实验环境¶
确认不再需要实验资源后:
kubectl delete namespace cilium-lab
kubectl delete ciliumegressgatewaypolicy client-egress-gateway --ignore-not-found
kubectl delete ciliumloadbalancerippool lab-lb-pool --ignore-not-found
kubectl delete ciliuml2announcementpolicy lab-l2-policy --ignore-not-found
kubectl delete ciliumbgpclusterconfig lab-bgp --ignore-not-found
如果给节点打过标签:
18. 附录:最小命令速查¶
cilium version
cilium status
cilium connectivity test
cilium hubble port-forward
hubble status
hubble observe --follow
hubble observe --namespace <ns> --verdict DROPPED
kubectl -n kube-system exec ds/cilium -- cilium-dbg status --verbose
kubectl -n kube-system exec ds/cilium -- cilium-dbg endpoint list
kubectl -n kube-system exec ds/cilium -- cilium-dbg service list
kubectl -n kube-system exec ds/cilium -- cilium-dbg monitor --type drop
helm -n kube-system get values cilium -o yaml
helm -n kube-system history cilium