Skip to main content

One post tagged with "networking"

View all tags

Kubernetes 全景解析 (2):网络模型与服务发现全链路解析

· 29 min read
Rainy
雨落无声,代码成诗 —— 致力于技术与艺术的极致平衡

前言

在 Kubernetes 的众多核心概念中,网络模型与服务发现机制是最为复杂也最为关键的部分之一。一个健康的 K8s 集群,其网络层必须满足 Pod 之间、Pod 与 Node 之间、以及 Pod 与外部世界的无缝通信。同时,随着微服务架构的普及,服务发现、负载均衡、流量路由等能力变得不可或缺。

本文将深入剖析 K8s 网络模型的三层架构、Service 的四种类型与流量路径、Ingress 控制器原理,以及 NetworkPolicy 安全策略,帮助你全面掌握 K8s 网络的核心机制。

一、K8s 网络模型基础

1.1 K8s 网络的三个基本要求

Kubernetes 对集群网络提出了三个基本要求,这些要求构成了 K8s 网络模型的核心:

  1. 所有 Pod 可以在没有 NAT 的情况下相互通信

    • 每个 Pod 都拥有独立的 IP 地址
    • Pod 之间可以直接通信,无需网络地址转换
    • 无论 Pod 位于哪个 Node 上
  2. 所有 Node 可以与所有 Pod 通信

    • Node 可以直接访问 Pod 的 IP
    • 无需额外的端口映射或代理
  3. Pod 看到的自己 IP 与其他 Pod 看到的 IP 相同

    • 不存在 IP 欺骗或地址转换
    • 网络行为可预测
设计理念

K8s 采用"扁平网络"模型,避免了传统容器网络中的复杂 NAT 配置,使得网络行为更加透明和可预测。这种设计大大简化了应用的开发和调试。

1.2 CNI(Container Network Interface)插件机制

Kubernetes 本身不实现具体的网络功能,而是通过 CNI(Container Network Interface)标准将网络实现委托给第三方插件。CNI 定义了一套接口规范,网络插件只需实现这些接口即可与 K8s 集成。

CNI 插件的主要职责包括:

  • IP 地址分配:为 Pod 分配 IP 地址
  • 网络配置:设置 Pod 的网络命名空间、路由表、防火墙规则
  • 网络连接:创建 veth pair、网桥、路由等网络设备

1.3 常见 CNI 插件对比

插件名称网络模式性能功能特性适用场景
FlannelVXLAN/Host-GW中等简单易用,支持多种后端中小规模集群,快速部署
CalicoBGP/纯路由强大的网络策略,支持 IPAM需要细粒度网络控制的企业级应用
CiliumeBPF极高基于 eBPF 的可观测性和安全高性能、高安全要求的场景
Weave NetVXLAN/加密中等内置加密,简单部署对安全性要求较高的场景
选择建议
  • Flannel:适合入门学习和中小规模集群
  • Calico:适合需要网络策略和企业级功能的场景
  • Cilium:适合追求极致性能和可观测性的场景
  • Weave Net:适合对数据加密有强需求的场景

1.4 K8s 网络三层模型

上图展示了 K8s 网络的三层架构:

  • 第 1 层:节点网络 - 物理机或虚拟机的网络,用于节点间通信
  • 第 2 层:Pod 网络 - 覆盖网络(Overlay)或纯路由网络,用于 Pod 间通信
  • 第 3 层:服务网络 - 虚拟 IP 网络,用于服务发现和负载均衡

二、Service:服务发现与负载均衡

2.1 Service 的四种类型

Service 是 K8s 中用于服务发现和负载均衡的核心抽象。它为一组功能相同的 Pod 提供稳定的访问入口,并实现流量分发。

2.1.1 ClusterIP(默认类型)

ClusterIP 是 Service 的默认类型,它为 Service 分配一个集群内部的虚拟 IP(VIP),仅在集群内部可访问。

apiVersion: v1
kind: Service
metadata:
name: nginx-clusterip
namespace: default
spec:
type: ClusterIP
selector:
app: nginx
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP

