探秘 K8s Pod 网络:从原理到实战

2025-11-11 运维 kubernetes

在 Kubernetes(简称 K8s)生态中,Pod 作为最小部署单元,是容器运行的载体,而 Pod 网络则是维系整个集群通信的 “神经网络”。无论是同一节点上的 Pod 互通、跨节点 Pod 协作,还是集群内外服务的连接,都依赖稳定、高效的 Pod 网络机制。如果说 K8s 是云原生应用的 “操作系统”,那么 Pod 网络就是这套系统的 “通信总线”—— 没有可靠的网络,容器化应用的分布式部署、弹性伸缩等核心优势都无从谈起。

本文将从 Pod 网络的基础类型切入,深入剖析其工作原理,对比主流网络插件,详解 DNS 服务配置、网络安全策略,结合实战排查技巧与案例,帮助读者全面掌握 K8s Pod 网络的核心知识与实践方法。

Pod 网络类型全解析

容器内部网络

同一 Pod 中的多个容器共享一个网络命名空间(Network Namespace),这是 K8s Pod 网络最基础的特性。这意味着它们拥有相同的 IP 地址、端口空间、路由表和 DNS 配置,容器之间可以通过 localhost 直接通信,无需额外的网络转发或端口映射。

优势

  1. 通信效率极高,无需跨网络命名空间的转发开销;
  2. 配置简单,容器间可直接复用端口(只要不冲突),无需考虑端口暴露;
  3. 数据隔离性强,同一 Pod 内的容器共享网络栈,数据传输无需经过外部网络。

典型场景:Pod 中的 “主容器” 负责业务逻辑,“边车容器”(Sidecar)负责日志收集、监控代理、服务网格代理(如 Istio)等,边车容器通过 localhost 与主容器通信,无需暴露额外端口。

Pod 之间网络

不同 Pod 之间的通信是 K8s 集群网络的核心场景,无论是同一节点上的 Pod,还是跨节点的 Pod,都需要通过统一的网络方案实现互通。K8s 本身没有内置网络实现,而是通过 CNI(Container Network Interface,容器网络接口)规范对接第三方网络插件,常见的有 Flannel、Calico 等。

核心原则

K8s 要求所有 Pod 都拥有独立的、可路由的 IP 地址,且 Pod 之间无需 NAT(网络地址转换)即可直接通信,即 “Pod IP 全局可达”。

实战示例:Flannel 插件实现跨节点通信

Flannel 是最常用的轻量级 CNI 插件,通过在集群中分配独立的子网给每个节点,实现跨节点 Pod 通信,其核心原理是 “Overlay 网络”(覆盖网络),常用 VXLAN 模式转发流量。

1. 安装 Flannel

1
2
# 下载 Flannel 配置文件(适配 K8s 1.24+)
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.22.3/Documentation/kube-flannel.yml

2. 工作流程

  • 集群初始化时,Flannel 会为每个节点分配一个独立的子网(如节点 A 分配 10.244.0.0/24,节点 B 分配 10.244.1.0/24);
  • 同一节点上的 Pod 属于同一子网,通过节点内部的网桥(如 cni0)直接通信;
  • 跨节点 Pod 通信时(如节点 A 的 Pod10.244.0.10访问节点 B 的 Pod10.244.1.10):
    1. 流量从 Pod 流出,经过节点的 cni0 网桥转发到 Flannel 守护进程(flanneld);
    2. flanneld 通过 VXLAN 隧道将流量封装,发送到目标节点;
    3. 目标节点的 flanneld 解封装流量,转发到目标 Pod 所在的 cni0 网桥,最终送达目标 Pod。

集群内部网络

Pod 的 IP 地址是动态变化的(如 Pod 重启、重建后 IP 会改变),直接通过 Pod IP 访问服务会导致 “服务不可用”。K8s 提供 Service 资源,为一组 Pod 提供固定的访问入口(ClusterIP),并通过标签选择器(Label Selector)自动关联 Pod,实现负载均衡和服务发现。

核心作用

  1. 固定访问地址:Service 分配的 ClusterIP 是集群内部固定的虚拟 IP,不会随 Pod 变化;
  2. 负载均衡:自动将请求分发到关联的多个 Pod 上,提高服务可用性;
  3. 服务发现:通过 Service 名称,集群内的 Pod 可直接访问目标服务,无需记忆 Pod IP。

