Skip to content

Kubernetes 网络 ​

网络模型 ​

Kubernetes 的基本假设:

  • 每个 Pod 有集群内唯一 IP。
  • Pod 可直接与其他 Pod 通信,不依赖应用感知的 NAT。
  • 节点代理和 Pod 可以互相通信。
  • 同一 Pod 内容器共享 IP、端口空间和 localhost。

具体路由、隧道、eBPF、iptables/IPVS/nftables、IPAM 和 NetworkPolicy 由 CNI/数据面实现。Pod IP 是短暂身份,客户端应通过 Service 或更高层路由访问服务。

Service ​

yaml
apiVersion: v1
kind: Service
metadata:
  name: web
  namespace: demo
spec:
  selector:
    app: web
  ports:
    - name: http
      port: 80
      targetPort: http
  type: ClusterIP

Service 选择 Ready Pod 并通过 EndpointSlice 发布后端:

bash
kubectl -n demo get service web
kubectl -n demo get endpointslice -l kubernetes.io/service-name=web
kubectl -n demo describe service web

targetPort: http 引用容器命名端口,减少端口修改时的耦合。Service selector 错误、Pod 未 Ready 或标签不匹配都会导致没有端点。

Service 类型 ​

类型作用注意事项
ClusterIP仅集群内部虚拟 IP默认选择,仍需 NetworkPolicy
HeadlessclusterIP: None,DNS 返回 Pod/端点常配 StatefulSet/服务发现
NodePort每个节点暴露端口暴露面大,通常作为 LB 的底层机制
LoadBalancer请求云/平台负载均衡器成本、配额、源 IP 和健康检查依赖实现
ExternalNameDNS CNAME 指向外部名称无代理和健康检查,注意 DNS/证书语义

externalTrafficPolicy: Local 可保留客户端源 IP并避免第二跳,但只有本地有端点的节点能接流量,负载均衡健康检查和容量必须配套。

DNS ​

同命名空间内:

text
web
web.demo
web.demo.svc
web.demo.svc.cluster.local

集群域名未必是 cluster.local,不要硬编码完整后缀。Pod 的 /etc/resolv.conf 通常含搜索域和 ndots,短名称查询可能产生多次 DNS 请求;外部高 QPS 域名可使用尾点完全限定名并验证应用行为。

bash
kubectl -n demo exec dns-test -- cat /etc/resolv.conf
kubectl -n demo exec dns-test -- nslookup web
kubectl -n kube-system get deployment,pods -l k8s-app=kube-dns

DNS 故障要区分:解析失败、DNS 服务无端点、CoreDNS 上游故障、NetworkPolicy 拦截 UDP/TCP 53、节点 conntrack 或应用缓存。

Ingress ​

Ingress 是 HTTP(S) 路由 API,必须安装 Ingress Controller 才生效:

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
  namespace: demo
spec:
  ingressClassName: internal-nginx
  rules:
    - host: web.example.internal
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web
                port:
                  name: http

注解、正则、重写、超时和认证多为 Controller 私有能力,迁移前必须核对实现。生产应显式 ingressClassName,配置 TLS、证书自动化、访问日志、超时和请求大小限制。

Ingress Controller 生命周期

Ingress API 仍是 Kubernetes 稳定 API,但具体 Controller 是独立项目。选择实现时核对官方维护状态、安全公告和升级路径,不要把旧教程中的 Controller 注解当作 Kubernetes 标准。

Gateway API ​

Gateway API 将基础设施与应用路由职责分离,需要安装 CRD 和兼容 Controller:

  • GatewayClass:基础设施提供者定义的实现类。
  • Gateway:监听器、地址和证书等基础设施入口。
  • HTTPRoute、GRPCRoute 等:应用团队定义的路由。
  • ReferenceGrant:显式授权跨命名空间引用。
yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: web
  namespace: demo
