2、K8s网络策略(NetworkPolicy)基础:NetworkPolicy资源定义、Pod选择器、Ingress/Egress规则、默认拒绝策略
2.1 NetworkPolicy 资源定义
NetworkPolicy 是 Kubernetes 原生的网络安全资源对象,用于控制 Pod 组之间的网络通信。它工作在 OSI 第 3/4 层(IP 地址和端口),通过标签选择器匹配目标 Pod,并定义允许的入站(Ingress)和出站(Egress)流量规则。
一个完整的 NetworkPolicy 资源定义包含以下核心字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| apiVersion | string | 固定为 networking.k8s.io/v1 |
| kind | string | 固定为 NetworkPolicy |
| metadata | ObjectMeta | 名称、命名空间、标签等元数据 |
| spec.podSelector | LabelSelector | 选择策略生效的目标 Pod 组 |
| spec.policyTypes | []PolicyType | 声明策略类型:Ingress、Egress 或两者 |
| spec.ingress | []NetworkPolicyIngressRule | 入站规则列表(可选) |
| spec.egress | []NetworkPolicyEgressRule | 出站规则列表(可选) |
关键原则:NetworkPolicy 是“白名单”机制——只定义允许的流量,未明确允许的流量默认被拒绝。策略生效的前提是集群已安装支持 NetworkPolicy 的 CNI 插件(如 Calico、Cilium、Weave Net)。
以下是一个基础的 NetworkPolicy YAML 示例:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend
namespace: production
spec:
podSelector:
matchLabels:
app: web
tier: frontend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: api-gateway
ports:
- protocol: TCP
port: 8080
2.2 Pod 选择器(podSelector)
Pod 选择器是 NetworkPolicy 的核心定位机制,通过标签(Label)匹配确定策略作用的目标 Pod 组。选择器支持两种匹配模式:
- matchLabels:精确匹配,要求 Pod 包含所有指定的标签键值对。
- matchExpressions:表达式匹配,支持
In、NotIn、Exists、DoesNotExist四种操作符。
选择器行为要点:
- 如果
podSelector为空({}),策略将匹配命名空间内的所有 Pod。 - 策略只作用于
metadata.namespace指定的命名空间,不会跨命名空间生效。 - 一个命名空间可以应用多个 NetworkPolicy,规则之间是“或”关系——只要任一策略允许,流量即被放行。
多租户隔离提示:在多租户场景中,建议为每个租户的 Pod 打上明确的租户标签(如
tenant: alpha),然后通过 podSelector 精确匹配租户标签,避免策略误覆盖其他租户的 Pod。
2.3 Ingress / Egress 规则
Ingress 规则控制入站流量(谁可以访问目标 Pod),Egress 规则控制出站流量(目标 Pod 可以访问谁)。每条规则由 来源/目的地选择器 和 端口列表 组成。
2.3.1 Ingress 规则结构
ingress:
- from: # 来源选择器列表(多个来源之间是“或”关系)
- podSelector: # 来源 Pod 标签选择
matchLabels:
app: api
- namespaceSelector: # 来源命名空间标签选择
matchLabels:
env: staging
- ipBlock: # 来源 IP 段(CIDR)
cidr: 10.0.0.0/16
except: # 排除的 IP 段(可选)
- 10.0.1.0/24
ports: # 目标端口列表(多个端口之间是“或”关系)
- protocol: TCP
port: 443
- protocol: UDP
port: 53
2.3.2 Egress 规则结构
egress:
- to: # 目的地选择器列表(多个目的地之间是“或”关系)
- podSelector:
matchLabels:
app: database
- namespaceSelector:
matchLabels:
name: monitoring
- ipBlock:
cidr: 0.0.0.0/0 # 允许访问所有外部 IP
except:
- 10.0.0.0/8
ports:
- protocol: TCP
port: 5432
选择器组合规则:
- podSelector + namespaceSelector:当两者同时出现在同一个
from/to条目中时,表示“且”关系——来源 Pod 必须同时匹配两个选择器。 - 多个 from/to 条目:条目之间是“或”关系——匹配任一条目即允许。
- 空 ports:如果未指定端口,规则匹配所有端口。
常见误区:Egress 规则中的
ipBlock 如果设置为 0.0.0.0/0,会允许访问所有外部 IP,包括集群外部的公网地址。在多租户隔离场景中,应严格限制出站 IP 范围,避免数据外泄。
2.4 默认拒绝策略
Kubernetes 默认允许所有 Pod 之间的通信。要实现“默认拒绝”,需要显式创建 NetworkPolicy 来锁定命名空间的流量边界。默认拒绝策略分为三种类型:
| 策略类型 | YAML 关键配置 | 效果 |
|---|---|---|
| 默认拒绝所有入站 | podSelector: {}policyTypes: [Ingress]不定义 ingress 规则 |
拒绝所有进入命名空间内 Pod 的流量 |
| 默认拒绝所有出站 | podSelector: {}policyTypes: [Egress]不定义 egress 规则 |
拒绝所有从命名空间内 Pod 发出的流量 |
| 默认拒绝所有双向 | podSelector: {}policyTypes: [Ingress, Egress]不定义 ingress 和 egress 规则 |
完全隔离命名空间,内外流量均被拒绝 |
默认拒绝所有入站流量的示例:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
# 没有 ingress 规则,所有入站流量被拒绝
默认拒绝所有出站流量的示例:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
# 没有 egress 规则,所有出站流量被拒绝
多租户隔离最佳实践:在创建租户命名空间时,首先应用“默认拒绝所有双向”策略,然后根据租户的实际通信需求逐步添加白名单规则。这种“先锁后开”的方式可以避免因遗漏策略导致的安全漏洞。
2.5 NetworkPolicy 流量控制流程
下图展示了 NetworkPolicy 在 Pod 通信中的决策流程:
2.6 多租户场景下的策略组合示例
以下是一个典型的多租户隔离策略组合,展示如何通过多个 NetworkPolicy 实现“默认拒绝 + 按需开放”:
# 策略1:默认拒绝所有双向流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: tenant-deny-all
namespace: tenant-alpha
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# 策略2:允许租户内部 Pod 互相通信
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: tenant-allow-internal
namespace: tenant-alpha
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: tenant-alpha
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: tenant-alpha
---
# 策略3:允许从 API 网关访问 Web Pod
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-gateway-to-web
namespace: tenant-alpha
spec:
podSelector:
matchLabels:
app: web
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: shared-infra
podSelector:
matchLabels:
app: api-gateway
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443
策略生效顺序:Kubernetes 对 NetworkPolicy 的评估顺序是“先匹配先允许”——只要有一条策略的规则匹配流量,流量即被放行,不再继续检查后续策略。因此,默认拒绝策略必须放在最前面,白名单策略放在后面。