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 |
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"] } |
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 进行实时流量验证。