声明一个没有 kube-proxy 的集群
目标
用 values 文件准确声明取代 kube-proxy 的 Cilium 配置,通过真实工作负载和 Service 确认后端形成过程,并编写脚本自行证明“确实没有 kube-proxy”。
为什么重要
看似只需一行 kubeProxyReplacement: true,实际并非如此。缺少 k8sServiceHost 时,Cilium 启动期间找不到 API 服务器,整个集群无法启动;在已有集群中移除 kube-proxy 再迁移时,节点残留的 KUBE- chain 会与 eBPF 路径冲突。因此实践中的标准做法是从一开始就不安装它,并通过统计 chain 数量证明结果。
本实验分三部分:values 文件说明“启用什么”,实际 apply 资源说明“标签与 selector 如何形成后端”,验证脚本说明“如何证明”。第三部分尤其重要:文档声明的功能与节点上真正运行的功能是两个命题。
在 /root/cca-config/ 下编写 Cilium Helm values 与脚本,并实际 apply Kubernetes 基础资源。
步骤
- 创建 namespace
cca-net。 - 创建
/root/cca-config/cilium-values.yaml,顶层写入kubeProxyReplacement: true、k8sServiceHost: 10.0.0.120、k8sServicePort: 6443和ipam.mode: kubernetes。 - 在同一文件继续加入
routingMode: tunnel、tunnelProtocol: vxlan、bpf.masquerade: true、l7Proxy: true、encryption.enabled: true、encryption.type: wireguard。 - 给节点
lab-node-0、lab-node-1添加cca.homelab/tier=gpu,给lab-node-2添加cca.homelab/tier=cpu。 - 在 namespace
cca-net部署 3 replicas 的 Deploymentweb。Pod 标签为app=web,镜像为nginx:1.27-alpine,Pod spec 的nodeSelector为cca.homelab/tier: gpu。 - 在同一 namespace 创建 Service
web。类型为ClusterIP,port为80,targetPort为8080,selector 为app=web。 - 编写
/root/cca-config/verify-kubeproxy-free.sh并赋予执行权限。脚本必须:(1) 用kubectl统计 kube-system 中 kube-proxy Pod 数量;(2) 从iptables-save输出统计KUBE-chain 数量;(3) 从cilium状态确认 KubeProxyReplacement。任一数量非 0 时输出消息并以exit 1结束。
提示
- values 文件不要把层级写成
ipam.mode,应使用真实 YAML 层级:ipam:下写mode: kubernetes。 - 标签 key 含斜杠时,可直接写成
kubectl label node lab-node-0 cca.homelab/tier=gpu。 - Pod 为 Pending 时,在
kubectl describe pod事件中检查 nodeSelector 不匹配。 - 常见错误 1:省略 Service 的
targetPort,使其与port相同。容器监听端口与 Service 端口是两回事。 - 常见错误 2:验证脚本只输出数量却不判断。必须与 0 比较并制造失败,才算验证。
创建实验 namespace
创建 namespace cca-net。
这是最简单的第一步,只需确保名称准确。
写入 kube-proxy 替代核心值
创建 /root/cca-config/cilium-values.yaml,顶层写入 kubeProxyReplacement: true、k8sServiceHost: 10.0.0.120、k8sServicePort: 6443 和 ipam.mode: kubernetes。
没有 kube-proxy 时,Cilium 本应解析 API 服务器 VIP,但启动时它尚未运行,因此必须提供真实地址。IPAM 请选择直接使用节点 PodCIDR 的模式。
填写数据路径选项
在同一文件继续加入 routingMode: tunnel、tunnelProtocol: vxlan、bpf.masquerade: true、l7Proxy: true、encryption.enabled: true、encryption.type: wireguard。
继续写在同一文件。家庭实验的 underlay 不知道 PodCIDR 路由,因此需要封装;SNAT 也应交给 eBPF。使用 HTTP method 级策略还需打开相应开关。
给节点添加规格标签
给节点 lab-node-0、lab-node-1 添加 cca.homelab/tier=gpu,给 lab-node-2 添加 cca.homelab/tier=cpu。
对 Kubernetes 而言 GPU 只是资源数量。要表达有意义的调度意图,必须由人添加标签。注意 key 中的斜杠。
部署带调度约束的工作负载
在 namespace cca-net 部署 3 replicas 的 Deployment web。Pod 标签为 app=web,镜像为 nginx:1.27-alpine,Pod spec 的 nodeSelector 为 cca.homelab/tier: gpu。
把 nodeSelector 放入 Pod template。它必须与上一步的标签 key/value 完全一致,否则 Pod 会保持 Pending。
用 Service 汇聚并检查后端
在同一 namespace 创建 Service web。类型为 ClusterIP,port 为 80,targetPort 为 8080,selector 为 app=web。
Service 端口与容器端口可以不同。selector 与 Pod 标签不一致时,Service 虽能创建但后端为 0,这是 kube-proxy 和 eBPF 都无法转发的常见原因。
编写验证脚本
编写 /root/cca-config/verify-kubeproxy-free.sh 并赋予执行权限。脚本必须:(1) 用 kubectl 统计 kube-system 中 kube-proxy Pod 数量;(2) 从 iptables-save 输出统计 KUBE- chain 数量;(3) 从 cilium 状态确认 KubeProxyReplacement。任一数量非 0 时输出消息并以 exit 1 结束。
必须测量而不是宣称。统计 kube-proxy Pod 和节点 KUBE- chain 是否为 0,同时检查 Cilium 状态;失败时返回非 0 exit code,并确保文件可执行。