基于 Kubernetes v1.37 源码(pkg/proxy/pkg/controller/endpointslice/

一、为什么需要网络抽象? @

Kubernetes 中 Pod 是短暂的,IP 会变化,多个 Pod 需要统一访问入口:

Pod IP 会变化 → 不能直接访问 Pod
       ↓
需要稳定的访问入口 → Service 抽象
       ↓
多个 Pod 需要负载均衡 → Endpoints/EndpointSlice
       ↓
外部访问 → NodePort / LoadBalancer / Ingress
       ↓
Pod 之间通信 → CNI 网络插件

二、网络体系全景 @

┌─────────────────────────────────────────────────────────────┐
│                      外部流量                                │
│       ↓                                                     │
│  Ingress Controller (Nginx/Traefik/Envoy)                   │
│       ↓                                                     │
│  Service (ClusterIP / NodePort / LoadBalancer)              │
│       ↓                                                     │
│  kube-proxy (iptables / IPVS / nftables)                    │
│       ↓                                                     │
│  Endpoints / EndpointSlice (后端 Pod IP)                     │
│       ↓                                                     │
│  Pod                                                        │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│                    Pod 间通信                                │
│  CNI 插件 (Calico/Flannel/Cilium) → 路由/Overlay           │
└─────────────────────────────────────────────────────────────┘

三、Service @

Service 为一组 Pod 提供稳定的网络端点。

3.1 Service 类型 @

类型 访问范围 用途
ClusterIP 集群内部 默认,仅内部可达
NodePort 节点 IP + 端口 外部直接访问
LoadBalancer 云厂商 LB 自动创建外部负载均衡器
ExternalName CNAME 映射 映射到外部服务
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: ClusterIP
  selector:
    app: nginx
  ports:
  - port: 80          # Service 端口
    targetPort: 8080  # 容器端口
    protocol: TCP

3.2 Service 实现原理 @

ClusterIP 是一个虚拟 IP(VIP),只存在于 iptables/ipvs 规则中:

客户端访问 ClusterIP:80
       ↓
kube-proxy 维护的 iptables/ipvs 规则
       ↓
DNAT 转换 → Pod IP:8080
       ↓
响应返回客户端

四、Endpoints / EndpointSlice @

4.1 Endpoints @

Endpoints 存储 Service 后端所有 Pod 的 IP 和端口:

apiVersion: v1
kind: Endpoints
metadata:
  name: my-service
subsets:
- addresses:
  - ip: 10.244.1.5
    nodeName: node-1
    targetRef:
      kind: Pod
      name: nginx-1
  - ip: 10.244.2.3
    nodeName: node-2
    targetRef:
      kind: Pod
      name: nginx-2
  ports:
  - port: 8080
    protocol: TCP

4.2 EndpointSlice @

EndpointSlice 是 Endpoints 的替代方案,解决大规模集群性能问题:

apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
  name: my-service-abc123
  labels:
    kubernetes.io/service-name: my-service
addressType: IPv4
endpoints:
- addresses: ["10.244.1.5"]
  nodeName: node-1
  conditions:
    ready: true
- addresses: ["10.244.2.3"]
  nodeName: node-2
  conditions:
    ready: true
ports:
- port: 8080
  protocol: TCP

为什么需要 EndpointSlice?

问题 Endpoints EndpointSlice
单对象大小 所有后端在一个对象 每组最多 100 个端点
更新频率 任何变化都更新整个对象 只更新变化的 Slice
扩展性 5000+ Pod 时性能下降 支持 100,000+ 端点

4.3 EndpointSlice Controller @

// pkg/controller/endpointslice/endpointslice_controller.go
func (c *Controller) syncService(logger klog.Logger, key string) error {
    service, err := c.serviceLister.Services(namespace).Get(name)

    // 1. 获取 Service 选择的所有 Pod
    pods, err := c.podLister.Pods(namespace).List(labels.SelectorFromSet(service.Spec.Selector))

    // 2. 按 kubernetes.io/service-name + endpointslice.kubernetes.io/managed-by
    //    标签列出现有的 EndpointSlices
    endpointSlices, err := c.endpointSliceLister.EndpointSlices(namespace).List(esLabelSelector)

    // 3. 计算期望的 Slice,对比现有 Slice,执行增删改
    //    (计算逻辑封装在 staging/src/k8s.io/endpointslice/reconciler.go 的 Reconciler 中)
    err = c.reconciler.Reconcile(logger, service, pods, endpointSlices, lastChangeTriggerTime)
    return nil
}

五、kube-proxy @

kube-proxy 运行在每个节点上,实现 Service 的负载均衡。

5.1 三种模式 @

模式 实现 适用场景
iptables Linux iptables 规则 通用,默认
IPVS IPVS(内核负载均衡) 大规模集群
nftables nftables(iptables 继任者) 未来趋势

5.2 iptables 模式 @

// pkg/proxy/iptables/proxier.go
func (proxier *Proxier) syncProxyRules() {
    // 1. 为每个 Service 创建 KUBE-SVC-XXXX 链及跳转规则
    for svcName, svcInfo := range proxier.serviceMap {
        // ...(KUBE-SERVICES → KUBE-SVC-XXXX 跳转)

        // 2. 为该 Service 的所有 Endpoint 生成 KUBE-SEP-XXXX 链与 DNAT 规则
        proxier.writeServiceToEndpointRules(natRules, svcPortNameString, svcInfo, svcChain, endpoints, args)
    }
}

iptables 规则示例

# 访问 ClusterIP:80
-A KUBE-SERVICES -d 10.96.0.10/32 -p tcp --dport 80 -j KUBE-SVC-ABCDE

# Service 链 → 随机选择后端
-A KUBE-SVC-ABCDE -m statistic --mode random --probability 0.5 -j KUBE-SEP-AAAAA
-A KUBE-SVC-ABCDE -j KUBE-SEP-BBBBB

# DNAT 转换
-A KUBE-SEP-AAAAA -p tcp -j DNAT --to-destination 10.244.1.5:8080
-A KUBE-SEP-BBBBB -p tcp -j DNAT --to-destination 10.244.2.3:8080

5.3 IPVS 模式 @

// pkg/proxy/ipvs/proxier.go
func (proxier *Proxier) syncProxyRules() {
    // 1. 为每个 Service 创建 IPVS 虚拟服务
    for svcName, svcInfo := range proxier.serviceMap {
        vs := &utilipvs.VirtualServer{Address: svcInfo.ClusterIP, Port: svcInfo.Port /* ... */}
        err = proxier.ipvs.AddVirtualServer(vs)

        // 2. 为每个 Endpoint 添加真实服务器
        for _, ep := range svcInfo.Endpoints {
            rs := &utilipvs.RealServer{Address: ep.IP, Port: ep.Port}
            err = proxier.ipvs.AddRealServer(vs, rs)
        }
    }
}

IPVS vs iptables

特性 iptables IPVS
匹配方式 顺序遍历 哈希表 O(1)
规模限制 ~5000 Service 性能下降 10,000+ Service
负载均衡 随机 多种算法(rr/lc/dh/sh)
内核模块 无需额外模块 需要 ip_vs 模块

5.4 nftables 模式 @

// pkg/proxy/nftables/proxier.go
func (proxier *Proxier) syncProxyRules() {
    // 使用 nftables 替代 iptables
    // 优势:原子更新、性能更好、规则更简洁
}

六、Ingress @

Ingress 提供 HTTP/HTTPS 层的路由规则。

6.1 Ingress 资源 @

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: foo.example.com
    http:
      paths:
      - path: /bar
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 80
      - path: /baz
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 80
  tls:
  - hosts:
    - foo.example.com
    secretName: tls-secret

6.2 Ingress Controller @

Ingress 只是规则,需要 Ingress Controller 来执行:

Controller 实现 特点
Nginx Ingress Nginx 最常用,功能丰富
Traefik Traefik 自动发现,云原生
Envoy Ingress Envoy/Istio 服务网格集成
Contour Envoy Kubernetes 原生
Gateway API 多实现 Ingress 的继任者

6.3 Ingress 执行流程 @

外部请求 → Ingress Controller(监听 Ingress 资源)
       ↓
匹配 Host + Path 规则
       ↓
转发到对应的 Service
       ↓
Service → kube-proxy → Pod

七、Gateway API @

Gateway API 是 Ingress 的继任者,解决 Ingress 的功能局限:

apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: example-class
spec:
  controllerName: example.com/gateway-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: example-gateway
spec:
  gatewayClassName: example-class
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: All
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: example-route
spec:
  parentRefs:
  - name: example-gateway
  hostnames:
  - "foo.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /bar
    backendRefs:
    - name: service1
      port: 80

Gateway API vs Ingress

特性 Ingress Gateway API
角色分离 管理员+用户混在一起 GatewayClass/Gateway/Route 分离
多协议 主要 HTTP HTTP/TCP/TLS/gRPC
跨命名空间 不支持 支持
权重路由 注解实现 原生支持

八、CNI(容器网络接口) @

CNI 是 Pod 间通信的基础,由网络插件实现。

8.1 CNI 架构 @

┌────────────────────────────────────────────────────────────┐
│                    Kubernetes 集群                          │
│  ┌──────────────────────────────────────────────────────┐  │
│  │              CNI 插件(二进制 + 配置)                  │  │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐            │  │
│  │  │ Calico   │  │ Flannel  │  │ Cilium   │            │  │
│  │  └──────────┘  └──────────┘  └──────────┘            │  │
│  └──────────────────────────────────────────────────────┘  │
│                            ↓                               │
│  kubelet → CRI → CNI 插件 → 配置 Pod 网络                    │
└────────────────────────────────────────────────────────────┘

8.2 CNI 插件接口 @

// github.com/containernetworking/cni/libcni/api.go
type CNI interface {
    AddNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
    CheckNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
    DelNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
    GetNetworkListCachedResult(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
    GetNetworkListCachedConfig(net *NetworkConfigList, rt *RuntimeConf) ([]byte, *RuntimeConf, error)

    // 单个网络的 Add/Del/Check,以及
    // ValidateNetworkList、GCNetworkList、GetStatusNetworkList 等
    AddNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
    CheckNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error
    DelNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error
    // ...
}

8.3 网络配置流程 @

1. kubelet 创建 Pod
       ↓
2. kubelet 调用 CRI 创建 Sandbox
       ↓
3. CRI 调用 CNI 插件
       ↓
4. CNI 插件执行:
   a. 创建 veth pair
   b. 将一端放入 Pod 网络命名空间
   c. 将一端放入主机网桥
   d. 分配 Pod IP
   e. 配置路由
       ↓
5. Pod 获得 IP,可以通信

8.4 主流 CNI 插件 @

插件 实现 特点
Calico BGP 路由 高性能,网络策略
Flannel VXLAN/Host-gw 简单易用
Cilium eBPF 高性能,可观测性
Weave Net Mesh 网络 零配置
Antrea OVS VMware 开源

8.5 网络策略(NetworkPolicy) @

NetworkPolicy 控制 Pod 之间的通信:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-except-same-namespace
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: my-namespace
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          name: my-namespace

九、DNS(CoreDNS) @

CoreDNS 为集群提供 DNS 服务:

9.1 Service DNS @

# ClusterIP Service
<service-name>.<namespace>.svc.cluster.local

# 示例
my-service.default.svc.cluster.local → 10.96.0.10

9.2 Pod DNS @

# Pod(需启用 hostname/subdomain)
<pod-ip-dashed>.<namespace>.pod.cluster.local

# 示例
10-244-1-5.default.pod.cluster.local

9.3 CoreDNS 配置 @

apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        health
        kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods insecure
            fallthrough in-addr.arpa ip6.arpa
        }
        prometheus :9153
        forward . /etc/resolv.conf
        cache 30
        loop
        reload
        loadbalance
    }