访问方式

  • 集群内部:http://nginx-clusterip.default.svc.cluster.local:80
  • 集群内部(短名):http://nginx-clusterip:80
最佳实践

对于不需要外部访问的内部服务(如数据库、缓存、内部 API),始终使用 ClusterIP 类型以确保安全性。

2.1.2 NodePort

NodePort 在每个 Node 上开放一个端口(默认范围 30000-32767),外部流量可以通过 NodeIP:NodePort 访问 Service。

apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport
namespace: default
spec:
type: NodePort
selector:
app: nginx
ports:
- name: http
port: 80
targetPort: 80
nodePort: 30080
protocol: TCP

访问方式

  • 外部访问:http://<任意NodeIP>:30080
  • 集群内部:http://nginx-nodeport.default.svc.cluster.local:80
注意事项

NodePort 会占用 Node 的端口,且端口范围有限(默认 30000-32767)。生产环境不建议直接使用 NodePort 暴露服务,应结合 Ingress 或 LoadBalancer 使用。

2.1.3 LoadBalancer

LoadBalancer 类型会向云服务商申请一个负载均衡器,并将外部流量分发到后端的 Node。

apiVersion: v1
kind: Service
metadata:
name: nginx-loadbalancer
namespace: default
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
# 云服务商特定配置
loadBalancerIP: "203.0.113.10"
externalTrafficPolicy: Local

访问方式

  • 外部访问:http://<LoadBalancerIP>:80
  • 集群内部:http://nginx-loadbalancer.default.svc.cluster.local:80
云服务商依赖

LoadBalancer 类型需要云服务商的支持(如 AWS ELB、GCP Load Balancer、Azure Load Balancer)。在本地开发环境(如 Minikube、Kind)中,通常无法正常工作。

2.1.4 ExternalName

ExternalName 类型将 Service 映射到外部 DNS 名称,不创建 ClusterIP,主要用于访问外部服务。

apiVersion: v1
kind: Service
metadata:
name: external-database
namespace: default
spec:
type: ExternalName
externalName: database.example.com

访问方式

  • 集群内部:http://external-database.default.svc.cluster.local
  • 实际会被 DNS 解析为:database.example.com

2.6 Service 应用协议(appProtocol)

Service 的 appProtocol 字段(v1.20 Stable)允许为每个 Service 端口指定应用层协议,为实现提供更丰富的行为提示。

支持的协议类型