配置示例:创建 ClusterIP Service

1
2
3
4
5
6
7
8
9
10
11
12
# service-demo.yaml
apiVersion: v1
kind: Service
metadata:
name: my-service # Service 名称(用于 DNS 解析)
spec:
selector:
app: my-app # 关联标签为 app=my-app 的 Pod
ports:
- port: 80 # Service 暴露的端口(集群内部访问端口)
targetPort: 8080 # Pod 实际监听的端口
type: ClusterIP # 集群内部访问类型(默认)

应用场景:集群内的微服务通信(如订单服务访问支付服务),通过 Service 名称即可实现稳定访问,无需关注 Pod IP 的动态变化。

集群外部网络

默认情况下,Service 和 Pod 仅能在集群内部访问,若需让外部用户或应用访问集群内的服务,K8s 提供了 3 种主流方案:

1. NodePort

在每个节点上开放一个静态端口(NodePort),外部流量通过 节点 IP:NodePort 访问集群内的 Service。

配置示例

1
2
3
4
5
6
spec:
type: NodePort
ports:
- port: 80 # Service 内部端口
targetPort: 8080 # Pod 端口
nodePort: 30007 # 自定义 NodePort(范围:30000-32767,可选)

优势:配置简单,无需额外依赖;缺点:端口范围有限,暴露节点 IP,扩展性差。

2. LoadBalancer

依赖云厂商的负载均衡服务(如 AWS ELB、阿里云 SLB),自动创建负载均衡器并关联节点,外部流量通过负载均衡器 IP 访问服务。

配置示例

1
2
3
4
5
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080

优势:自动负载均衡,高可用,扩展性好;缺点:依赖云厂商,可能产生额外费用。

3. Ingress

Ingress 是集群的 “入口网关”,通过统一的域名和路径规则,将外部流量路由到不同的 Service,支持 HTTPS、路径重写、负载均衡等高级功能,是生产环境中暴露服务的首选方案。

配置示例(需先安装 Ingress Controller,如 Nginx Ingress):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# ingress-demo.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- host: app.example.com # 外部访问域名
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service # 关联的 Service 名称
port:
number: 80

优势

  • 统一入口,支持多域名、多路径路由;
  • 支持 HTTPS 终结、SSL 证书管理;
  • 无需暴露节点 IP 或静态端口,安全性更高。

Pod 网络工作原理深度剖析

Pod 网络创建流程

Pod 的网络命名空间和网络配置,是通过 K8s 组件与 CNI 插件协同完成的,完整流程如下:

  1. 用户提交 Pod 请求:通过 kubectl apply -f pod.yaml 提交 Pod 配置,API Server 接收请求并存储到 etcd;

  2. 调度器分配节点:调度器(kube-scheduler)根据节点资源、亲和性等规则,为 Pod 选择合适的节点,并将节点信息更新到 etcd;

  3. Kubelet 启动 Pod:目标节点的 Kubelet 组件监听 API Server,发现新的 Pod 调度到本节点后,调用容器运行时(如 containerd)创建 Pod 的网络命名空间;

  4. CNI 插件配置网络

    :Kubelet 调用 CNI 插件(如 Flannel),执行以下操作:

    • 为 Pod 分配独立的 IP 地址(从节点子网中分配);
    • 配置 Pod 的网络接口(如 eth0),并连接到节点的网桥(如 cni0);
    • 设置路由规则,确保 Pod 能访问集群内其他 Pod 和外部网络;
  5. 网络就绪:Pod 网络配置完成后,Kubelet 标记 Pod 为 “Running” 状态,此时 Pod 可正常通信。

网络通信机制(以 Flannel VXLAN 模式为例)

