4. 网络策略(NetworkPolicy)基础:NetworkPolicy API介绍、Pod选择器与命名空间选择器、策略方向(Ingress/Egress)
4.1 NetworkPolicy API 概述
NetworkPolicy 是 Kubernetes 内置的 API 资源,用于控制 Pod 组之间的网络通信。在 Serverless 集群中,Pod 生命周期短、密度高,网络策略是实现租户隔离、微服务访问控制和最小权限安全基线的核心手段。
NetworkPolicy 工作在 OSI 第 3/4 层(IP + 端口),由 kube-network-policies 控制器或 CNI 插件(如 Calico、Cilium)负责执行。其 API 版本为 networking.k8s.io/v1,核心字段如下:
| 字段 | 类型 | 说明 |
|---|---|---|
podSelector |
LabelSelector | 选择策略生效的目标 Pod 组 |
policyTypes |
[]PolicyType | 声明策略方向:Ingress、Egress 或两者 |
ingress |
[]IngressRule | 入站规则列表,定义允许访问目标 Pod 的源 |
egress |
[]EgressRule | 出站规则列表,定义目标 Pod 允许访问的目的地 |
4.2 Pod 选择器与命名空间选择器
选择器是 NetworkPolicy 的“寻址系统”,决定了策略的生效范围和规则匹配对象。分为两类:
4.2.1 Pod 选择器(podSelector)
通过标签选择目标 Pod。空选择器 {} 表示选中命名空间内所有 Pod。示例:
spec:
podSelector:
matchLabels:
app: api-gateway
该策略只对带有 app=api-gateway 标签的 Pod 生效。
4.2.2 命名空间选择器(namespaceSelector)
在 Ingress/Egress 规则中,使用 namespaceSelector 限定源或目标 Pod 所在的命名空间。常与 podSelector 组合使用:
ingress:
- from:
- namespaceSelector:
matchLabels:
team: platform
podSelector:
matchLabels:
role: monitor
上述规则表示:只允许来自 team=platform 命名空间中 role=monitor 的 Pod 访问目标 Pod。
podSelector单独使用 → 同命名空间内选择namespaceSelector单独使用 → 跨命名空间选择所有 PodnamespaceSelector+podSelector→ 跨命名空间且精确到 Pod 标签ipBlock→ 基于 CIDR 选择集群外部 IP
4.3 策略方向:Ingress 与 Egress
NetworkPolicy 通过 policyTypes 字段显式声明策略方向。如果不声明,默认只处理 Ingress;如果声明了 Egress,则必须同时定义 egress 规则。
4.3.1 Ingress(入站)规则
控制外部流量能否进入目标 Pod。每个 Ingress 规则包含 from 和 ports:
ingress:
- from:
- ipBlock:
cidr: 10.0.0.0/16
except:
- 10.0.1.0/24
ports:
- protocol: TCP
port: 8080
4.3.2 Egress(出站)规则
控制目标 Pod 能否访问外部。每个 Egress 规则包含 to 和 ports:
egress:
- to:
- namespaceSelector:
matchLabels:
name: database
ports:
- protocol: TCP
port: 5432
4.4 完整策略示例与字段解析
以下是一个同时控制 Ingress 和 Egress 的完整示例,适用于 Serverless 微服务场景:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-egress-db-ingress-monitor
namespace: production
spec:
podSelector:
matchLabels:
app: order-service
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
tier: frontend
podSelector:
matchLabels:
app: web-ui
ports:
- protocol: TCP
port: 3000
egress:
- to:
- namespaceSelector:
matchLabels:
name: database
podSelector:
matchLabels:
role: primary
ports:
- protocol: TCP
port: 5432
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
ports:
- protocol: UDP
port: 53
- 目标 Pod:production 命名空间中
app=order-service的 Pod - Ingress:只允许来自
tier=frontend命名空间中app=web-ui的 Pod 访问 TCP 3000 端口 - Egress 规则 1:允许访问
name=database命名空间中role=primary的 Pod 的 TCP 5432 端口 - Egress 规则 2:允许访问外部 DNS(UDP 53),但排除私有 IP 段
4.5 策略生效规则与默认行为
| 场景 | 行为 | 说明 |
|---|---|---|
| 无任何 NetworkPolicy | 允许所有流量 | 默认宽松模式,不推荐生产使用 |
| 仅定义 Ingress 规则 | 拒绝未匹配的入站流量;出站默认允许 | 需在 policyTypes 中显式声明 Ingress |
| 仅定义 Egress 规则 | 拒绝未匹配的出站流量;入站默认允许 | 需在 policyTypes 中显式声明 Egress |
| 同时定义 Ingress + Egress | 双向白名单,未匹配流量均被拒绝 | 最严格模式,Serverless 推荐 |
| 多条策略命中同一 Pod | 规则取并集(OR 逻辑) | 只要有一条策略允许,流量即通过 |
policyTypes: [Ingress, Egress],并显式定义必要的出站规则。
4.6 Serverless 环境下的最佳实践
- 显式声明 policyTypes:始终同时声明 Ingress 和 Egress,避免默认行为带来的安全盲区。
- 使用命名空间隔离:为每个租户或环境创建独立命名空间,并通过
namespaceSelector控制跨命名空间通信。 - 精确端口控制:在 Serverless 场景中,Pod 通常只暴露一个端口,务必在策略中指定
port字段,避免开放所有端口。 - Egress 规则包含 DNS:Serverless 工作负载频繁进行服务发现,必须允许 UDP 53 端口的出站流量,否则 DNS 解析失败。
- 避免空选择器:除非确实需要策略作用于命名空间内所有 Pod,否则始终使用精确的
matchLabels,减少误拦截。
kubectl describe networkpolicy <name> 查看策略详情;使用 kubectl run --image=nicolaka/netshoot 临时 Pod 进行连通性测试,验证策略是否按预期生效。