协议描述
IANA 标准服务名httphttpsftpsmtp 等(参考 IANA Service Names
kubernetes.io/h2cHTTP/2 over cleartext(明文 HTTP/2,参考 RFC 7540)
kubernetes.io/wsWebSocket over cleartext(明文 WebSocket,参考 RFC 6455)
kubernetes.io/wssWebSocket over TLS(加密 WebSocket,参考 RFC 6455)
自定义前缀协议mycompany.com/my-custom-protocol

使用示例

apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: myapp
ports:
- name: http
port: 80
targetPort: 9376
protocol: TCP
appProtocol: http # 指定应用协议
- name: grpc
port: 9090
targetPort: 9090
protocol: TCP
appProtocol: kubernetes.io/h2c # HTTP/2 cleartext
appProtocol 的作用

appProtocol 字段的值会自动同步到对应的 Endpoints 和 EndpointSlice 对象中,供 Ingress Controller、Service Mesh 等组件使用,以提供协议感知的路由、健康检查等增强功能。

2.7 Service 名称验证规则(v1.34 Alpha)

FEATURE STATE: Kubernetes v1.34 [alpha](默认关闭)

Kubernetes v1.34 引入了 RelaxedServiceNameValidation 特性门控,允许 Service 对象名称以数字开头。

默认规则(特性门控关闭):

  • Service 名称必须是有效的 RFC 1035 标签名称
  • 必须以字母开头,只能包含字母、数字和连字符(-)

放宽规则(特性门控开启):

  • Service 名称可以是有效的 RFC 1123 标签名称
  • 允许以数字开头
启用 RelaxedServiceNameValidation

要启用此特性,需要在 API Server 和 Controller Manager 的启动参数中添加:

--feature-gates=RelaxedServiceNameValidation=true

2.2 kube-proxy 工作模式

kube-proxy 是 K8s 网络的核心组件,负责维护 Service 的网络规则。它支持三种工作模式:

2.2.1 iptables 模式

iptables 模式使用 iptables 规则实现负载均衡,每个 Service 会创建一系列 iptables 规则。

优点

  • 实现简单,兼容性好
  • 无需额外依赖

缺点

  • 规则数量随 Service 数量线性增长,性能下降明显
  • 不支持高级负载均衡算法(仅支持随机轮询)
  • 调试困难
  • iptables 正逐步被 Linux 内核的 nftables 框架取代

2.2.2 IPVS 模式

IPVS(IP Virtual Server)是基于 Linux 内核的负载均衡技术,性能远高于 iptables。

优点

  • 性能优异,支持大规模 Service
  • 支持多种负载均衡算法(rr、lc、dh、sh、sed、nq)
  • 连接跟踪更精确

缺点

  • 需要加载 IPVS 内核模块
  • 配置相对复杂

2.2.3 nftables 模式(v1.33 GA)

nftables 是 Linux 内核新一代的防火墙和数据包过滤框架,旨在取代传统的 iptables。kube-proxy 的 nftables 模式自 v1.29 引入(Alpha),v1.33 达到 GA(正式可用)。

优点

  • 替代逐步淘汰的 iptables 框架,面向未来
  • 规则处理性能优于 iptables
  • 统一了 IPv4/IPv6/ARP/桥接的过滤框架
  • 内核 5.13+ 及 nft 命令行工具 1.0.1+ 支持

缺点

  • 需要较新的内核版本(>= 5.13)
  • 需要 nft 命令行工具(>= 1.0.1)
  • 生态成熟度仍在提升中
性能优化建议

对于生产环境,建议根据内核版本选择 kube-proxy 模式:

  • 内核 >= 5.13:优先使用 nftables 模式(面向未来,性能更优)
  • 内核 < 5.13:使用 IPVS 模式以获得更好的性能

可以通过修改 kube-proxy 的配置来启用:

apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "nftables" # 可选值: "iptables" | "ipvs" | "nftables"

2.3 DNS 服务发现(CoreDNS)

CoreDNS 是 K8s 集群的默认 DNS 服务器,它为 Service 和 Pod 提供 DNS 解析服务。

DNS 记录格式

资源类型DNS 记录格式示例
Service(普通)<service-name>.<namespace>.svc.cluster.localnginx.default.svc.cluster.local
Service(Headless)<pod-ip>.<service-name>.<namespace>.svc.cluster.local10.244.1.2.nginx.default.svc.cluster.local
Pod<pod-ip>.<namespace>.pod.cluster.local10.244.1.2.default.pod.cluster.local

CoreDNS 配置示例

apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
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
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}

2.4 Headless Service 与 StatefulSet 的配合

Headless Service 是一种特殊的 Service,它不分配 ClusterIP,而是直接将 DNS 解析到后端的 Pod IP。这种设计常与 StatefulSet 配合使用,用于有状态应用。

apiVersion: v1
kind: Service
metadata:
name: nginx-headless
namespace: default
spec:
clusterIP: None # Headless Service 的关键配置
selector:
app: nginx
ports:
- name: http
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nginx-stateful
namespace: default
spec:
serviceName: nginx-headless # 关联 Headless Service
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80

DNS 解析结果

# 解析 Headless Service
$ dig nginx-headless.default.svc.cluster.local

;; ANSWER SECTION:
nginx-headless.default.svc.cluster.local. 5 IN A 10.244.1.2
nginx-headless.default.svc.cluster.local. 5 IN A 10.244.2.2
nginx-headless.default.svc.cluster.local. 5 IN A 10.244.3.2

