3. NetworkPolicy 核心概念:Ingress/Egress 规则、Pod 选择器、命名空间选择器、策略类型

在 Kubernetes 网络模型中,NetworkPolicy 是一种以应用为中心的资源对象,用于控制 Pod 之间以及 Pod 与外部端点之间的网络流量。理解其核心概念是构建精准、高效网络策略的基础,也是后续进行策略命中率分析与误报复核的前提。

3.1 策略类型:Ingress、Egress 与双向控制

NetworkPolicy 通过 policyTypes 字段声明策略生效的方向。该字段是一个字符串数组,可包含 Ingress、Egress 或两者。若未显式指定,默认行为如下:

  • 仅定义 Ingress 规则:policyTypes 默认为 ["Ingress"]。
  • 仅定义 Egress 规则:policyTypes 默认为 ["Egress"]。
  • 同时定义 Ingress 和 Egress 规则:policyTypes 必须显式包含两者,否则未声明的方向将不受策略约束。
关键理解: 一旦某个 Pod 被 NetworkPolicy 选中,其对应方向(Ingress 或 Egress)的流量将默认被 拒绝,除非有显式的允许规则匹配。这是“白名单”机制的核心。
策略类型 控制方向 默认行为(被选中后) 典型场景
Ingress 入站流量(进入 Pod) 拒绝所有入站流量 保护数据库 Pod,仅允许应用 Pod 访问
Egress 出站流量(离开 Pod) 拒绝所有出站流量 限制恶意 Pod 外联,仅允许访问特定 API
Ingress + Egress 双向流量 拒绝所有入站和出站流量 高安全隔离环境,如支付服务 Pod
NetworkPolicy 策略类型与流量方向 目标 Pod Ingress 规则 (控制入站流量) Egress 规则 (控制出站流量) 策略类型声明示例 policyTypes: ["Ingress"] → 仅控制入站,出站不受限 policyTypes: ["Ingress", "Egress"] → 双向控制,默认全拒绝

3.2 Pod 选择器:策略作用的目标

spec.podSelector 是 NetworkPolicy 的核心定位机制。它使用标准的 Kubernetes 标签选择器(Label Selector)来匹配命名空间内的 Pod。匹配到的 Pod 将成为该策略的“目标 Pod”,其流量行为将受规则约束。

  • 空选择器 {}:匹配命名空间内的 所有 Pod。常用于全局默认拒绝策略。
  • 非空选择器:仅匹配标签完全符合的 Pod。例如 matchLabels: { app: frontend }。
  • 与关系:matchLabels 中的多个标签是逻辑“与”关系,Pod 必须同时拥有所有指定标签。
  • 表达式选择器:matchExpressions 支持更复杂的匹配逻辑,如 In、NotIn、Exists、DoesNotExist。
最佳实践: 在定义 Pod 选择器时,应使用具有业务含义的标签(如 tier: backend、component: redis),避免使用 Pod 名称或 IP 等易变属性。这有助于策略的可读性和可维护性。

3.3 命名空间选择器:跨命名空间流量控制

在 Ingress 或 Egress 规则中,from 和 to 字段可以包含 namespaceSelector,用于匹配其他命名空间。这实现了跨命名空间的流量隔离与授权。

  • 独立使用:namespaceSelector: { matchLabels: { team: platform } } 匹配所有标签为 team: platform 的命名空间。
  • 与 Pod 选择器组合:同时指定 namespaceSelector 和 podSelector,表示“来自特定命名空间中的特定 Pod”。两者是逻辑“与”关系。
  • 空选择器:namespaceSelector: {} 匹配 所有命名空间,包括 kube-system 等系统命名空间。使用时需谨慎。
