3. NetworkPolicy 资源定义:核心字段解析

NetworkPolicy 是 Kubernetes 原生的网络隔离资源,其核心在于通过 podSelector、policyTypes 以及 ingress/egress 规则字段,精确控制 Pod 级别的入站与出站流量。理解这三个字段的协作关系,是编写跨命名空间 Helm Chart 通信规则的基础。

3.1 核心字段总览

一个完整的 NetworkPolicy 资源由以下四个关键字段构成,其中前三个字段直接决定策略的生效范围与流量方向:

字段 类型 作用 是否必填
podSelector LabelSelector 选择策略生效的目标 Pod 集合 是
policyTypes []string 声明策略生效的流量方向(Ingress / Egress / 两者) 推荐显式声明
ingress []IngressRule 定义允许入站流量的来源与端口 按需
egress []EgressRule 定义允许出站流量的目标与端口 按需
最佳实践:在 Helm Chart 中始终显式声明 policyTypes 字段。如果不声明,Kubernetes 默认仅对 ingress 规则生效,可能导致出站流量意外被放行或拦截。

3.2 podSelector:策略的目标选择器

podSelector 使用标签选择器(LabelSelector)来匹配命名空间内的 Pod。其行为遵循以下规则:

  • 精确匹配:通过 matchLabels 指定一组键值对,Pod 必须包含所有指定标签才被选中。
  • 表达式匹配:通过 matchExpressions 支持 In、NotIn、Exists、DoesNotExist 等操作符。
  • 空选择器:如果 podSelector: {},则选中命名空间内的 所有 Pod。
# 示例:选择带有 app=frontend 标签的 Pod
podSelector:
  matchLabels:
    app: frontend
注意:podSelector 仅作用于当前命名空间。如果需要跨命名空间选择目标 Pod,必须在 ingress/egress 规则中使用 namespaceSelector 或 ipBlock。

3.3 policyTypes:流量方向的显式声明

policyTypes 是一个字符串数组,用于明确告知 Kubernetes 该策略需要控制哪些方向的流量。它解决了早期版本中默认行为不明确的问题。

policyTypes 值 生效规则 典型场景
["Ingress"] 仅控制入站流量 只允许特定来源访问数据库
["Egress"] 仅控制出站流量 只允许应用访问特定外部 API
["Ingress", "Egress"] 同时控制入站和出站流量 微服务间双向严格隔离
# 示例:同时声明入站和出站规则
policyTypes:
  - Ingress
  - Egress
关键理解:如果 policyTypes 包含 Egress 但未定义 egress 规则,则所有出站流量都会被拒绝。这是实现“默认拒绝”策略的常用手法。

3.4 ingress/egress 规则:流量准入与准出

ingress 和 egress 规则定义了具体的流量控制逻辑。每个规则包含 来源/目标选择器 和 端口 两部分。

3.4.1 ingress 规则结构

ingress:
  - from:                    # 来源列表(多个来源之间是 OR 关系)
    - podSelector:           # 来源 Pod 标签选择器(同命名空间)
        matchLabels:
          app: backend
    - namespaceSelector:     # 来源命名空间标签选择器(跨命名空间)
        matchLabels:
          team: data
    - ipBlock:               # 来源 IP 地址段(外部流量)
        cidr: 10.0.0.0/16
        except:
          - 10.0.1.0/24
    ports:                   # 目标端口列表(多个端口之间是 OR 关系)
    - protocol: TCP
      port: 8080

3.4.2 egress 规则结构

egress:
  - to:                      # 目标列表(多个目标之间是 OR 关系)
    - podSelector:
        matchLabels:
          app: database
    - namespaceSelector:
        matchLabels:
          environment: production
    - ipBlock:
        cidr: 0.0.0.0/0      # 允许访问所有外部 IP
        except:
          - 10.0.0.0/8       # 排除内部网段
    ports:
    - protocol: TCP
      port: 5432
跨命名空间通信要点:当使用 namespaceSelector 时,可以结合 podSelector 实现更精细的控制。例如:namespaceSelector 选择命名空间,podSelector 在该命名空间内进一步筛选 Pod。两者同时出现时,是 AND 关系。

3.5 核心字段协作关系图

下图展示了 NetworkPolicy 核心字段之间的协作流程,从策略定义到流量匹配的完整链路:

NetworkPolicy 核心字段协作流程 NetworkPolicy podSelector policyTypes 匹配目标 Pod 集合 ingress 规则 from + ports egress 规则 to + ports 允许/拒绝入站流量 允许/拒绝出站流量 policyTypes 决定 哪些规则被激活

3.6 规则组合逻辑:AND 与 OR

理解 NetworkPolicy 中多个选择器之间的逻辑关系,是避免配置错误的关键:

组合位置 逻辑关系 示例
同一规则内多个选择器(如 from 下的 podSelector + namespaceSelector) AND:必须同时满足 来自命名空间 A 且 标签为 app=web 的 Pod
同一规则内多个条目(如 from 列表中的多个独立块) OR:满足任一即可 来自命名空间 A 或 来自 IP 段 10.0.0.0/16
多个 ingress/egress 规则(数组中的多个规则) OR:满足任一规则即放行 规则 1 允许端口 80 或 规则 2 允许端口 443

3.7 完整示例:跨命名空间通信策略

以下是一个完整的 NetworkPolicy 示例,展示如何允许 frontend 命名空间中的 Pod 访问 backend 命名空间中的数据库 Pod:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-db
  namespace: backend
spec:
  podSelector:
    matchLabels:
      app: database
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              name: frontend
          podSelector:
            matchLabels:
              app: web
      ports:
        - protocol: TCP
          port: 5432
策略解读:该策略部署在 backend 命名空间,选中标签为 app=database 的 Pod。仅允许来自 frontend 命名空间(标签 name=frontend)且标签为 app=web 的 Pod 通过 TCP 5432 端口访问。其他所有入站流量被隐式拒绝。

3.8 常见配置陷阱

  • 遗漏 policyTypes:未声明时,Kubernetes 默认只应用 Ingress 规则,Egress 规则被忽略。
  • 空 podSelector 误解:podSelector: {} 选中所有 Pod,而非“不生效”。
  • 跨命名空间 namespaceSelector 缺失:仅使用 podSelector 无法跨命名空间选择目标。
  • 端口协议不匹配:默认协议为 TCP,如果服务使用 UDP 或 SCTP,必须显式声明。
  • 多个规则间的 OR 关系误判:多个 ingress 规则是 OR 关系,只要一个规则匹配即放行,不会叠加拒绝。