以 “节点 A 的 Pod A(IP:10.244.0.10)访问节点 B 的 Pod B(IP:10.244.1.10)” 为例,详细拆解流量转发流程:

  1. Pod A 发起请求:Pod A 中的应用发起 TCP 连接请求(目标 IP:10.244.1.10,目标端口:8080);
  2. Pod 内部路由:由于 Pod 网络命名空间已配置路由规则,流量从 Pod A 的 eth0 接口流出;
  3. 节点网桥转发:流量到达节点 A 的 cni0 网桥(cni0 是 Pod 与节点网络的桥梁);
  4. Flannel 封装流量:节点 A 的 flanneld 进程监听 cni0 网桥,识别到目标 IP 属于节点 B 的子网,将原始 IP 数据包封装为 VXLAN 数据包(外层 IP 为节点 A 和节点 B 的物理 IP);
  5. 跨节点传输:VXLAN 数据包通过节点的物理网卡发送,经过集群网络(如交换机、路由器)传输到节点 B;
  6. Flannel 解封装流量:节点 B 的 flanneld 进程接收 VXLAN 数据包,解封装得到原始 IP 数据包;
  7. 目标节点转发:节点 B 的 flanneld 将原始数据包转发到 cni0 网桥,再由网桥转发到 Pod B 的 eth0 接口;
  8. Pod B 接收请求:Pod B 中的应用监听 8080 端口,接收并处理请求。

主流网络插件对比与选择

K8s 支持多种 CNI 插件,不同插件在性能、功能、适用场景上存在差异,以下是主流插件的对比与选择建议:

Flannel

  • 核心特点:轻量级、配置简单、无状态,支持 VXLAN、Host-GW 等模式;

  • 工作原理:为每个节点分配独立子网,通过 Overlay 网络或路由转发实现 Pod 互通;

  • 优势:部署成本低,适合中小型集群、测试环境或对网络性能要求不高的场景;

  • 劣势:VXLAN 模式存在封装开销,性能略低于 Calico;不支持网络策略(NetworkPolicy);

  • 配置建议

    1
    2
    3
    # 启用 Host-GW 模式(无封装开销,性能更好,要求节点之间能直接通信)
    kubectl edit configmap kube-flannel-cfg -n kube-system
    # 修改 net-conf.json 中的 "Type" 为 "host-gw"

Calico

  • 核心特点:高性能、功能丰富,支持 BGP 路由协议、网络策略、加密通信等;
  • 工作原理:基于 BGP 协议在节点之间分发路由信息,Pod 之间通过路由直接通信,无需 Overlay 封装(默认模式);
  • 优势:
    1. 性能优异,无 VXLAN 封装开销,适合大型集群、高性能场景;
    2. 支持细粒度的网络策略(NetworkPolicy),可控制 Pod 之间的访问权限;
    3. 支持网络加密(IPsec)、Pod 移动性、带宽管理等高级功能;
  • 劣势:配置相对复杂,需要理解 BGP 路由基础;
  • 典型场景:生产环境、大型集群、对网络性能和安全性有较高要求的场景(如金融、电商系统)。

其他插件

  • Weave Net:支持自动网络配置,无需预先规划子网,支持加密通信和网络策略,适合快速部署的中小型集群;
  • Cilium:基于 eBPF 技术,性能远超传统插件,支持高级网络策略、可观测性,适合对性能和功能有极致要求的场景(如服务网格、边缘计算);
  • Canal:结合 Flannel 的简单性和 Calico 的网络策略,适合需要网络策略但不想复杂配置的场景。

选择建议

场景推荐插件
测试环境、小型集群Flannel
生产环境、大型集群Calico/Cilium
需要网络策略Calico/Cilium/Weave Net
极致性能要求Calico(BGP 模式)/Cilium
快速部署、自动配置Weave Net

网络策略与安全保障

在多租户集群或复杂微服务架构中,需要限制 Pod 之间的访问权限(如只允许订单服务访问支付服务,拒绝其他服务访问),K8s 的 NetworkPolicy 资源可实现细粒度的网络访问控制。

NetworkPolicy 详解

NetworkPolicy 是 K8s 中的网络安全规则,用于定义 “哪些 Pod 可以被哪些来源(Pod、IP、端口)访问”,或 “哪些 Pod 可以访问哪些目标”,仅对匹配标签的 Pod 生效。

核心概念

  • Pod 选择器(podSelector):指定规则作用于哪些 Pod(通过标签匹配);
  • 入站规则(ingress):允许哪些来源的流量访问目标 Pod;
  • 出站规则(egress):允许目标 Pod 访问哪些目的地;
  • 规则匹配条件:可通过 IP 段(ipBlock)、Pod 标签(podSelector)、命名空间(namespaceSelector)、端口(ports)过滤流量。