# 解析单个 Pod
$ dig nginx-stateful-0.nginx-headless.default.svc.cluster.local

;; ANSWER SECTION:
nginx-stateful-0.nginx-headless.default.svc.cluster.local. 5 IN A 10.244.1.2
应用场景

Headless Service 适用于以下场景:

  • StatefulSet 应用(如数据库、消息队列)
  • 需要直接访问 Pod IP 的应用
  • 自定义负载均衡策略
  • 服务网格(Service Mesh)

2.8 Service 四种类型流量路径对比

上图展示了四种 Service 类型的流量路径:

  1. NodePort:外部流量通过 NodeIP:NodePort 进入,分发到各个 Node
  2. LoadBalancer:外部流量通过云负载均衡器进入,分发到各个 Node
  3. ClusterIP:集群内部流量通过虚拟 IP 分发到后端 Pod
  4. ExternalName:DNS 解析到外部服务名称

三、Ingress:七层路由入口

3.1 Ingress vs Service 的区别

特性ServiceIngress
网络层四层(L4 - TCP/UDP)七层(L7 - HTTP/HTTPS)
路由能力基于 IP 和端口基于 Host、Path、Header
协议支持TCP/UDPHTTP/HTTPS/gRPC
TLS 终止不支持支持
使用场景服务间通信、内部服务外部访问、多域名路由
核心区别

Service 是四层负载均衡,只能基于 IP 和端口进行路由;Ingress 是七层负载均衡,可以基于 HTTP Host、Path、Header 等进行智能路由。Ingress 通常作为多个 Service 的统一入口。

3.2 Ingress Controller

Ingress Controller 是 Ingress 资源的执行器,负责根据 Ingress 规则配置负载均衡器。常见的 Ingress Controller 包括:

Controller特点适用场景
Nginx Ingress成熟稳定,功能丰富通用场景,生产环境首选
Traefik自动配置,支持多种后端微服务架构,动态环境
APISIX高性能,支持云原生高流量、高并发场景
Istio Gateway服务网格集成已使用 Istio 的场景

Nginx Ingress Controller 部署示例

apiVersion: v1
kind: Namespace
metadata:
name: ingress-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
replicas: 2
selector:
matchLabels:
app: ingress-nginx
template:
metadata:
labels:
app: ingress-nginx
spec:
containers:
- name: controller
image: k8s.gcr.io/ingress-nginx/controller:v1.8.1
args:
- /nginx-ingress-controller
- --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
- --publish-service=$(POD_NAMESPACE)/ingress-nginx
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- name: http
containerPort: 80
- name: https
containerPort: 443
---
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
namespace: ingress-nginx
spec:
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
selector:
app: ingress-nginx

3.3 Ingress 资源配置

3.3.1 基于 Host 的路由

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-host-based
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- host: web.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80

