Kubernetes The Hard Way 实战:为集群手动配置 Pod 网络路由(Provisioning Pod Network Routes)
本篇基于 kubernetes-the-hard-way 教程中的“Provisioning Pod Network Routes”实验,讲解在纯静态部署(无脚本、无 CNI 自动编排)的 Kubernetes 集群中,为什么需要为每个 worker 节点手动添加 Pod CIDR 路由,以及如何利用 machines.txt 机器数据库配合 ip route 命令完成跨节点 Pod 网络互通。读完本文,你可以理解 Kubernetes 网络模型中“每个节点一个 Pod 网段”的设计,并掌握路由规划、配置与验证的完整操作流程。
为什么需要手动配置 Pod 网络路由
在 Kubernetes 的网络模型中,Pod 被调度到某个节点后,会获得一个来自该节点 Pod CIDR 范围的 IP 地址。但在完成本实验之前,同一节点上的 Pod 可以通信,不同节点上的 Pod 之间却无法通信——原因是各节点之间缺少把对端 Pod 网段指向对端节点内部 IP 的网络路由。
本实验的目标就是:为每个 worker 节点创建一条路由,把“节点 A 的 Pod CIDR 网段 → 经由节点 A 的内部 IP 转发”这一映射写入其余节点的 Linux 路由表。
需要说明的是,这并非实现 Kubernetes 网络模型的唯一方式,Flannel、Calico 等 CNI 插件可以自动完成这些路由/Overlay 工作。本教程(以及 README 的定位)刻意选择“the hard way”,即用最原始的手工方式完成每一步,目的是让学习者彻底理解集群引导的每个底层环节。
前置条件:理解 machines.txt 机器数据库
本实验所有操作都在 jumpbox 上执行,依赖前面实验创建的 machines.txt 文件(见 Provisioning Compute Resources)。该文件作为“机器数据库”,每行一台机器,字段格式为:
IPV4_ADDRESS FQDN HOSTNAME POD_SUBNET
- 第 1 列
IPV4_ADDRESS:机器内部 IP 地址; - 第 2 列
FQDN:完全限定域名,如node-0.kubernetes.local; - 第 3 列
HOSTNAME:主机名,如node-0; - 第 4 列
POD_SUBNET:分配给该节点用于 Pod 地址的唯一 IP 网段。
教程示例中的机器数据库(IP 已做掩码处理)如下:
XXX.XXX.XXX.XXX server.kubernetes.local server
XXX.XXX.XXX.XXX node-0.kubernetes.local node-0 10.200.0.0/24
XXX.XXX.XXX.XXX node-1.kubernetes.local node-1 10.200.1.0/24
注意 server(控制平面节点)没有 POD_SUBNET 列——它只承载控制平面组件,不运行 Pod,因此无需为其配置 Pod 路由。
Pod 网段从哪里来:CNI bridge 配置与集群 CIDR
理解路由之前,值得先看看 Pod IP 实际是如何分配的。在 worker 节点引导阶段(Bootstrapping the Kubernetes Worker Nodes),教程把 CNI 配置模板下发到每台节点,并用 sed 将 SUBNET 占位符替换为该节点在 machines.txt 中的 POD_SUBNET:
for HOST in node-0 node-1; do
SUBNET=$(grep ${HOST} machines.txt | cut -d " " -f 4)
sed "s|SUBNET|$SUBNET|g" \
configs/10-bridge.conf > 10-bridge.conf
...
done
替换后的 CNI 配置(模板见 10-bridge.conf)结构如下:
{
"cniVersion": "1.0.0",
"name": "bridge",
"type": "bridge",
"bridge": "cni0",
"isGateway": true,
"ipMasq": true,
"ipam": {
"type": "host-local",
"ranges": [
[{"subnet": "10.200.0.0/24"}]
],
"routes": [{"dst": "0.0.0.0/0"}]
}
}
从这份配置可以看出:
- 每个节点通过
cni0网桥为 Pod 创建网络命名空间,host-localIPAM 插件从本节点的SUBNET网段中分配 Pod IP; routes: [{"dst": "0.0.0.0/0"}]表示容器内默认路由指向网桥网关,Pod 出节点流量由节点 IP 转发;- 节点侧的 kubelet-config.yaml 中
maxPods: 16限制了单节点 Pod 数量,而/24的 Pod 网段(254 个可用地址)足以覆盖这一上限。
与此同时,集群层面使用统一的 10.200.0.0/16 作为集群 CIDR:在 kube-controller-manager.service 中通过 --cluster-cidr=10.200.0.0/16 传入,kube-proxy-config.yaml 中也声明了 clusterCIDR: "10.200.0.0/16"。各节点的 10.200.0.0/24、10.200.1.0/24 正好是这个 /16 网段下的子网,三者共同构成了完整的地址规划:
集群 CIDR: 10.200.0.0/16
├── node-0 Pod CIDR: 10.200.0.0/24
└── node-1 Pod CIDR: 10.200.1.0/24
创建路由:提取变量并写入各节点路由表
打印各 worker 实例的内部 IP 与 Pod CIDR
在 jumpbox 上执行以下命令块,从 machines.txt 中用 grep 按主机名匹配行、cut 按空格切列,提取出控制平面和两个 worker 节点的 IP 与 Pod 网段:
{
SERVER_IP=$(grep server machines.txt | cut -d " " -f 1)
NODE_0_IP=$(grep node-0 machines.txt | cut -d " " -f 1)
NODE_0_SUBNET=$(grep node-0 machines.txt | cut -d " " -f 4)
NODE_1_IP=$(grep node-1 machines.txt | cut -d " " -f 1)
NODE_1_SUBNET=$(grep node-1 machines.txt | cut -d " " -f 4)
}
这里 cut -d " " -f 1 取第 1 列(IPV4_ADDRESS),-f 4 取第 4 列(POD_SUBNET)。这些变量在同一个 shell 会话中保持有效,供后续路由命令使用。
在 server 节点添加两条路由
控制平面节点需要能访问两个 worker 节点上的所有 Pod,因此在 server 上添加指向两个 Pod 网段的路由:
ssh root@server <<EOF
ip route add ${NODE_0_SUBNET} via ${NODE_0_IP}
ip route add ${NODE_1_SUBNET} via ${NODE_1_IP}
EOF
展开后等价于:
ip route add 10.200.0.0/24 via <node-0 内部 IP>
ip route add 10.200.1.0/24 via <node-1 内部 IP>
在两个 worker 节点上互加对方网段路由
worker 节点只需路由到对端节点的 Pod 网段(本网段内的 Pod 通过本地 cni0 网桥直接可达,无需路由)。
在 node-0 上添加指向 node-1 Pod 网段的路由:
ssh root@node-0 <<EOF
ip route add ${NODE_1_SUBNET} via ${NODE_1_IP}
EOF
在 node-1 上添加指向 node-0 Pod 网段的路由:
ssh root@node-1 <<EOF
ip route add ${NODE_0_SUBNET} via ${NODE_0_IP}
EOF
至此,任意两个节点间都建立了“对端 Pod CIDR → 对端节点内部 IP”的路由映射,跨节点 Pod 通信路径打通:
node-0 上的 Pod (10.200.0.x)
→ node-0 内核路由:10.200.1.0/24 via <node-1 IP>
→ node-1 内核路由:目标 IP 属于本地 cni0 网段,直接投递
→ node-1 上的 Pod (10.200.1.x)
验证路由表
分别登录三台机器查看路由表,确认新路由已生效。
ssh root@server ip route
预期输出(XXX 为掩码后的实际地址):
default via XXX.XXX.XXX.XXX dev ens160
10.200.0.0/24 via XXX.XXX.XXX.XXX dev ens160
10.200.1.0/24 via XXX.XXX.XXX.XXX dev ens160
XXX.XXX.XXX.0/24 dev ens160 proto kernel scope link src XXX.XXX.XXX.XXX
server 上应同时出现两条 Pod 网段路由。
ssh root@node-0 ip route
default via XXX.XXX.XXX.XXX dev ens160
10.200.1.0/24 via XXX.XXX.XXX.XXX dev ens160
XXX.XXX.XXX.0/24 dev ens160 proto kernel scope link src XXX.XXX.XXX.XXX
ssh root@node-1 ip route
default via XXX.XXX.XXX.XXX dev ens160
10.200.0.0/24 via XXX.XXX.XXX.XXX dev ens160
XXX.XXX.XXX.0/24 dev ens160 proto kernel scope link src XXX.XXX.XXX.XXX
node-0 上只有 10.200.1.0/24(node-1 的网段),node-1 上只有 10.200.0.0/24(node-0 的网段),各节点仅保留对端路由,符合“本网段本地可达、对端网段走路由”的预期。
小结与后续步骤
- 地址规划是前提:
machines.txt第 4 列的POD_SUBNET与集群 CIDR(10.200.0.0/16,见 kube-controller-manager.service 和 kube-proxy-config.yaml)共同决定了路由目标网段的划分,三者必须一致。 - 路由是跨节点互通的关键一环:CNI bridge 配置(10-bridge.conf)只解决了“节点内 Pod 拿 IP”的问题;本实验用三条
ip route add命令解决了“跨节点 Pod 可达”的问题。 - 适用前提与限制:该手工路由方案假设所有节点位于同一二层/可路由网络,且
ip route add写入的是非持久化路由——节点重启后需要重新执行,这也是生产环境中使用 Flannel/Calico 等 CNI 自动管理路由的原因。教程 README 也明确说明,该集群的搭建结果不视为生产就绪。
路由配置完成后,集群的 Pod 网络层即全部就绪,下一步可执行 Smoke Test 实验,通过创建 nginx Deployment、Port Forward、NodePort 服务等实际操作验证整个集群(包括跨节点 Pod 通信)是否正常工作。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00