十、完整流量路径 @

10.1 集群内访问 @

客户端 Pod → Service ClusterIP
       ↓
kube-proxy(iptables/ipvs)
       ↓
DNAT 转换 → 选择后端 Pod
       ↓
响应返回客户端

10.2 外部访问(NodePort) @

外部请求 → 节点 IP:NodePort
       ↓
kube-proxy 拦截
       ↓
DNAT 转换 → 选择后端 Pod
       ↓
响应返回外部

10.3 外部访问(LoadBalancer) @

外部请求 → 云厂商 LB IP
       ↓
LB 转发到节点 NodePort
       ↓
kube-proxy 拦截
       ↓
DNAT 转换 → 选择后端 Pod
       ↓
响应返回外部

10.4 外部访问(Ingress) @

外部请求 → Ingress Controller(80/443)
       ↓
匹配 Host + Path 规则
       ↓
转发到对应 Service
       ↓
kube-proxy → Pod
       ↓
响应返回外部

十一、生产最佳实践 @

11.1 使用 IPVS 模式 @

apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
ipvs:
  scheduler: lc  # 最少连接

11.2 启用 EndpointSlice @

# 默认已启用,检查状态
kubectl get endpointslices -A

11.3 使用 NetworkPolicy @

# 默认拒绝所有 ingress
kubectl apply -f deny-all.yaml

# 按需开放
kubectl apply -f allow-specific.yaml

11.4 使用 Gateway API @

# 安装 Gateway API CRD(standard channel,版本以最新发布为准)
kubectl apply --server-side -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.6.1/standard-install.yaml

十二、设计亮点总结 @

  • 分层抽象:Service 提供稳定 VIP,Endpoints 维护后端 Pod IP,kube-proxy 实现负载均衡,Ingress 处理 HTTP 路由,CNI 管理 Pod 网络。
  • kube-proxy 多模式:iptables/IPVS/nftables 适应不同规模和场景。
  • EndpointSlice:解决大规模集群性能问题,支持 100,000+ 端点。
  • Gateway API:角色分离,功能更强大,是 Ingress 的继任者。

十三、总结 @

Kubernetes 网络体系的设计体现了几个核心思想:

  • 分层解耦:Service → Endpoints → kube-proxy → Pod
  • 可插拔:CNI、Ingress Controller、kube-proxy 模式均可替换
  • 可扩展:EndpointSlice、Gateway API 解决规模问题
  • 安全性:NetworkPolicy 实现微隔离

理解网络体系,就掌握了 Kubernetes 服务间通信和外部访问的关键。