spec:
  parentRefs:
    - name: internal-gateway
      namespace: platform-gateway
  hostnames:
    - web.example.internal
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: web
          port: 80

检查 status.parents[].conditions,对象 Accepted 不代表所有引用均已解析或数据面已就绪。Gateway API 版本与能力取决于 CRD/Controller,不跟 Kubernetes 核心版本自动同步。

NetworkPolicy ​

NetworkPolicy 只有在 CNI 支持时才生效。策略是加法模型:某方向一旦被策略选中,只允许所有适用策略规则的并集。

先为命名空间建立默认拒绝:

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
  namespace: demo
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress

再允许 web 接收 gateway 流量并访问 DNS;本例未放通 Kubernetes API 或其他业务出站,须按真实目的端点另加规则:

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: web-allow
  namespace: demo
spec:
  podSelector:
    matchLabels:
      app: web
  policyTypes: [Ingress, Egress]
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: platform-gateway
      ports:
        - protocol: TCP
          port: 8080
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53

DNS 规则必须匹配集群实际 DNS Pod/节点实现;某些 CNI 对 ipBlock、hostNetwork、节点和 NAT 前后地址的行为不同。上线默认拒绝前,用测试命名空间和流量清单验证监控、证书、镜像、API、外部依赖全部路径。

双栈、MTU 与源地址 ​

  • 双栈 Service 可有 IPv4/IPv6 两个 ClusterIP,应用和依赖必须支持。
  • 隧道网络会减少有效 MTU;症状可能是小包成功、大包超时或 TLS 卡住。
  • Service、Ingress 和负载均衡可能做 SNAT,应用看到的源 IP取决于数据路径。
  • 代理链上的 X-Forwarded-For 只有在信任边界正确时可用,不能无条件信任客户端自带头。

网络排障路径 ​

bash
# 1. Pod 是否 Ready、IP 是否分配
kubectl -n demo get pod -l app=web -o wide

# 2. Service selector 与端点
kubectl -n demo get svc web -o yaml
kubectl -n demo get endpointslice -l kubernetes.io/service-name=web -o wide

# 3. 从调用方 Pod 测 DNS、端口和 HTTP
kubectl -n demo exec client -- nslookup web
kubectl -n demo exec client -- wget -S -O- http://web:80/readyz

# 4. 查看策略、路由对象与事件
kubectl -n demo get networkpolicy
kubectl -n demo describe ingress web
kubectl -n demo get httproute web -o yaml

按“应用监听 → Pod IP → EndpointSlice → Service → Ingress/Gateway/LB → 外部 DNS”逐层测试,不要一开始就重启 CNI。

生产网络清单 ​

  • Pod、Service、节点和 LB 地址段不重叠,容量有告警。
  • CNI、kube-proxy/替代数据面、CoreDNS 多副本跨故障域。
  • 命名空间默认拒绝并显式放行,策略有自动化连通性测试。
  • 入站和出站均有明确边界、证书、超时、重试和限流。
  • 避免应用层与网关层重试叠加造成重试风暴。
  • DNS、conntrack、丢包、延迟、EndpointSlice 和 LB 健康有监控。
  • Controller/CRD 升级与 Kubernetes 升级分开评估兼容性。

补充:端口与会话亲和性 ​

来源:jekyall_blog 的 Kubernetes Services 笔记(2023-11-24);重复的类型、选择器和排障说明已合并到上文。

NodePort 的常见默认范围是 30000–32767,实际范围由集群配置决定。端口冲突应检查具体的 NodePort 分配或外部监听入口;不能据此要求不同 ClusterIP Service 使用互不重复的 port。

Service 可以配置会话亲和性,使同一客户端尽量落到相同后端。它不能代替应用的会话存储,也不能保证 Pod 重建后仍是原实例。排查无流量时,依次核对 selector、Ready、targetPort、网络策略和入口类型,清单先通过 dry-run 验证。

继续阅读