Kubernetes 提供了 NetworkPolicy 用于定义 Pod 之间的网络访问控制。但很多人在使用过程中,要么设了等于没设,要么设置后服务直接"失联"。本文基于实践,深入讲解 NetworkPolicy 的语法、应用方式及常见误区,帮助你将其用得对、用得稳。
一、什么是 NetworkPolicy?为什么需要它?
Kubernetes 默认网络模型遵循"所有 Pod 默认可互相通信"。这对开发调试很友好,但在生产环境下却存在重大隐患:
- 所有服务互相暴露,无访问边界;
- 一旦某个 Pod 被攻破,可横向攻击整个集群;
- 多租户环境下,租户间数据易被非授权访问。
因此,引入网络策略非常有必要。Kubernetes 的 NetworkPolicy 提供一种声明式方式,定义:
- 哪些 Pod 可以访问哪些目标 Pod;
- 哪些端口、协议可以开放;
- 是否允许从外部入站或出站通信。
⚠️ 需要特别强调的是 :NetworkPolicy 并不负责网络本身,它只是一个策略描述,需要网络插件(如 Calico、Cilium)实现支持。
二、NetworkPolicy 的核心语法
一个最小的 NetworkPolicy 结构如下:
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-frontend
namespace: default
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
这个策略的含义是:
只允许带有
app=frontend
标签的 Pod 访问app=backend
的 Pod。其他所有访问都将被拒绝。
NetworkPolicy 支持以下几种类型:
规则方向 | 字段 | 说明 |
---|---|---|
入站策略 | ingress |
控制谁可以访问目标 Pod |
出站策略 | egress |
控制目标 Pod 可以访问谁 |
作用对象 | podSelector |
指定策略应用于哪些 Pod |
匹配范围 | namespaceSelector 、ipBlock 、port |
精细化过滤条件 |
注意 :一旦某个 Pod 被选中并应用策略,则默认全部拒绝,除非显式允许。这也是误区出现的关键之一。
三、实战示例:三种常见场景
场景 1:允许某个命名空间访问指定服务
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-namespace
namespace: default
spec:
podSelector:
matchLabels:
role: db
ingress:
- from:
- namespaceSelector:
matchLabels:
project: analytics
该策略只允许带有 project=analytics
标签的命名空间下的 Pod 访问当前 namespace 中标记为 role=db
的 Pod。
场景 2:禁止所有入站流量(默认拒绝)
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
namespace: default
spec:
podSelector: {} # 匹配所有 Pod
ingress: [] # 明确为空,即不允许任何流量
这是一个非常有效的"白名单策略起点",建议在生产环境作为默认策略启用,然后再逐个添加需要放行的规则。
场景 3:允许访问特定端口
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-metrics
namespace: default
spec:
podSelector:
matchLabels:
app: metrics-server
ingress:
- ports:
- protocol: TCP
port: 443
此策略允许其他 Pod 访问 metrics-server
的 443 端口,但不允许访问其他端口。
四、常见误区与踩坑总结
误区 1:策略设置后,访问全部失效
原因:一旦为某个 Pod 设置了 NetworkPolicy,则默认全部拒绝所有流量,除非显式允许。
建议:配合默认允许策略一起使用,例如为 DNS 组件、监控组件等先配置放行规则。
误区 2:策略没生效,以为配置错误
排查重点:
-
你集群的 CNI 插件是否支持 NetworkPolicy?
- Flannel 原生不支持;
- Calico、Cilium 支持完整策略;
-
是否为目标 Pod 打上了正确的标签?
-
策略是否生效在正确的 namespace 上?
误区 3:只写了 ingress 忽略了 egress
许多用户只定义了 ingress,但实际通信失败,问题出在对端被拦了 egress。
建议:明确策略控制方向,必要时添加:
yaml
policyTypes:
- Ingress
- Egress
误区 4:忘记放行核心服务(如 kube-dns)
DNS 无法解析 是 NetworkPolicy 配置最常见的问题之一,建议为所有命名空间添加 DNS 放行策略:
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: default
spec:
podSelector: {}
egress:
- to:
- namespaceSelector:
matchLabels:
k8s-app: kube-system
ports:
- protocol: UDP
port: 53
policyTypes:
- Egress
五、从"能用"到"用好":我在实践中的思考
在实际项目中,我曾经遇到过这样一幕:
刚上线的安全策略导致线上服务大量超时,排查发现数据库无法连接。原来我们设定了 ingress 策略,但忘了放行 egress 到数据库。
这类事故暴露一个现实:NetworkPolicy 虽然语法简单,但逻辑上类似于"防火墙规则",需要慎之又慎。
我的经验是:
- 从默认拒绝 + 白名单放行开始;
- 将 NetworkPolicy 与服务部署绑定,避免策略缺失;
- 结合工具做策略审计与模拟测试(如
kubectl-debug
、network-policy-editor
); - 把 NetworkPolicy 纳入 DevSecOps 流程,版本化管理。
六、结语:让网络策略成为"默认安全防线"
NetworkPolicy 是 Kubernetes 提供的强大网络控制工具,但前提是你使用了支持它的 CNI,并理解它的工作模型。
它不是网络的替代,而是网络策略的扩展。在微服务时代,它是服务边界控制、横向攻击防护、数据访问隔离的重要组成部分。
别等安全事故之后才想着补策略,不如从现在开始,把 NetworkPolicy 变成你服务部署清单的一部分。