3. Kubernetes 网络策略回顾:NetworkPolicy 资源定义、Pod 选择器、Ingress/Egress 规则
在深入 Cilium 网络策略之前,必须牢固掌握 Kubernetes 原生 NetworkPolicy 的设计哲学与核心机制。Kubernetes 网络策略是一种以应用为中心(Application-Centric)的声明式防火墙规则,它通过标签选择器(Label Selector)动态匹配 Pod,并基于四层(L3/L4)协议与端口控制流量。本节将系统回顾其资源定义结构、Pod 选择器的工作模式以及 Ingress/Egress 规则的配置逻辑。
3.1 NetworkPolicy 资源定义结构
一个标准的 NetworkPolicy 资源由 spec 中的三个核心字段构成:podSelector、policyTypes、以及 ingress/egress 规则数组。以下是一个同时定义了入站与出站规则的完整示例:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-allow-policy
namespace: production
spec:
podSelector:
matchLabels:
app: backend-api
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend-web
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
下表总结了各字段的语义与约束:
| 字段 | 类型 | 说明 |
|---|---|---|
podSelector |
LabelSelector | 必填。选择策略所作用的 Pod 集合。空选择器({})匹配命名空间下所有 Pod。 |
policyTypes |
[]PolicyType | 可选。显式声明策略生效方向。若省略,默认根据规则存在情况推断:有 ingress 规则则包含 Ingress,有 egress 规则则包含 Egress。 |
ingress |
[]IngressRule | 可选。入站白名单规则列表。每个规则包含 from(来源选择器)和 ports(目标端口)。 |
egress |
[]EgressRule | 可选。出站白名单规则列表。每个规则包含 to(目标选择器)和 ports(目标端口)。 |
ingress: [] 或 egress: [])意味着拒绝所有对应方向的流量。
3.2 Pod 选择器:标签驱动的动态匹配
Pod 选择器是 NetworkPolicy 的“寻址”核心。它使用 Kubernetes 标签选择器语法,支持两种匹配模式:
- matchLabels:精确匹配。要求目标 Pod 必须包含所有指定的标签键值对。
- matchExpressions:表达式匹配。支持
In、NotIn、Exists、DoesNotExist四种操作符,用于更复杂的集合运算。
选择器可以出现在三个位置,分别控制不同的作用域:
- spec.podSelector:定义“谁”被策略保护(目标 Pod)。
- ingress[].from[].podSelector:定义“谁”可以访问目标 Pod(来源 Pod)。
- egress[].to[].podSelector:定义目标 Pod 可以访问“谁”(目的 Pod)。
podSelector 仅在当前 NetworkPolicy 所在的命名空间内生效。如果需要跨命名空间匹配,必须使用 namespaceSelector 或 ipBlock。
以下 SVG 图展示了 Pod 选择器在 Ingress 规则中的匹配流程:
3.3 Ingress 规则:入站流量控制
Ingress 规则定义允许哪些来源(from)访问目标 Pod 的哪些端口(ports)。from 字段是一个数组,支持四种来源选择器类型,它们之间是 OR 逻辑:
| 来源类型 | 字段 | 作用域 | 示例 |
|---|---|---|---|
| Pod 选择器 | podSelector |
同命名空间 | 允许来自 app=frontend 的 Pod |
| 命名空间选择器 | namespaceSelector |
跨命名空间 | 允许来自 env=staging 命名空间的所有 Pod |
| 命名空间 + Pod 组合 | namespaceSelector + podSelector |
跨命名空间 + 精确 Pod | 允许来自 env=prod 命名空间中 app=monitor 的 Pod |
| IP 段 | ipBlock |
集群外部或 CIDR | 允许来自 10.0.0.0/16 的流量 |
ipBlock 不经过 Kubernetes 标签系统,直接基于 IP 地址匹配。在动态容器环境中,Pod IP 会频繁变化,因此 ipBlock 通常用于控制集群外部流量或与裸金属设备通信,不推荐用于 Pod 间策略。
3.4 Egress 规则:出站流量控制
Egress 规则定义目标 Pod 允许访问哪些目的地(to)以及使用哪些端口。to 字段的语法与 from 完全对称,同样支持四种目标选择器类型,且多个条目之间为 OR 逻辑。
以下是一个典型的 Egress 规则示例,允许 app=backend-api 的 Pod 访问 app=database 的 Pod 的 5432 端口,同时允许访问集群外部 DNS 服务:
spec:
podSelector:
matchLabels:
app: backend-api
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8
ports:
- protocol: UDP
port: 53
以下 SVG 图对比了 Ingress 与 Egress 规则在 Pod 视角下的流量方向:
3.5 策略生效规则与常见陷阱
理解以下生效规则对于编写正确的 NetworkPolicy 至关重要:
- 默认拒绝:一旦命名空间中存在任何一条 NetworkPolicy 匹配到某个 Pod,该 Pod 的未显式允许的流量将被拒绝。如果命名空间中没有任何 NetworkPolicy,则所有 Pod 的流量默认全部允许。
- 规则叠加(AND/OR):同一 NetworkPolicy 内的多个
from或to条目是 OR 关系;多条 NetworkPolicy 作用于同一个 Pod 时,规则之间也是 OR 关系——只要有一条策略允许,流量即被放行。 - 空选择器:
podSelector: {}匹配命名空间下所有 Pod。这在隔离整个命名空间时非常有用。 - 端口必须显式声明:如果
ports字段未指定,则规则匹配所有端口。一旦指定了端口,则只匹配指定端口。