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 核心字段之间的协作流程,从策略定义到流量匹配的完整链路:
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 关系,只要一个规则匹配即放行,不会叠加拒绝。