选择器组合 匹配范围 示例
仅 podSelector 本命名空间内的特定 Pod podSelector: { matchLabels: { app: web } }
仅 namespaceSelector 所有命名空间(匹配标签的) namespaceSelector: { matchLabels: { env: prod } }
namespaceSelector + podSelector 特定命名空间中的特定 Pod namespaceSelector: {...}, podSelector: { matchLabels: { app: api } }
ipBlock 集群外部的 CIDR 范围 ipBlock: { cidr: "10.0.0.0/8", except: ["10.96.0.0/12"] }
选择器层级与流量匹配逻辑 Kubernetes 集群 命名空间 A (team: platform) Pod A1 (app: web) Pod A2 (app: api) 命名空间 B (team: data) Pod B1 (app: db) Pod B2 (app: cache) 选择器匹配示例 namespaceSelector: {matchLabels: {team: platform}} + podSelector: {matchLabels: {app: web}} → 仅匹配 Pod A1

3.4 Ingress 与 Egress 规则详解

规则体 ingress 和 egress 是策略的具体执行逻辑。每个规则体是一个数组,数组内的多个规则是逻辑“或”关系——只要匹配其中一条,流量即被允许。

3.4.1 Ingress 规则结构

ingress:
  - from:                    # 来源列表(或关系)
    - podSelector:           # 来源 Pod 选择器
        matchLabels:
          app: frontend
      namespaceSelector:     # 来源命名空间选择器(与 podSelector 是与关系)
        matchLabels:
          env: production
    - ipBlock:               # 来源 IP 段
        cidr: 10.0.0.0/8
        except:
          - 10.96.0.0/12
    ports:                   # 目标端口列表(与 from 是与关系)
      - protocol: TCP
        port: 8080
      - protocol: UDP
        port: 53

3.4.2 Egress 规则结构

egress:
  - to:                      # 目标列表(或关系)
    - podSelector:           # 目标 Pod 选择器
        matchLabels:
          app: database
      namespaceSelector:     # 目标命名空间选择器
        matchLabels:
          team: data
    - ipBlock:               # 目标 IP 段
        cidr: 0.0.0.0/0
        except:
          - 10.0.0.0/8
    ports:                   # 目标端口列表
      - protocol: TCP
        port: 5432
常见误区: 在同一个 from 或 to 条目中,podSelector 和 namespaceSelector 是逻辑“与”关系;而不同 from 或 to 条目之间是逻辑“或”关系。理解这一层级关系是避免策略误报的关键。

3.5 策略类型与选择器的协同工作

一个完整的 NetworkPolicy 将上述概念整合在一起。以下是一个同时控制 Ingress 和 Egress 的示例:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-allow-policy
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: api-server
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - protocol: TCP
          port: 8443
  egress:
    - to:
        - podSelector:
            matchLabels:
              app: database
        - ipBlock:
            cidr: 10.100.0.0/16
      ports:
        - protocol: TCP
          port: 5432

该策略的含义:

  • 目标:命名空间 production 中标签为 app: api-server 的 Pod。
  • Ingress:仅允许来自本命名空间内标签为 app: frontend 的 Pod 访问 TCP 8443 端口。
  • Egress:仅允许访问本命名空间内标签为 app: database 的 Pod 的 TCP 5432 端口,以及 10.100.0.0/16 网段内的任意 IP。
  • 默认拒绝:所有其他入站和出站流量将被拒绝。

3.6 策略命中率与误报的根源

理解上述核心概念后,我们可以定位策略命中率低和误报的常见原因:

问题类型 根本原因 影响
命中率低 Pod 选择器标签不匹配;命名空间选择器范围过窄;端口协议不匹配 策略未生效,流量被意外拒绝或允许
误报(假阳性) 选择器范围过宽(如空选择器);ipBlock 包含意外网段;规则“或”关系导致意外放行 安全审计告警,但实际流量正常
误报(假阴性) 未声明 policyTypes 导致方向缺失;from/to 条目内“与”关系误用为“或” 恶意流量未被拦截,安全漏洞
核验方法: 在镜像拉取加速场景中,建议使用 kubectl describe networkpolicy 查看策略详情,并结合 kubectl get pods --show-labels 确认标签一致性。对于复杂策略,可使用 kubectl netpol 插件或 kubectl-sniff 进行实时流量验证。