3.3.2 基于 Path 的路由

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-path-based
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api-service
port:
number: 80
- path: /web(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: web-service
port:
number: 80
- path: /(.*)
pathType: ImplementationSpecific
backend:
service:
name: frontend-service
port:
number: 80

3.3.3 TLS 配置

apiVersion: v1
kind: Secret
metadata:
name: tls-secret
namespace: default
type: kubernetes.io/tls
data:
tls.crt: LS0tLS1CRUdJTi... # Base64 编码的证书
tls.key: LS0tLS1CRUdJTi... # Base64 编码的私钥
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-tls
namespace: default
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- secure.example.com
secretName: tls-secret
rules:
- host: secure.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: secure-service
port:
number: 443
TLS 最佳实践
  1. 使用 Let's Encrypt 自动获取和更新证书(推荐使用 cert-manager)
  2. 强制 HTTPS 重定向(如 nginx.ingress.kubernetes.io/ssl-redirect: "true")
  3. 定期轮换证书
  4. 使用强加密套件

3.4 Ingress 路由分发流程

上图展示了 Ingress 的路由分发流程:

  1. 外部客户端发起 HTTP/HTTPS 请求
  2. Ingress Controller 接收请求,根据 Ingress 资源规则进行匹配
  3. 根据 HostPath 将请求路由到对应的 Service
  4. Service 将请求负载均衡到后端的 Pod

3.5 Gateway API:下一代服务路由标准

Gateway API 是 Kubernetes 官方项目,专注于 L4 和 L7 路由,代表了 Kubernetes Ingress、负载均衡和服务网格 API 的下一代演进方向。相比传统的 Ingress API,Gateway API 提供了更强大、更灵活的路由能力。

Gateway API 的核心优势

特性Ingress APIGateway API
角色导向单一角色支持基础设施提供者、集群操作者、应用开发者三种角色
表达能力依赖注解实现高级功能原生支持流量加权、Header 匹配等高级路由
可扩展性有限支持自定义资源扩展
跨命名空间不支持支持共享 Gateway 和跨命名空间路由
协议支持主要 HTTP/HTTPS支持 HTTP、gRPC、TCP、UDP 等多种协议
服务网格集成不支持通过 GAMMA 倡议支持服务网格

Gateway API 的核心资源

  • GatewayClass:定义 Gateway 的实现类型(如 Envoy、Nginx、Contour)
  • Gateway:定义网络入口点,监听端口、TLS 配置等
  • HTTPRoute/GRPCRoute:定义路由规则,支持流量权重、Header 匹配等
Gateway API vs Ingress

Gateway API 不是 Ingress 的简单替代,而是一个更强大、更灵活的 API 框架:

  • Gateway API for Ingress:管理南北向流量(从外部到集群内部)
  • Gateway API for Service Mesh (GAMMA):管理东西向流量(集群内部服务间通信)

Gateway API 已成为 SIG-Network 的官方项目,多个主流实现(如 Envoy Gateway、Kong Gateway、Contour)都已支持。

Gateway API 示例

# GatewayClass:定义 Gateway 的实现类型
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: eg
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller

---
# Gateway:定义网络入口点
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: eg
spec:
gatewayClassName: eg
listeners:
- name: http
protocol: HTTP
port: 80
hostname: "*.example.com"

---
# HTTPRoute:定义路由规则
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: backend
spec:
parentRefs:
- name: eg
hostnames:
- "api.example.com"
rules:
- backendRefs:
- name: api-service
port: 80
何时使用 Gateway API

Gateway API 适合以下场景:

  • 需要更强大的路由能力(流量加权、Header 匹配、灰度发布)
  • 需要跨命名空间共享 Gateway
  • 需要支持多种协议(HTTP、gRPC、TCP、UDP)
  • 计划使用服务网格(Service Mesh)

对于简单的 HTTP/HTTPS 路由需求,传统的 Ingress API 仍然足够。

四、NetworkPolicy:网络策略与安全隔离

4.1 默认网络策略

Kubernetes 集群默认情况下,所有 Pod 之间都是互通的(全通模式)。这种默认行为在多租户环境中可能带来安全风险。

默认全通模式

# 默认情况下,无需任何 NetworkPolicy,所有 Pod 都可以相互通信

默认全拒模式

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: default
spec:
podSelector: {} # 空选择器匹配所有 Pod
policyTypes:
- Ingress
- Egress
安全建议

在生产环境中,建议采用"默认拒绝,显式允许"的策略。首先创建默认拒绝所有流量的 NetworkPolicy,然后为需要通信的 Pod 创建允许规则。

4.2 ingress/egress 规则

NetworkPolicy 支持 ingress(入站)和 egress(出站)两种规则类型。

4.2.1 仅允许入站流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-only
namespace: default
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080

4.2.2 仅允许出站流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-egress-only
namespace: default
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432

4.2.3 同时允许入站和出站流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-both
namespace: default
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
- to:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: UDP
port: 53

4.3 标签选择器与策略匹配

NetworkPolicy 使用标签选择器来匹配 Pod 和 Namespace。

选择器类型用途示例
podSelector匹配同一 Namespace 中的 Podapp: frontend
namespaceSelector匹配 Namespacename: production
podSelector + namespaceSelector匹配特定 Namespace 中的 PodNamespace: team: backend, Pod: app: api

复杂选择器示例

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: complex-selector
namespace: default
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
# 允许同一 Namespace 中标签为 app: frontend 的 Pod
- podSelector:
matchLabels:
app: frontend
# 允许 production Namespace 中所有 Pod
- namespaceSelector:
matchLabels:
env: production
# 允许 monitoring Namespace 中标签为 app: prometheus 的 Pod
- namespaceSelector:
matchLabels:
team: monitoring
podSelector:
matchLabels:
app: prometheus
ports:
- protocol: TCP
port: 8080

4.4 NetworkPolicy 规则匹配示意图

上图展示了 NetworkPolicy 的规则匹配逻辑:

  1. 外部流量被拒绝(未在 ingress 规则中)
  2. frontend Namespace 中的 Pod 可以访问 backend(匹配 app: frontend
  3. production Namespace 中的 Pod 可以访问 backend(匹配 env: production
  4. backend Pods 可以访问 database(匹配 app: database
  5. backend Pods 可以访问 DNS(匹配 DNS 规则)
  6. backend Pods 无法访问互联网(未在 egress 规则中)
NetworkPolicy 依赖

NetworkPolicy 的实现依赖于 CNI 插件。并非所有 CNI 插件都支持 NetworkPolicy:

  • 支持:Calico、Cilium、Weave Net、Romana
  • 不支持:Flannel(需要配合 Canal 使用)

在选择 CNI 插件时,如果需要网络策略功能,请确保插件支持 NetworkPolicy。

五、EndpointSlice 与服务网格简介

5.1 EndpointSlice 机制

EndpointSlice 是 K8s 1.17+ 引入的新特性(v1.21 达到 Stable),用于替代传统的 Endpoints 资源。它将 Pod 端点信息分片存储,解决了大规模集群中 Endpoints 资源过大的问题。

Endpoints API 已废弃(v1.33)

自 Kubernetes v1.33 起,传统的 Endpoints API 已被正式标记为废弃(Deprecated)。相比 EndpointSlice,旧的 Endpoints API 存在以下问题:

  • 不支持双栈集群:无法同时表示 IPv4 和 IPv6 端点
  • 缺少新特性支持:不包含 trafficDistribution 等新功能所需的信息
  • 端点截断:当端点数量超过 1000 时,会截断端点列表,导致部分后端无法接收流量

官方推荐所有用户迁移到 EndpointSlice API。EndpointSlice 由 EndpointSlice 控制器自动管理,无需手动创建。

EndpointSlice 的优势

特性Endpoints(已废弃)EndpointSlice(推荐)
存储方式单个大对象分片存储(每个切片最多 100 个端点)
扩展性受限于单个对象大小(1000 端点截断)支持大规模集群
双栈支持不支持支持 IPv4/IPv6 双栈
拓扑感知不支持支持 Zone、Node 等拓扑信息
性能频繁更新导致性能下降增量更新,性能更好
新特性兼容不支持 trafficDistribution 等完整支持

EndpointSlice 示例

apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: nginx-service-abc123
namespace: default
labels:
kubernetes.io/service-name: nginx-service
addressType: IPv4
ports:
- name: http
protocol: TCP
port: 80
endpoints:
- addresses:
- "10.244.1.2"
nodeName: node-1
zone: zone-a
conditions:
ready: true
- addresses:
- "10.244.1.3"
nodeName: node-1
zone: zone-a
conditions:
ready: true
- addresses:
- "10.244.2.2"
nodeName: node-2
zone: zone-b
conditions:
ready: true
自动管理

EndpointSlice 由 EndpointSlice 控制器自动管理,无需手动创建。当创建 Service 时,控制器会自动创建对应的 EndpointSlice。

5.2 Service Mesh 与 K8s 网络的关系

Service Mesh(服务网格)是建立在 K8s 网络之上的应用层网络抽象,它通过在每个 Pod 中注入 Sidecar 代理来实现流量管理、安全、可观测性等功能。

主流 Service Mesh 对比

特性IstioLinkerdConsul Connect
架构控制平面 + 数据平面控制平面 + 数据平面控制平面 + 数据平面
SidecarEnvoyproxy-wasmEnvoy
性能中等中等
功能丰富中等中等
学习曲线陡峭平缓平缓

Service Mesh 与 K8s 网络的关系

上图展示了 Service Mesh 与 K8s 网络的层次关系:

  1. 应用层:应用容器通过 gRPC/HTTP 协议通信
  2. Sidecar 代理:拦截应用流量,实现流量管理、安全、可观测性
  3. K8s 网络:Service 和 NetworkPolicy 提供四层网络能力
  4. CNI 网络:提供 Pod 间通信的三层网络能力
  5. 节点网络:物理或虚拟机的二层网络
何时使用 Service Mesh

Service Mesh 并非必需,适合以下场景:

  • 微服务数量多(> 50 个服务)
  • 需要细粒度的流量控制(灰度发布、A/B 测试)
  • 需要统一的安全策略(mTLS、授权)
  • 需要深度可观测性(分布式追踪、指标)

对于小规模集群或简单应用,K8s 原生的 Service 和 Ingress 已足够。

六、网络故障排查常用命令

6.1 Pod 网络排查

# 1. 检查 Pod 的 IP 地址
kubectl get pod <pod-name> -o wide

# 2. 检查 Pod 的网络配置
kubectl exec -it <pod-name> -- ip addr
kubectl exec -it <pod-name> -- ip route

# 3. 检查 Pod 的 DNS 解析
kubectl exec -it <pod-name> -- nslookup kubernetes.default
kubectl exec -it <pod-name> -- cat /etc/resolv.conf

# 4. 测试 Pod 间连通性
kubectl exec -it <pod-name-1> -- ping <pod-ip-2>
kubectl exec -it <pod-name-1> -- curl http://<service-name>:<port>

# 5. 检查 Pod 的网络策略
kubectl get networkpolicy -n <namespace>
kubectl describe networkpolicy <policy-name> -n <namespace>

6.2 Service 网络排查

# 1. 检查 Service 的详细信息
kubectl get svc <service-name> -o yaml
kubectl describe svc <service-name>

# 2. 检查 Endpoints/EndpointSlice
kubectl get endpoints <service-name>
kubectl get endpointslice -l kubernetes.io/service-name=<service-name>

# 3. 检查 kube-proxy 日志
kubectl logs -n kube-system -l k8s-app=kube-proxy

# 4. 检查 iptables 规则(在 Node 上执行)
sudo iptables -t nat -L KUBE-SERVICES -n
sudo iptables -t nat -L KUBE-SVC-<hash> -n

# 5. 检查 IPVS 规则(如果使用 IPVS 模式)
sudo ipvsadm -Ln

6.3 Ingress 网络排查

# 1. 检查 Ingress 资源
kubectl get ingress
kubectl describe ingress <ingress-name>

# 2. 检查 Ingress Controller
kubectl get pods -n ingress-nginx
kubectl logs -n ingress-nginx <ingress-controller-pod>

# 3. 检查 Ingress Controller 配置
kubectl exec -n ingress-nginx <ingress-controller-pod> -- cat /etc/nginx/nginx.conf

# 4. 测试 Ingress 路由
curl -v http://<host>/path
curl -v -H "Host: <host>" http://<ingress-ip>/path

# 5. 检查 TLS 证书
kubectl get secret <tls-secret-name> -o yaml
openssl x509 -in <cert-file> -text -noout

6.4 CNI 网络排查

# 1. 检查 CNI 插件 Pod
kubectl get pods -n kube-system | grep -E "calico|cilium|flannel|weave"

# 2. 检查 CNI 插件日志
kubectl logs -n kube-system <cni-plugin-pod>

# 3. 检查节点网络配置(在 Node 上执行)
ip addr
ip route
brctl show # 如果使用网桥模式

# 4. 检查 veth pair(在 Node 上执行)
ip link show type veth

# 5. 测试节点间连通性
ping <other-node-ip>
traceroute <other-node-ip>
排查思路

网络故障排查的一般思路:

  1. 从内到外:先检查 Pod 内部网络,再检查 Service,最后检查 Ingress
  2. 从下到上:先检查 CNI 网络层,再检查 K8s 网络层,最后检查应用层
  3. 分层验证:每层网络都要验证连通性、DNS 解析、端口监听
  4. 日志优先:优先查看相关组件的日志,获取错误信息

七、本章小结

本文深入剖析了 Kubernetes 网络模型与服务发现的核心机制,涵盖了以下关键内容:

核心要点回顾

  1. K8s 网络模型

    • 三个基本要求:Pod 互通、Node 与 Pod 互通、Pod IP 一致性
    • CNI 插件机制:Flannel、Calico、Cilium、Weave Net 各有优劣
    • 三层网络架构:节点网络、Pod 网络、服务网络
  2. Service 服务发现

    • 四种类型:ClusterIP、NodePort、LoadBalancer、ExternalName
    • kube-proxy 工作模式:iptables、IPVS、nftables(v1.33 GA)
    • CoreDNS 服务发现机制
    • Headless Service 与 StatefulSet 的配合使用
    • appProtocol 字段(v1.20 Stable):支持 HTTP/2、WebSocket 等应用协议
    • RelaxedServiceNameValidation(v1.34 Alpha):允许 Service 名称以数字开头
  3. Ingress 七层路由

    • Ingress vs Service 的本质区别
    • 主流 Ingress Controller:Nginx、Traefik、APISIX
    • 基于 Host、Path 的路由配置
    • TLS 证书管理
    • Gateway API:下一代服务路由标准,支持角色导向、流量加权、跨命名空间等高级功能
  4. NetworkPolicy 网络安全

    • 默认全通 vs 默认全拒策略
    • ingress/egress 规则配置
    • 标签选择器的灵活使用
  5. 高级特性

    • EndpointSlice 机制解决大规模集群问题(Endpoints API v1.33 已废弃
    • Gateway API 与 Ingress 的演进关系
    • Service Mesh 与 K8s 网络的关系
  6. 故障排查

    • Pod、Service、Ingress、CNI 各层排查命令
    • 分层验证的排查思路

最佳实践建议

  1. CNI 插件选择

    • 中小集群:Flannel(简单易用)
    • 企业级应用:Calico(功能丰富)
    • 高性能场景:Cilium(eBPF)
  2. Service 类型选择

    • 内部服务:ClusterIP
    • 外部访问:Ingress + LoadBalancer
    • 特殊场景:NodePort(开发测试)、ExternalName(外部服务)
  3. 安全策略

    • 默认拒绝,显式允许
    • 最小权限原则
    • 定期审计 NetworkPolicy
  4. 性能优化

    • 优先使用 nftables 模式(v1.33 GA),其次 IPVS 模式
    • 使用 EndpointSlice(替代已废弃的 Endpoints API)
    • 合理规划 Service 数量

下一步学习

  • 深入学习特定 CNI 插件的配置和调优
  • 掌握 Service Mesh(Istio/Linkerd)的部署和使用
  • 学习网络可观测性工具(如 Cilium Hubble)
  • 实践网络故障排查和性能优化
  • 探索 Gateway API 在生产环境中的应用

Kubernetes 网络是一个庞大而复杂的主题,本文涵盖了其核心概念和最佳实践。在实际应用中,建议根据具体的业务需求和集群规模,选择合适的网络方案,并持续监控和优化网络性能。


相关阅读

作者简介:本文作者专注于云原生技术,拥有丰富的 Kubernetes 实践经验,致力于分享云原生技术最佳实践。