注意事项

  • NetworkPolicy 仅对支持的 CNI 插件生效(如 Calico、Cilium、Weave Net),Flannel 不支持;
  • 默认情况下,没有 NetworkPolicy 时,所有 Pod 之间可自由通信;一旦创建了针对某个 Pod 的 NetworkPolicy,未被规则允许的流量将被拒绝。

实战场景应用

场景 1:限制仅指定 Pod 可访问支付服务

假设支付服务的 Pod 标签为 app=payment,仅允许标签为 app=order 的订单服务 Pod 访问其 8080 端口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# networkpolicy-payment.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: payment-policy
spec:
podSelector:
matchLabels:
app: payment # 作用于支付服务 Pod
policyTypes:
- Ingress # 仅配置入站规则
ingress:
- from:
- podSelector:
matchLabels:
app: order # 允许订单服务 Pod 访问
ports:
- protocol: TCP
port: 8080 # 仅允许访问 8080 端口

场景 2:限制 Pod 仅能访问内部服务和 DNS

假设应用 Pod 标签为 app=web,仅允许其访问集群内 app=api 的服务(80 端口),以及 DNS 服务(53 端口,用于域名解析)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# networkpolicy-web.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: web-policy
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Egress # 配置出站规则
egress:
# 允许访问 api 服务
- to:
- podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 80
# 允许访问 DNS 服务(集群 DNS 服务 IP 通常为 10.96.0.10)
- to:
- ipBlock:
cidr: 10.96.0.10/32
ports:
- protocol: UDP
port: 53

K8s DNS 服务:从 IP 访问到域名解析

在 K8s 集群中,直接使用 Pod IP 或 Service ClusterIP 访问服务存在明显缺陷:Pod IP 动态变化、ClusterIP 是虚拟 IP 难以记忆。K8s 内置的 DNS 服务(核心组件为 CoreDNS)解决了这一问题,为 Pod、Service 提供了域名解析能力,让集群内的服务可通过 “名称” 实现通信,无需关注底层 IP。

一、K8s DNS 核心组件:CoreDNS

CoreDNS 是 K8s 1.13+ 版本的默认 DNS 服务器,替代了早期的 kube-dns。它以 Pod 形式运行在 kube-system 命名空间,通过 Service(kube-dns,ClusterIP 通常为 10.96.0.10)暴露服务,所有 Pod 会自动配置该 DNS 服务器作为默认 DNS 解析器。

1. 查看 CoreDNS 状态

1
2
3
4
5
6
7
8
# 查看 CoreDNS Pod
kubectl get pods -n kube-system -l k8s-app=kube-dns

# 查看 kube-dns Service(DNS 服务入口)
kubectl get svc kube-dns -n kube-system
# 输出示例:
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP 30d

2. CoreDNS 核心功能

  • 为 Service 自动创建域名,支持集群内解析;
  • 为 Pod 提供可选的域名解析(需配置 hostnamesubdomain);
  • 支持自定义 DNS 配置(如转发外部域名、自定义域名映射);
  • 支持 DNS 缓存,提升解析性能。

二、K8s DNS 解析规则:3 类核心域名

K8s 为不同资源定义了标准化的 DNS 域名格式,确保解析的唯一性和可用性,核心分为 3 类:

1. Service 域名(最常用)

Service 是集群内服务发现的核心,CoreDNS 会为每个 Service 自动生成域名,格式为:

1
<service-name>.<namespace>.svc.<cluster-domain>
  • <service-name>:Service 的名称(如 my-service);
  • <namespace>:Service 所在的命名空间(如 default);
  • <cluster-domain>:集群域名(默认是 cluster.local,可通过 K8s 配置修改)。

解析结果:Service 的 ClusterIP(如 10.96.1.23)。

使用场景

  • 同一命名空间内的 Pod 访问 Service,可简化为 <service-name>(如 my-service),CoreDNS 会自动补全命名空间和集群域名;
  • 跨命名空间访问 Service,需指定完整域名(如 my-service.prod.svc.cluster.local,访问 prod 命名空间的 my-service)。

