了解 AKS 网络:底层网络

发布: (2026年3月3日 GMT+8 13:35)
5 分钟阅读
原文: Dev.to

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
VNet10.0.0.0/16
AKS 子网10.0.1.0/24
VM 子网10.0.2.0/24
Service CIDR10.240.0.0/16
Overlay Pods(可选)192.168.0.0/16

底层模式(Azure CNI)

🗺️ 架构图(PlantUML)

Architecture diagram

🧠 CIDR 说明

CIDR用途
10.0.0.0/16Azure VNet
10.0.1.0/24AKS 节点
10.0.2.0/24测试 VM
10.240.0.0/16Kubernetes Service(虚拟)
192.168.0.0/16Overlay 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 节点。

🧭 包流图示

Packet flow diagram

🧪 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 测试方式

  1. 获取节点的内部 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
  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!

流程

  1. VM → 节点 IP
  2. 节点接收流量
  3. kube-proxy 匹配 NodePort 规则
  4. DNAT 到 Pod IP
  5. 响应返回

🧠 深度技术解析

当数据包到达节点时,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

不同的路由域。

0 浏览
Back to Blog

相关文章

阅读更多 »

当工作成为心理健康风险时

markdown !Ravi Mishrahttps://media2.dev.to/dynamic/image/width=50,height=50,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fu...