了解 AKS 网络:底层网络
Source: Dev.to
如果你曾经尝试从虚拟机 curl 一个 Kubernetes Service IP,结果却一直卡住——本指南正适合你。
我们将拆解:
- AKS 网络设计
- CIDR 布局(VNet、子网、Service CIDR、Pod CIDR)
- 为什么
ClusterIP在虚拟机上会失败 - 为什么
NodePort能正常工作 - 步骤化的数据包流向
- 完整的 Azure CLI 部署步骤
所有内容均在 Azure Kubernetes Service (AKS) 上的 Microsoft Azure 环境中测试通过。
🧱 1️⃣ 网络设计概览
实验拓扑
| 组件 | CIDR |
|---|---|
| VNet | 10.0.0.0/16 |
| AKS 子网 | 10.0.1.0/24 |
| VM 子网 | 10.0.2.0/24 |
| Service CIDR | 10.240.0.0/16 |
| Overlay Pods(可选) | 192.168.0.0/16 |
底层模式(Azure CNI)
🗺️ 架构图(PlantUML)
🧠 CIDR 说明
| CIDR | 用途 |
|---|---|
10.0.0.0/16 | Azure VNet |
10.0.1.0/24 | AKS 节点 |
10.0.2.0/24 | 测试 VM |
10.240.0.0/16 | Kubernetes Service(虚拟) |
192.168.0.0/16 | Overlay Pods(若启用) |
关键概念: Service CIDR 不 属于 Azure VNet 路由的一部分,因此从 VM 到 ClusterIP 的流量会被 Azure 路由器丢弃。
⚙️ 2️⃣ 完整 Azure CLI 设置
变量
LOCATION=eastus2
RG=aks-networking-lab
VNET_NAME=aks-vnet
UNDERLAY_SUBNET=aks-underlay-subnet
VM_SUBNET=vm-subnet
AKS_NAME=aks-underlay
创建资源组
az group create \
--name $RG \
--location $LOCATION
创建 VNet + AKS 子网
az network vnet create \
--resource-group $RG \
--name $VNET_NAME \
--address-prefix 10.0.0.0/16 \
--subnet-name $UNDERLAY_SUBNET \
--subnet-prefix 10.0.1.0/24
创建 VM 子网
az network vnet subnet create \
--resource-group $RG \
--vnet-name $VNET_NAME \
--name $VM_SUBNET \
--address-prefix 10.0.2.0/24
获取子网 ID(用于 AKS)
SUBNET_ID=$(az network vnet subnet show \
--resource-group $RG \
--vnet-name $VNET_NAME \
--name $UNDERLAY_SUBNET \
--query id -o tsv)
创建 AKS 集群
az aks create \
--resource-group $RG \
--name $AKS_NAME \
--network-plugin azure \
--vnet-subnet-id $SUBNET_ID \
--service-cidr 10.240.0.0/16 \
--dns-service-ip 10.240.0.10 \
--node-count 2 \
--generate-ssh-keys
连接到集群
az aks get-credentials \
--resource-group $RG \
--name $AKS_NAME
🚀 3️⃣ 部署测试应用
kubectl create deployment nginx --image=nginx
kubectl scale deployment nginx --replicas=2
暴露为 ClusterIP
kubectl expose deployment nginx \
--name nginx-svc \
--port 80 \
--type ClusterIP
验证 Service
kubectl get svc
示例输出
nginx-svc ClusterIP 10.240.225.54 80/TCP
IP 地址(10.240.225.54)来源于 Service CIDR。
🔥 4️⃣ 包流: ClusterIP(为什么 VM 访问失败)
从 VM 上尝试:
curl 10.240.225.54
它会挂起,因为 Azure 路由会检查:
Is 10.240.0.0/16 in the VNet? → No
→ Drop packet
数据包永远到达不到任何 AKS 节点。
🧭 包流图示
🧪 5️⃣ 转换为 NodePort
kubectl patch svc nginx-svc \
-p '{"spec":{"type":"NodePort"}}'
验证:
kubectl get svc nginx-svc
示例输出
nginx-svc NodePort 10.240.225.54 80:31598/TCP
现在该服务可以通过任意节点的 IP 以及分配的 node‑port(示例中为 31598)进行访问。
✅ 6️⃣ 正确的从 VM 测试方式
-
获取节点的内部 IP:
kubectl get nodes -o wide示例输出
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME aks-nodepool1-42091994-vmss000000 Ready <none> 34m v1.33.6 10.0.1.33 <none> Ubuntu 22.04.5 LTS 5.15.0-1103-azure containerd://1.7.30-2 aks-nodepool1-42091994-vmss000001 Ready <none> 34m v1.33.6 10.0.1.4 <none> Ubuntu 22.04.5 LTS 5.15.0-1103-azure containerd://1.7.30-2 -
通过节点 IP 和 node‑port 进行 curl:
curl http://10.0.1.4:31598
您应该收到默认的 Nginx 响应,确认当服务以 NodePort 方式暴露时可以从 VM 访问。
指南结束。
退出全屏模式
示例
azureuser@test-vm:~$ curl -s 10.0.1.33:31598 | grep -i "welcome"
Welcome to nginx!
欢迎使用 nginx!
流程
- VM → 节点 IP
- 节点接收流量
kube-proxy匹配 NodePort 规则- DNAT 到 Pod IP
- 响应返回
🧠 深度技术解析
当数据包到达节点时,kube-proxy 会安装类似以下的 iptables 规则:
KUBE-NODEPORTS
KUBE-SERVICES
KUBE-SEP-XXXX
DNAT 示例
10.0.1.4:31598 → 10.0.1.10:80
为什么 ClusterIP 在 Pod 内部有效
- 数据包首先到达节点。
kube-proxy将目标地址重写为 Pod IP。
为什么在 VM 上会失败
- 数据包从未到达节点。
- Azure 路由会将其丢弃。
🎯 关键要点
- ClusterIP = 虚拟内部 Kubernetes IP。
- NodePort = 节点在真实的 VNet IP 上监听。
- Service CIDR 必须 不 与 VNet CIDR 重叠。
- Azure 仅路由 VNet CIDR。
kube-proxy负责 Service IP 的转换。
🏁 最终思维模型
Azure 负责:
10.0.0.0/16
Kubernetes 负责:
10.240.0.0/16
不同的路由域。