实战示例:假设 default 命名空间有一个 Service 名为 payment-service(端口 80),Pod 中访问该服务的方式:

1
2
3
4
5
# 同一命名空间(default),简化域名
curl http://payment-service:80

# 跨命名空间(如从 dev 命名空间访问 default 命名空间的服务)
curl http://payment-service.default.svc.cluster.local:80

2. Pod 域名(可选)

默认情况下,Pod 的域名由 K8s 自动生成,格式为 <pod-ip>-<namespace>.pod.<cluster-domain>(如 10-244-0-10-default.pod.cluster.local),但这种格式不便于使用。

若需为 Pod 配置自定义域名,可通过 hostnamesubdomain 字段配置:

1
2
3
4
5
6
7
8
9
10
11
12
# pod-with-dns.yaml
apiVersion: v1
kind: Pod
metadata:
name: web-pod
namespace: default
spec:
hostname: web # Pod 的主机名(必填)
subdomain: app # 子域名(需配合 Headless Service 使用)
containers:
- name: nginx
image: nginx

注意:Pod 自定义域名需要配合 Headless Service(无 ClusterIP 的 Service)使用,Headless Service 的名称需与 Pod 的 subdomain 一致:

1
2
3
4
5
6
7
8
9
10
11
12
# headless-service.yaml
apiVersion: v1
kind: Service
metadata:
name: app # 与 Pod 的 subdomain 一致
spec:
selector:
app: web # 关联 Pod 的标签
clusterIP: None # 声明为 Headless Service
ports:
- port: 80
targetPort: 80

最终 Pod 域名web.app.default.svc.cluster.local,其他 Pod 可通过该域名访问此 Pod。

3. 外部域名(转发解析)

CoreDNS 默认会转发集群内无法解析的域名(如 www.baidu.comgithub.com)到节点的 DNS 服务器(配置在 /etc/resolv.conf),确保 Pod 能访问外部网络。

若需自定义外部域名转发规则(如转发公司内部域名到专用 DNS 服务器),可修改 CoreDNS 的 ConfigMap:

1
kubectl edit configmap coredns -n kube-system

添加自定义转发规则(示例:转发 company.com 域名到 192.168.1.100 DNS 服务器):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
# 自定义转发规则:company.com 域名转发到 192.168.1.100
forward . company.com 192.168.1.100
cache 30
loop
reload
loadbalance
}

三、DNS 配置与优化:解决解析问题

1. Pod 的 DNS 配置文件

每个 Pod 的 /etc/resolv.conf 文件由 K8s 自动生成,包含 CoreDNS 的 ClusterIP、搜索域(search domains)等配置,示例:

1
2
3
nameserver 10.96.0.10  # CoreDNS 的 ClusterIP
search default.svc.cluster.local svc.cluster.local cluster.local # 搜索域
options ndots:5 # 解析域名时,若域名包含的点少于 5 个,会自动拼接搜索域

关键参数说明

  • search:搜索域列表,当访问短域名(如 payment-service)时,CoreDNS 会按顺序拼接搜索域,尝试解析 payment-service.default.svc.cluster.localpayment-service.svc.cluster.local 等;
  • ndots:5:控制短域名拼接规则,默认值为 5,意味着若域名包含的点少于 5 个(如 payment-service 含 0 个点),会优先使用搜索域拼接;若域名包含 5 个及以上点(如 a.b.c.d.e.f),则直接解析。

2. 常见 DNS 问题与解决方案

问题 1:Pod 无法解析 Service 名称
  • 排查步骤:
    1. 检查 CoreDNS Pod 是否正常运行(kubectl get pods -n kube-system -l k8s-app=kube-dns);
    2. 进入 Pod 内部,测试 DNS 解析(nslookup my-service.default.svc.cluster.local 10.96.0.10);
    3. 检查 Pod 的 /etc/resolv.conf 是否正确配置(是否包含 nameserver 10.96.0.10)。
  • 解决方案:
    • 若 CoreDNS 未运行,重启 CoreDNS Pod(kubectl delete pods -n kube-system -l k8s-app=kube-dns);
    • 若解析超时,检查网络插件是否正常(如 Flannel/Calico 是否运行),确保 Pod 能访问 CoreDNS 的 53 端口(TCP/UDP)。
