Kubernetes——基于域名访问与东西/南北流量管理
一、环境说明
项目 | 说明 |
集群版本 | Kubernetes v1.24.17 |
部署方式 | kubeadm 离线部署 |
容器运行时 | containerd 1.6.21 |
网络插件 | Calico |
镜像仓库 |
|
Master 节点 | 192.168.2.125(k8s-master01) |
Worker 节点 | 192.168.2.126 / 192.168.30.127 |
⚠️ 所有镜像必须提前导入 containerd 的k8s.io命名空间:ctr -n k8s.io images import xxx.tar
二、基于域名访问 K8s 应用
2.1 部署 Nginx 应用(Deployment + Service)
创建 Deployment:
cat > nginx-new-deploy.yaml << 'EOF' apiVersion: apps/v1 kind: Deployment metadata: name: nginx-new-deploy labels: app: nginx-new spec: replicas: 3 selector: matchLabels: app: nginx-new template: metadata: labels: app: nginx-new spec: containers: - name: nginx image: 672tq9h17eavbw.xuanyuan.run/library/nginx:1.26.0-alpine imagePullPolicy: IfNotPresent ports: - containerPort: 80 readinessProbe: httpGet: path: / port: 80 initialDelaySeconds: 5 periodSeconds: 10 EOF # 构建 kubectl apply -f nginx-new-deploy.yaml # 查看 kubectl get pods kubectl get deploy创建 ClusterIP Service:
cat > nginx-svc.yaml << 'EOF' apiVersion: v1 kind: Service metadata: name: nginx-svc labels: app: nginx-new spec: selector: app: nginx-new ports: - port: 80 targetPort: 80 type: ClusterIP EOF # 构建 kubectl apply -f nginx-svc.yaml验证部署:
kubectl get pods -o wide kubectl get svc nginx-svc预期输出:3 个 Pod Running,nginx-svc 分配了 ClusterIP(如10.96.x.x)。
2.2 集群内部域名解析(CoreDNS)
K8s 内置 CoreDNS,Service 创建后会自动注册 DNS 记录,格式为:
<service-name>.<namespace>.svc.cluster.local
启动测试 Pod 验证 DNS: kubectl run test-dns --image=672tq9h17eavbw.xuanyuan.run/library/busybox:1.35 -- sleep 3600 解析 Service 短域名: kubectl exec test-dns -- nslookup nginx-svc输出示例:
Server: 10.96.0.10 Address: 10.96.0.10:53 Name: nginx-svc.default.svc.cluster.local Address: 10.104.178.59 ** server can't find nginx-svc.svc.cluster.local: NXDOMAIN ** server can't find nginx-svc.cluster.local: NXDOMAIN ** server can't find nginx-svc.cluster.local: NXDOMAIN ** server can't find nginx-svc.svc.cluster.local: NXDOMAIN command terminated with exit code 1解析 Service 完整域名: kubectl exec test-dns -- nslookup nginx-svc.default.svc.cluster.local输出示例:
Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: nginx-svc Address 1: 10.96.x.x nginx-svc.default.svc.cluster.local通过域名访问 Nginx:
kubectl exec test-dns -- wget -q -O- http://nginx-svc kubectl exec test-dns -- wget -q -O- http://nginx-svc.default.svc.cluster.local✅ 至此,集群内部已可通过域名访问应用。
2.3 外部域名映射(ExternalName Service)
将集群外部域名映射为集群内部 Service,Pod 内可通过内部域名访问外部服务:
cat > external-svc.yaml << 'EOF' apiVersion: v1 kind: Service metadata: name: external-nginx spec: type: ExternalName externalName: nginx.example.com EOF kubectl apply -f external-svc.yaml验证解析:
kubectl exec test-dns -- nslookup external-nginx.default.svc.cluster.local输出中会看到 CNAME 指向nginx.example.com。
三、南北流量演示(外部 → 集群内部)
南北流量指外部客户端访问集群内服务的流量方向。
3.1 方式一:NodePort 直接暴露
cat > nginx-nodeport-svc.yaml << 'EOF' apiVersion: v1 kind: Service metadata: name: nginx-31318-svc spec: selector: app: nginx-new ports: - port: 80 targetPort: 80 nodePort: 31818 type: NodePort EOF kubectl apply -f nginx-nodeport-svc.yaml验证访问:
# 通过任意节点 IP + NodePort 访问 curl http://192.168.2.125:31818 curl http://192.168.2.126:31818 curl http://192.168.2.127:31818流量路径:
Client → NodeIP:31818 → kube-proxy(iptables/IPVS) → Pod:80
⚠️ NodePort 方式简单直接,但端口范围受限(30000-32767),且缺乏域名和路径路由能力。
3.2 方式二:Ingress + 域名(推荐)
Ingress 是 K8s 南北流量的标准入口,支持基于域名、路径的路由转发。
3.2.1 部署 NGINX Ingress Controller
# 拉取镜像到k8s.io命名空间 ctr -n k8s.io images pull registry.cn-hangzhou.aliyuncs.com/acs/aliyun-ingress-controller:v1.8.2-aliyun.1 # 验证镜像已存在 ctr -n k8s.io images list | grep aliyun-ingress # 配置yaml文件 cat > ingress-all.yaml << 'EOF' --- apiVersion: v1 kind: Namespace metadata: name: ingress-nginx --- apiVersion: v1 kind: ServiceAccount metadata: name: ingress-nginx-controller namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: ingress-nginx-controller rules: - apiGroups: [""] resources: ["configmaps","endpoints","nodes","pods","secrets","services","namespaces","events"] verbs: ["get","list","watch","create","update","patch"] - apiGroups: ["networking.k8s.io"] resources: ["ingresses","ingressclasses"] verbs: ["get","list","watch","update"] - apiGroups: ["networking.k8s.io"] resources: ["ingresses/status"] verbs: ["update"] - apiGroups: ["discovery.k8s.io"] resources: ["endpointslices"] verbs: ["get","list","watch"] - apiGroups: ["coordination.k8s.io"] resources: ["leases"] verbs: ["get","list","watch","create","update"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: ingress-nginx-controller roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: ingress-nginx-controller subjects: - kind: ServiceAccount name: ingress-nginx-controller namespace: ingress-nginx --- apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: name: nginx spec: controller: k8s.io/ingress-nginx --- apiVersion: v1 kind: Service metadata: name: ingress-nginx-controller namespace: ingress-nginx spec: selector: app: ingress-nginx ports: - port: 80 targetPort: 80 name: http - port: 443 targetPort: 443 name: https type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: ingress-nginx-controller namespace: ingress-nginx labels: app: ingress-nginx spec: replicas: 1 selector: matchLabels: app: ingress-nginx template: metadata: labels: app: ingress-nginx spec: hostNetwork: true serviceAccountName: ingress-nginx-controller tolerations: - operator: Exists nodeSelector: kubernetes.io/hostname: k8s-master01 containers: - name: controller image: registry.cn-hangzhou.aliyuncs.com/acs/aliyun-ingress-controller:v1.8.2-aliyun.1 imagePullPolicy: IfNotPresent ports: - containerPort: 80 name: http - containerPort: 443 name: https args: - /nginx-ingress-controller - --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller - --election-id=ingress-controller-leader - --controller-class=k8s.io/ingress-nginx - --http-port=80 - --https-port=443 env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name livenessProbe: httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 EOF # 应用配置 kubectl apply -f ingress-all.yaml # 等待 Pod 就绪 kubectl wait --for=condition=ready pod -n ingress-nginx -l app=ingress-nginx --timeout=120s # 验证核心资源 kubectl get ingressclass nginx kubectl get pods -n ingress-nginx -o wide💡hostNetwork: true让 Ingress Controller 直接使用宿主机网络,外部可通过NodeIP:80/443访问,无需额外 NodePort 映射。
验证 Ingress Controller 就绪:
kubectl get pods -n ingress-nginx -o wide kubectl logs -n ingress-nginx deployment/ingress-nginx-controller3.2.2 创建 Ingress 规则
cat > nginx-ingress.yaml << 'EOF' apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: nginx-ingress spec: ingressClassName: nginx rules: - host: nginx.example.com http: paths: - path: / pathType: Prefix backend: service: name: nginx-svc port: number: 80 EOF kubectl apply -f nginx-ingress.yaml # 验证 kubectl get ingress nginx-ingress kubectl describe ingress nginx-ingress查看 Ingress 状态:
kubectl get ingress nginx-ingress kubectl describe ingress nginx-ingress3.2.3 通过域名访问验证
方法一:修改本地 hosts 文件(测试推荐)
在访问机器上添加: echo "192.168.2.125 nginx.example.com" >> /etc/hosts 然后浏览器或 curl 访问: curl http://nginx.example.com方法二:curl 指定 Host 头(无需改 hosts)
curl -H "Host: nginx.example.com" http://192.168.2.125
方法三:多域名路由演示
cat > multi-host-ingress.yaml << 'EOF' apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: multi-host-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: ingressClassName: nginx rules: - host: web.example.com http: paths: - path: / pathType: Prefix backend: service: name: nginx-svc port: number: 80 - host: api.example.com http: paths: - path: / pathType: Prefix backend: service: name: nginx-31318-svc port: number: 80 EOF kubectl apply -f multi-host-ingress.yaml验证多域名:
curl -H "Host: web.example.com" http://192.168.2.125 curl -H "Host: api.example.com" http://192.168.2.1253.2.4 南北流量完整路径
┌──────────┐ ┌──────────────┐ ┌──────────────────┐ ┌────────────┐ ┌─────────────┐ │ Client │────▶│ DNS 解析 │────▶│ Ingress Controller│────▶│ nginx-svc │────▶│ nginx Pods │ │ (浏览器) │ │ nginx.example│ │ (hostNetwork) │ │ ClusterIP │ │ (3 replicas)│ └──────────┘ │ .com → NodeIP│ └──────────────────┘ └────────────┘ └─────────────┘ └──────────────┘四、东西流量演示(集群内部 Pod → Pod)
东西流量指集群内部 Pod 之间互相访问的流量方向。
4.1 部署测试客户端
cat > test-client.yaml << 'EOF' apiVersion: apps/v1 kind: Deployment metadata: name: test-client spec: replicas: 1 selector: matchLabels: app: test-client template: metadata: labels: app: test-client spec: containers: - name: client # 阿里云 ACS 官方 curl 镜像(固定版本,可复现) image: registry.cn-hangzhou.aliyuncs.com/acs/curl:8.1.2 command: ["sleep", "3600"] imagePullPolicy: IfNotPresent EOF kubectl apply -f test-client.yaml # 等待 Pod 就绪 kubectl wait --for=condition=ready pod -l app=test-client --timeout=60s等待 Pod 就绪:
kubectl wait --for=condition=ready pod -l app=test-client --timeout=60s
4.2 通过 Service 域名访问(推荐)
CLIENT_POD=$(kubectl get pod -l app=test-client -o jsonpath='{.items[0].metadata.name}') # 短域名 kubectl exec $CLIENT_POD -- curl -s nginx-svc # 完整域名 kubectl exec $CLIENT_POD -- curl -s nginx-svc.default.svc.cluster.local4.3 通过 Pod IP 直接访问(不推荐)
NGINX_POD_IP=$(kubectl get pod -l app=nginx-new -o jsonpath='{.items[0].status.podIP}') echo "Nginx Pod IP: $NGINX_POD_IP" kubectl exec $CLIENT_POD -- curl -s $NGINX_POD_IP⚠️ Pod IP 是临时的,Pod 重建后会变化,生产环境应始终通过 Service 域名访问。
4.4 通过环境变量访问
K8s 会为每个 Service 自动注入环境变量到同命名空间的 Pod 中:
kubectl exec $CLIENT_POD -- env | grep NGINX_SVC输出示例:
NGINX_SVC_PORT_80_TCP=tcp://10.96.x.x:80 NGINX_SVC_SERVICE_HOST=10.96.x.x NGINX_SVC_SERVICE_PORT=80kubectl exec $CLIENT_POD -- sh -c 'curl -s http://$NGINX_SVC_SERVICE_HOST:$NGINX_SVC_SERVICE_PORT'4.5 东西流量完整路径
┌────────────────┐ ┌─────────────────┐ ┌────────────────────┐ ┌─────────────┐ │ test-client Pod│───▶│ kube-proxy │───▶│ nginx-svc │───▶│ nginx Pods │ │ │ │ (iptables/IPVS) │ │ ClusterIP: 10.96.x │ │ (3 replicas)│ └────────────────┘ └─────────────────┘ └────────────────────┘ └─────────────┘Calico 负责跨节点 Pod 网络的底层路由(BGP),kube-proxy 负责 Service 的负载均衡转发。
五、综合演示:南北 + 东西流量同时观测
5.1 部署多层级应用
cat > frontend-deploy.yaml << 'EOF' apiVersion: apps/v1 kind: Deployment metadata: name: frontend spec: replicas: 2 selector: matchLabels: app: frontend template: metadata: labels: app: frontend spec: containers: - name: frontend image: 672tq9h17eavbw.xuanyuan.run/library/nginx:1.26.0-alpine ports: - containerPort: 80 EOF cat > backend-deploy.yaml << 'EOF' apiVersion: apps/v1 kind: Deployment metadata: name: backend spec: replicas: 2 selector: matchLabels: app: backend template: metadata: labels: app: backend spec: containers: - name: backend image: 672tq9h17eavbw.xuanyuan.run/library/nginx:1.26.0-alpine ports: - containerPort: 80 EOF cat > backend-svc.yaml << 'EOF' apiVersion: v1 kind: Service metadata: name: backend-svc spec: selector: app: backend ports: - port: 80 targetPort: 80 EOF kubectl apply -f frontend-deploy.yaml kubectl apply -f backend-deploy.yaml kubectl apply -f backend-svc.yaml5.2 创建综合 Ingress
cat > full-ingress.yaml << 'EOF' apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: full-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: ingressClassName: nginx rules: - host: www.example.com http: paths: - path: / pathType: Prefix backend: service: name: frontend-svc port: number: 80 - path: /api pathType: Prefix backend: service: name: backend-svc port: number: 80 --- # frontend 也需要一个 Service apiVersion: v1 kind: Service metadata: name: frontend-svc spec: selector: app: frontend ports: - port: 80 targetPort: 80 EOF kubectl apply -f full-ingress.yaml5.3 流量全景图
南北流量(外部 → 集群) ┌──────────────────────────────────────────────────────────────────┐ │ │ │ Client ──▶ DNS ──▶ Ingress Controller ──┬──▶ frontend-svc ──▶ frontend Pods │ │ │ │ │ └──▶ backend-svc ──▶ backend Pods │ │ │ └──────────────────────────────────────────────────────────────────┘ 东西流量(集群内部 Pod → Pod) ┌──────────────────────────────────────────────────────────────────┐ │ │ │ frontend Pod ──▶ backend-svc(ClusterIP) ──▶ backend Pod │ │ │ │ │ │ (通过域名 backend-svc.default.svc.cluster.local) │ │ ▼ │ │ kube-proxy(iptables/IPVS) 负载均衡到后端 Pod │ │ │ └──────────────────────────────────────────────────────────────────┘5.4 验证综合访问
# 南北流量 - 访问前端 curl -H "Host: www.example.com" http://192.168.30.125/ # 南北流量 - 访问后端 API curl -H "Host: www.example.com" http://192.168.30.125/api # 东西流量 - 从 frontend Pod 调用 backend Service FRONTEND_POD=$(kubectl get pod -l app=frontend -o jsonpath='{.items[0].metadata.name}') kubectl exec $FRONTEND_POD -- wget -q -O- http://backend-svc六、验证与排障命令速查
6.1 域名解析验证
# CoreDNS Pod 状态 kubectl get pods -n kube-system -l k8s-app=kube-dns # DNS 解析测试 kubectl exec test-dns -- nslookup nginx-svc kubectl exec test-dns -- nslookup nginx-svc.default.svc.cluster.local kubectl exec test-dns -- cat /etc/resolv.conf6.2 Ingress 验证
# Ingress 状态 kubectl get ingress -A kubectl describe ingress nginx-ingress # Ingress Controller 日志 kubectl logs -n ingress-nginx deployment/ingress-nginx-controller -f # 访问日志 kubectl exec -n ingress-nginx deployment/ingress-nginx-controller -- tail -f /var/log/nginx/access.log6.3 Service 与端点验证
# Service 详情 kubectl describe svc nginx-svc # Endpoints(后端 Pod IP 列表) kubectl get endpoints nginx-svc kubectl describe endpoints nginx-svc6.4 常见故障排查
问题 | 排查命令 | 可能原因 |
域名解析失败 |
| CoreDNS 未运行 / 网络策略拦截 |
Ingress 404 |
| 域名不匹配 / Service 名称错误 |
Ingress 502 |
| 后端 Pod 未就绪 / 端口错误 |
Pod 间不通 |
| Calico 异常 / CIDR 冲突 |
NodePort 不通 |
| kube-proxy 异常 / 防火墙未关 |
七、资源清理
# 删除所有测试资源 kubectl delete -f full-ingress.yaml kubectl delete -f frontend-deploy.yaml kubectl delete -f backend-deploy.yaml kubectl delete -f backend-svc.yaml kubectl delete -f test-client.yaml kubectl delete -f nginx-ingress.yaml kubectl delete -f multi-host-ingress.yaml kubectl delete -f ingress-controller.yaml kubectl delete -f nginx-nodeport-svc.yaml kubectl delete -f nginx-svc.yaml kubectl delete -f nginx-new-deploy.yaml kubectl delete -f external-svc.yaml kubectl delete pod test-dns八、关键知识点总结
8.1 域名访问三要素
要素 | 说明 |
CoreDNS | K8s 内置 DNS 服务,自动为 Service 注册域名记录 |
Service | 域名背后对应的虚拟 IP + 负载均衡 |
Ingress | 集群外部域名入口,支持七层路由(域名/路径) |
8.2 南北 vs 东西流量对比
维度 | 南北流量(North-South) | 东西流量(East-West) |
方向 | 外部 Client ↔ 集群内部 | 集群内部 Pod ↔ Pod |
入口 | Ingress / NodePort / LoadBalancer | Service(ClusterIP) |
DNS | 外部 DNS → Ingress Controller | CoreDNS → ClusterIP |
负载均衡 | Ingress Controller | kube-proxy(iptables/IPVS) |
网络层 | Calico BGP + iptables NAT | Calico BGP 路由 |
典型场景 | 用户访问网站 | 微服务间 API 调用 |
8.3 核心架构图
┌─────────────────────────────────────────┐ │ Kubernetes Cluster │ │ │ ┌────────┐ │ ┌──────────────────────────────────┐ │ │ Client │───────┼─▶│ Ingress Controller (hostNetwork) │ │ └────────┘ │ └────────┬─────────────────────────┘ │ │ │ 南北流量(七层路由) │ │ ▼ │ │ ┌─────────────┐ ┌──────────────┐ │ │ │ Service │───▶│ Pod Replicas │ │ │ │ ClusterIP │ │ (Nginx etc.) │ │ │ └──────┬──────┘ └──────────────┘ │ │ │ │ │ │ 东西流量(服务间调用) │ │ ▼ │ │ ┌─────────────┐ ┌──────────────┐ │ │ │ Other Pod │───▶│ Other Service│ │ │ │ (caller) │ │ (callee) │ │ │ └─────────────┘ └──────────────┘ │ │ │ │ CoreDNS ── 域名解析服务 │ │ Calico ── Pod 网络 + BGP 路由 │ │ kube-proxy ── Service 负载均衡 │ └─────────────────────────────────────────┘九、操作步骤
9.1 南北流量(North-South)操作步骤
定义:外部客户端 → Ingress → Service → Pod 的跨集群边界流量
步骤 | 操作命令 | 作用说明 | 验证命令 | 预期结果 |
1 |
| 部署前端应用(2副本)+ 前端Service,作为南北流量入口 |
| 2个frontend Pod状态为 frontend-svc存在且Endpoints有2个Pod IP |
2 |
| 配置Ingress路由规则: 路由到frontend-svc 路由到backend-svc |
| Ingress规则正常,无报错 |
3 |
| 配置本地DNS解析,让外部能定位到Ingress节点 |
| 解析到192.168.2.125 |
4 |
| 验证南北流量全链路 | 页面返回内容 | 返回前端页面,包含 标识 |
5 | 浏览器访问 | 可视化验证南北流量 | 页面正常加载 | 同步骤4,适合直观验证 |
9.2 东西流量(East-West)操作步骤
定义:集群内 Pod → Service → Pod 的集群内部流量
步骤 | 操作命令 | 作用说明 | 验证命令 | 预期结果 |
1 | (可选)给backend配置标识页面 | 让后端返回带东西流量标识的页面,方便区分流量来源 |
| 2个backend Pod状态为 |
2 | 部署观测Pod(curl测试容器) | 作为流量发起方,持续观测集群内东西流量 |
| 观测Pod状态为 |
3 |
| 验证集群内Pod→Service的基础东西链路 | 返回内容 | 返回后端页面,包含 标识 |
4 |
| 验证业务级东西流量:前端Pod通过Service访问后端 | 返回内容 | 同步骤3,确认前端能调用后端接口 |
5 |
| 验证东西流量的访问日志(通过Ingress触发时) | 日志内容 | 出现 记录 |
9.3 核心概念速记表
概念 | 对应资源 | 作用 | 备注 |
南北入口 | Ingress | 暴露集群内服务到外部 | 需匹配 |
东西转发核心 | Service | 集群内Pod的服务发现和负载均衡 | 南北/东西流量都依赖Service |
南北流量标识 | 前端页面自定义内容 | 直观区分流量类型 | 无需额外组件 |
东西流量观测 | traffic-observer Pod | 持续验证集群内流量 | 用完可删除 |
一句话总结:Ingress 管南北(外部进来的流量),Service 管东西(内部 Pod 间流量),CoreDNS 让所有流量都能用域名代替 IP,Calico 保证所有流量真正通得了路。
