4. 网络策略(NetworkPolicy)基础:NetworkPolicy API介绍、Pod选择器与命名空间选择器、策略方向(Ingress/Egress)

4.1 NetworkPolicy API 概述

NetworkPolicy 是 Kubernetes 内置的 API 资源,用于控制 Pod 组之间的网络通信。在 Serverless 集群中,Pod 生命周期短、密度高,网络策略是实现租户隔离、微服务访问控制和最小权限安全基线的核心手段。

NetworkPolicy 工作在 OSI 第 3/4 层(IP + 端口),由 kube-network-policies 控制器或 CNI 插件(如 Calico、Cilium)负责执行。其 API 版本为 networking.k8s.io/v1,核心字段如下:

字段 类型 说明
podSelector LabelSelector 选择策略生效的目标 Pod 组
policyTypes []PolicyType 声明策略方向:Ingress、Egress 或两者
ingress []IngressRule 入站规则列表,定义允许访问目标 Pod 的源
egress []EgressRule 出站规则列表,定义目标 Pod 允许访问的目的地
关键认知:NetworkPolicy 是“白名单”机制——未显式允许的流量默认被拒绝。当集群中没有任何 NetworkPolicy 时,默认允许所有流量;一旦创建一条策略,该策略生效范围内的 Pod 将只允许匹配规则的流量。

4.2 Pod 选择器与命名空间选择器

选择器是 NetworkPolicy 的“寻址系统”,决定了策略的生效范围和规则匹配对象。分为两类:

4.2.1 Pod 选择器(podSelector)

通过标签选择目标 Pod。空选择器 {} 表示选中命名空间内所有 Pod。示例:

spec:
  podSelector:
    matchLabels:
      app: api-gateway

该策略只对带有 app=api-gateway 标签的 Pod 生效。

4.2.2 命名空间选择器(namespaceSelector)

在 Ingress/Egress 规则中,使用 namespaceSelector 限定源或目标 Pod 所在的命名空间。常与 podSelector 组合使用:

ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          team: platform
      podSelector:
        matchLabels:
          role: monitor

上述规则表示:只允许来自 team=platform 命名空间中 role=monitor 的 Pod 访问目标 Pod。

组合规则速查表:
  • podSelector 单独使用 → 同命名空间内选择
  • namespaceSelector 单独使用 → 跨命名空间选择所有 Pod
  • namespaceSelector + podSelector → 跨命名空间且精确到 Pod 标签
  • ipBlock → 基于 CIDR 选择集群外部 IP

4.3 策略方向:Ingress 与 Egress

NetworkPolicy 通过 policyTypes 字段显式声明策略方向。如果不声明,默认只处理 Ingress;如果声明了 Egress,则必须同时定义 egress 规则。

4.3.1 Ingress(入站)规则

控制外部流量能否进入目标 Pod。每个 Ingress 规则包含 from 和 ports:

ingress:
  - from:
    - ipBlock:
        cidr: 10.0.0.0/16
        except:
          - 10.0.1.0/24
    ports:
      - protocol: TCP
        port: 8080

4.3.2 Egress(出站)规则

控制目标 Pod 能否访问外部。每个 Egress 规则包含 to 和 ports:

egress:
  - to:
    - namespaceSelector:
        matchLabels:
          name: database
    ports:
      - protocol: TCP
        port: 5432
Serverless 环境注意:当 Pod 需要访问集群外部服务(如对象存储、DNS)时,必须显式添加 Egress 规则。Serverless 工作负载常因缺少 Egress 规则导致启动超时或依赖调用失败。
NetworkPolicy 流量方向与选择器关系 目标 Pod app: api-gateway Ingress 源 namespaceSelector + podSelector Egress 目标 namespaceSelector / ipBlock 允许入站 允许出站 命名空间选择器 namespaceSelector.matchLabels: team=platform Pod 选择器 podSelector.matchLabels: role=monitor 组合使用:跨命名空间 + 精确 Pod 标签匹配

4.4 完整策略示例与字段解析

以下是一个同时控制 Ingress 和 Egress 的完整示例,适用于 Serverless 微服务场景:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-egress-db-ingress-monitor
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: order-service
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              tier: frontend
          podSelector:
            matchLabels:
              app: web-ui
      ports:
        - protocol: TCP
          port: 3000
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              name: database
          podSelector:
            matchLabels:
              role: primary
      ports:
        - protocol: TCP
          port: 5432
    - to:
        - ipBlock:
            cidr: 0.0.0.0/0
            except:
              - 10.0.0.0/8
              - 172.16.0.0/12
              - 192.168.0.0/16
      ports:
        - protocol: UDP
          port: 53
示例解读:
  • 目标 Pod:production 命名空间中 app=order-service 的 Pod
  • Ingress:只允许来自 tier=frontend 命名空间中 app=web-ui 的 Pod 访问 TCP 3000 端口
  • Egress 规则 1:允许访问 name=database 命名空间中 role=primary 的 Pod 的 TCP 5432 端口
  • Egress 规则 2:允许访问外部 DNS(UDP 53),但排除私有 IP 段

4.5 策略生效规则与默认行为

场景 行为 说明
无任何 NetworkPolicy 允许所有流量 默认宽松模式,不推荐生产使用
仅定义 Ingress 规则 拒绝未匹配的入站流量;出站默认允许 需在 policyTypes 中显式声明 Ingress
仅定义 Egress 规则 拒绝未匹配的出站流量;入站默认允许 需在 policyTypes 中显式声明 Egress
同时定义 Ingress + Egress 双向白名单,未匹配流量均被拒绝 最严格模式,Serverless 推荐
多条策略命中同一 Pod 规则取并集(OR 逻辑) 只要有一条策略允许,流量即通过
常见陷阱:在 Serverless 集群中,如果只定义 Ingress 规则而未定义 Egress 规则,Pod 仍然可以访问外部网络。这可能导致数据泄露。建议始终同时声明 policyTypes: [Ingress, Egress],并显式定义必要的出站规则。
NetworkPolicy 流量决策流程 流量到达 Pod 有策略命中? 默认允许 (无策略时) 检查规则 Ingress/Egress 匹配规则? 允许通过 白名单匹配 拒绝流量 默认拒绝 核心原则:白名单机制 有策略时,未显式允许的流量一律拒绝;多条策略取并集

4.6 Serverless 环境下的最佳实践

  • 显式声明 policyTypes:始终同时声明 Ingress 和 Egress,避免默认行为带来的安全盲区。
  • 使用命名空间隔离:为每个租户或环境创建独立命名空间,并通过 namespaceSelector 控制跨命名空间通信。
  • 精确端口控制:在 Serverless 场景中,Pod 通常只暴露一个端口,务必在策略中指定 port 字段,避免开放所有端口。
  • Egress 规则包含 DNS:Serverless 工作负载频繁进行服务发现,必须允许 UDP 53 端口的出站流量,否则 DNS 解析失败。
  • 避免空选择器:除非确实需要策略作用于命名空间内所有 Pod,否则始终使用精确的 matchLabels,减少误拦截。
调试技巧:使用 kubectl describe networkpolicy <name> 查看策略详情;使用 kubectl run --image=nicolaka/netshoot 临时 Pod 进行连通性测试,验证策略是否按预期生效。