问题 2:短域名解析缓慢或失败
  • 原因ndots:5 配置导致短域名会多次拼接搜索域解析,增加延迟;

  • 解决方案:

    1. 访问跨命名空间 Service 时,使用完整域名(如 my-service.prod.svc.cluster.local);

    2. 自定义 Pod 的 DNS 配置,调整ndots值(需在 Pod .spec 中配置):

      1
      2
      3
      4
      5
      spec:
      dnsConfig:
      options:
      - name: ndots
      value: "2" # 减少拼接搜索域的次数
问题 3:Pod 无法解析外部域名
  • 排查步骤:
    1. 进入 Pod 内部,测试解析外部域名(nslookup www.baidu.com);
    2. 检查节点的 /etc/resolv.conf 是否配置了有效的 DNS 服务器;
    3. 检查 CoreDNS 是否正常转发外部域名(查看 CoreDNS 日志:kubectl logs -n kube-system -l k8s-app=kube-dns)。
  • 解决方案:
    • 若节点 DNS 配置无效,修改节点的 /etc/resolv.conf,添加公共 DNS(如 8.8.8.8114.114.114.114);
    • 若 CoreDNS 转发失败,检查集群网络是否允许 CoreDNS 访问外部 DNS 服务器的 53 端口。

3. DNS 性能优化

  • 启用 CoreDNS 缓存:默认已启用,缓存时长 30 秒(可通过 ConfigMap 调整 cache 字段);
  • 减少搜索域数量:若无需跨命名空间访问,可在 Pod 的 dnsConfig 中自定义 search 域,减少拼接次数;
  • 部署多个 CoreDNS 副本:提高可用性和并发处理能力(默认 2 个副本,可通过 kubectl scale deployment coredns -n kube-system --replicas=3 调整)。

四、DNS 实战:从配置到验证

1. 部署测试 Service 和 Pod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 部署一个 Nginx Service 和 Pod
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80
---
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx

2. 验证 DNS 解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 进入另一个测试 Pod(如 busybox)
kubectl run -it --rm busybox --image=busybox:1.35 -- sh

# 1. 解析同一命名空间的 Service(简化域名)
nslookup nginx-service
# 预期输出:Address 1: 10.96.x.x nginx-service.default.svc.cluster.local

# 2. 解析完整域名
nslookup nginx-service.default.svc.cluster.local
# 预期输出:Address 1: 10.96.x.x nginx-service.default.svc.cluster.local

# 3. 解析外部域名
nslookup www.baidu.com
# 预期输出:Address 1: 180.101.49.11(百度 IP)

3. 自定义 Pod DNS 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 自定义 DNS 搜索域和 ndots 值
apiVersion: v1
kind: Pod
metadata:
name: custom-dns-pod
spec:
containers:
- name: busybox
image: busybox:1.35
command: ["sleep", "3600"]
dnsConfig:
searches:
- prod.svc.cluster.local # 优先搜索 prod 命名空间
- default.svc.cluster.local
options:
- name: ndots
value: "2"
- name: timeout
value: "2" # 解析超时时间 2 秒

常见问题与排查技巧

网络异常场景

1. 同一节点 Pod 无法互通

  • 现象:同一节点上的两个 Pod 互相 ping 不通,或无法访问对方端口;
  • 可能原因:节点网桥(cni0)配置异常、容器网络接口未正确创建、防火墙规则拦截。

2. 跨节点 Pod 无法互通

  • 现象:同一集群不同节点的 Pod 无法通信,ping 目标 Pod IP 超时;
  • 可能原因:网络插件(如 Flannel)未正常运行、节点子网分配冲突、跨节点网络链路不通(如防火墙拦截 VXLAN 端口 8472)。

3. 外部无法访问集群服务

  • 现象:通过 NodePort/LoadBalancer/Ingress 访问服务超时或报错;
  • 可能原因:Service 未关联 Pod(标签选择器不匹配)、Ingress Controller 未安装、节点安全组 / 防火墙拦截端口。

4. DNS 解析失败

  • 现象:Pod 无法通过 Service 名称访问服务,nslookup 命令报错(如 server can't find xxx: NXDOMAIN);
  • 可能原因:CoreDNS 未正常运行、Pod 的 /etc/resolv.conf 配置异常、Service 名称或命名空间错误。

排查方法与工具

1. 基础排查工具

  • kubectl:查看资源状态、日志;
  • ping:测试 Pod IP 连通性;
  • telnet/nc:测试端口可达性(如 telnet 10.244.1.10 8080);
  • nslookup/dig:测试 DNS 解析(如 nslookup my-service);
  • tcpdump:抓包分析流量(如 tcpdump -i eth0 host 10.244.1.10);
  • iproute2:查看网络配置(如 ip addrip route)。

2. 分步排查流程

步骤 1:检查 Pod 状态
1
2
kubectl get pods -o wide
# 确保 Pod 处于 Running 状态,且节点分配正常
步骤 2:检查网络插件状态
1
2
3
4
# 检查 Flannel 状态
kubectl get pods -n kube-system -l app=flannel
# 检查 Calico 状态
kubectl get pods -n calico-system
步骤 3:测试 Pod 内部网络
1
2
3
4
5
6
7
8
# 进入 Pod
kubectl exec -it <pod-name> -- sh
# 查看网络接口
ip addr
# 查看路由表
ip route
# 测试 localhost 通信(同一 Pod 内容器)
curl localhost:<port>
步骤 4:测试 Pod 之间通信
1
2
3
4
5
6
# 同一节点 Pod 通信
kubectl exec -it <pod1-name> -- ping <pod2-ip>
# 跨节点 Pod 通信
kubectl exec -it <pod1-name> -- ping <跨节点-pod-ip>
# 测试端口可达性
kubectl exec -it <pod1-name> -- nc -zv <pod2-ip> <port>
步骤 5:测试 Service 访问
1
2
3
4
5
6
# 查看 Service 状态和 ClusterIP
kubectl get svc
# 测试访问 Service ClusterIP
kubectl exec -it <pod-name> -- curl <service-clusterip>:<port>
# 测试 DNS 解析 Service 名称
kubectl exec -it <pod-name> -- nslookup <service-name>
步骤 6:测试外部访问
1
2
3
4
# NodePort 模式:测试节点 IP:NodePort
curl <node-ip>:<node-port>
# Ingress 模式:测试域名访问(需配置本地 hosts 或 DNS)
curl http://app.example.com
步骤 7:抓包分析(进阶)
1
2
3
4
# 在 Pod 内抓包
kubectl exec -it <pod-name> -- tcpdump -i eth0 host <target-ip> -w /tmp/traffic.pcap
# 复制抓包文件到本地分析(需安装 tcpdump)
kubectl cp <pod-name>:/tmp/traffic.pcap ./traffic.pcap

案例分析:故障解决与优化

案例背景

某电商平台的 K8s 集群(3 个节点,使用 Flannel VXLAN 模式),线上环境出现 “订单服务无法访问支付服务” 的故障,现象如下:

  1. 订单服务 Pod(10.244.0.20,节点 A)无法通过支付服务的 Service 名称 payment-service 访问,报错 curl: (6) Could not resolve host: payment-service
  2. 直接通过支付服务 Pod IP(10.244.1.30,节点 B)访问正常;
  3. 其他服务(如商品服务)可正常通过 Service 名称访问支付服务。

排查过程

步骤 1:检查 Service 和 Pod 关联状态

1
2
3
4
5
6
7
8
9
# 查看支付服务 Service
kubectl get svc payment-service -o wide
# 输出:NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
# payment-service ClusterIP 10.96.5.78 <none> 80/TCP 10d app=payment

# 查看支付服务 Pod
kubectl get pods -l app=payment -o wide
# 输出:NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
# payment-pod-7f98d7c6b4-2xqzk 1/1 Running 0 5d 10.244.1.30 node-b <none>

结论:Service 标签选择器 app=payment 与 Pod 标签匹配,ClusterIP 为 10.96.5.78,状态正常。

步骤 2:测试订单服务 Pod 的 DNS 解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 进入订单服务 Pod
kubectl exec -it order-pod-67f89d7c5d-9x7zk -- sh

# 测试解析 payment-service
nslookup payment-service
# 输出:server can't find payment-service: NXDOMAIN

# 测试解析完整域名
nslookup payment-service.default.svc.cluster.local
# 输出:server can't find payment-service.default.svc.cluster.local: NXDOMAIN

# 测试解析其他 Service(如 product-service)
nslookup product-service
# 输出:Address 1: 10.96.8.123 product-service.default.svc.cluster.local

# 查看 Pod 的 /etc/resolv.conf
cat /etc/resolv.conf
# 输出:
# nameserver 10.96.0.10
# search prod.svc.cluster.local svc.cluster.local cluster.local
# options ndots:5

关键发现:订单服务 Pod 的 search 域包含 prod.svc.cluster.local,而支付服务位于 default 命名空间,订单服务 Pod 拼接搜索域时优先使用 prod 命名空间,导致解析失败。

步骤 3:验证命名空间配置

1
2
3
4
5
6
7
# 查看订单服务 Pod 所在命名空间
kubectl get pods order-pod-67f89d7c5d-9x7zk -o jsonpath='{.metadata.namespace}'
# 输出:prod

# 查看支付服务所在命名空间
kubectl get svc payment-service -o jsonpath='{.metadata.namespace}'
# 输出:default

结论:订单服务位于 prod 命名空间,支付服务位于 default 命名空间,订单服务 Pod 访问跨命名空间 Service 时未使用完整域名,导致 DNS 解析失败。

解决方案与优化措施

1. 临时解决方案:使用完整域名访问

修改订单服务的配置,将访问地址从 payment-service:80 改为 payment-service.default.svc.cluster.local:80,部署后测试正常。

2. 长期优化方案:调整 Pod DNS 配置

prod 命名空间的 Pod 添加 default 命名空间到搜索域,避免跨命名空间访问时解析失败:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 在 prod 命名空间创建 Pod 时,添加 DNS 配置
apiVersion: v1
kind: Pod
metadata:
name: order-pod
namespace: prod
spec:
containers:
- name: order-service
image: order-service:v1.0
dnsConfig:
searches:
- prod.svc.cluster.local
- default.svc.cluster.local # 添加 default 命名空间搜索域
- svc.cluster.local
- cluster.local

3. 集群层面优化:统一命名空间规划

  • 规范服务命名空间:将关联紧密的服务部署在同一命名空间(如 payment 命名空间部署支付相关服务,order 命名空间部署订单相关服务);
  • 为跨命名空间的核心服务创建别名 Service:在常用命名空间中创建指向核心服务的别名 Service,避免记忆完整域名。

4. 监控优化:添加 DNS 解析监控

  • 部署 Prometheus + Grafana 监控 CoreDNS 指标(如 coredns_dns_requests_totalcoredns_dns_request_duration_seconds_sum);
  • 配置告警规则:当 DNS 解析失败率超过阈值(如 1%)时,及时告警。

总结与展望

K8s Pod 网络是云原生应用通信的基础,其核心围绕 “Pod IP 全局可达” 和 “服务发现” 展开。本文从 Pod 网络类型、工作原理、主流插件、DNS 配置、网络安全、故障排查等维度,系统讲解了 Pod 网络的核心知识,并通过实战案例验证了理论的实用性。

核心要点回顾:

  1. 同一 Pod 内容器共享网络命名空间,通过 localhost 通信;
  2. 不同 Pod 依赖 CNI 插件实现互通,Flannel 适合轻量场景,Calico 适合生产环境;
  3. Service 提供固定访问入口,Ingress 是外部访问的首选方案;
  4. CoreDNS 实现域名解析,支持 Service、Pod 域名,需注意跨命名空间解析规则;
  5. NetworkPolicy 提供细粒度网络安全控制,生产环境建议启用。

未来展望:

  • 随着 eBPF 技术的兴起,Cilium 等基于 eBPF 的网络插件将成为主流,提供更高性能和更丰富的功能;
  • 服务网格(如 Istio)将与 Pod 网络深度融合,实现更细粒度的流量控制、可观测性和安全加密;
  • K8s 网络将向 “零信任” 架构演进,网络策略、加密通信、身份认证将成为默认配置。

对于开发者和运维人员而言,掌握 Pod 网络的核心原理和排查技巧,是保障 K8s 集群稳定运行的关键。建议在实际环境中多动手实践,结合监控工具及时发现并解决网络问题,为云原生应用提供可靠的通信基础。