【Kubernetes】K8s 集群 NetworkPolicy 策略
Network Policy 是 Pod 的防火墙,将开放的集群网络转变为受控的安全边界,一起来看看如何使用吧!
1、NetworkPolicy 概念
- NetworkPolicy 是 Kubernetes 中定义 Pod 之间、以及 Pod 与外部网络之间通信规则的资源,相当于云环境中的安全组或传统数据中心的防火墙策略
- 核心理念:默认情况下,Kubernetes 集群中的所有 Pod 是可以相互通信的(取决于 CNI 插件),NetworkPolicy 允许实施 "默认拒绝" 策略,只允许明确的通信规则
2、使用 NetworkPolicy 原因
| 原因 | 好处 |
|---|---|
| 实现零信任安全模型 | 不默认信任任何服务,每个服务都必须显式声明它需要与谁通信,极大减少了攻击面 |
| 微服务隔离 | 防止一个被入侵的微服务(如图像处理服务)横向移动去攻击更关键的服务(如数据库或支付服务) |
| 满足合规性要求 | 许多行业标准(如 PCI-DSS, HIPAA)要求对网络流量进行分段和控制 NetworkPolicy 提供了技术实现手段 |
| 多租户环境隔离 | 在共享的 K8s 集群中,确保不同团队或项目的服务无法相互访问,实现逻辑隔离 |
| 控制外部访问 | 精确控制哪些外部 IP 范围可访问集群内的服务,或者哪些 Pod 可访问互联网 |
3、前提条件
- 要使用 NetworkPolicy 的前提为当前 K8s 网络插件必须支持 NetworkPolicy
- 常见的支持插件有:Calico、Cilium、Weave Net、Kube-router
- 注意:Flannel 的默认配置不支持 NetworkPolicy
- 常见网络插件介绍见博客:https://blog.csdn.net/mm1234556/article/details/147410643
4、使用场景示例
4.1、场景1:默认拒绝所有流量
- 在 default 命名空间中,默认拒绝所有入口和出口流量
-
应用此策略后,default 命名空间内的所有 Pod 将无法被任何其他 Pod 访问,也无法访问任何其他 Pod 或外部地址
# 0-default-deny-all.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: default
spec:
# 选择所有 Pod
podSelector: {}
# 策略类型,指定此策略同时适用于入口和出口
policyTypes:
- Ingress
- Egress
# 由于没有指定任何 ingress 或 egress 规则,所以所有入口和出口流量都被拒绝。
4.2、场景2:允许同一命名空间内前端访问后端 API
- 在 web-app 命名空间中,允许带有标签 app: frontend 的 Pod 访问带有标签 app: backend-api 的 Pod 的 80 端口,拒绝所有其他流量
-
frontend -> Pod 可以 curl http://backend-api:80; backend-api -> Pod 不能访问 frontend Pod;其他任何 Pod 都无法访问 bakcend-api
# 1-frontend-to-backend.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: web-app
spec:
# 此策略应用于 "backend-api" Pod
podSelector:
matchLabels:
app: backend-api
policyTypes:
- Ingress
# 入口规则
ingress:
- from:
# 源 Pod 选择器:来自同一命名空间中带有 `app: frontend` 标签的 Pod
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 80
4.3、场景3:允许跨命名空间访问(如监控)
- 目标:允许在 monitoring 命名空间中的 Prometheus Pod 抓取所有命名空间中带有 monitoring: enabled 标签的 Pod 的指标端口(如 9090)
- 注意:为了让这个策略工作,monitoring 命名空间需要有标签 name: monitoring
# 给 monitoring 命名空间加标签 ame=monitoring
kubectl label namespace monitoring name=monitoring
# 2-allow-cross-ns-monitoring.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-prometheus-scraping
# 该策略可应用在任何被监控的 Pod 所在的命名空间,比如 web-app
namespace: web-app
spec:
podSelector:
matchLabels:
monitoring: enabled # 选择希望被监控的 Pod
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
# 选择 "monitoring" 命名空间
name: monitoring
podSelector:
matchLabels:
# 在 "monitoring" 命名空间中,进一步选择 Prometheus 的 Pod
app: prometheus
ports:
- protocol: TCP
port: 9090
4.4、场景4:控制 Pod 访问外部网络(出口策略)
- 目标:只允许一个支付服务 Pod 访问一个特定的外部支付网关 IP,禁止它访问其他任何外部地址
-
payment-service -> Pod 可以访问https://203.0.113.50:443
-
payment-service -> Pod 不能访问其他任何外部 IP(如 google.com)
-
它仍可访问集群内的 DNS 服务来解析 payment-gateway.com 这样的域名(该域名被解析为允许的 IP)
# 3-allow-egress-to-external-api.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-payment-to-gateway
namespace: production
spec:
# 此策略应用于支付服务 Pod
podSelector:
matchLabels:
app: payment-service
policyTypes:
- Egress
egress:
- to:
- ipBlock:
# 外部支付网关的 IP 地址或 CIDR
cidr: 203.0.113.50/32
ports:
- protocol: TCP
port: 443 # 假设网关使用 HTTPS
# 重要:通常还需要允许访问集群的 DNS 服务器,否则无法解析域名
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
4.5、场景5:多租户隔离
- 目标:完全隔离 team-a 和 team-b 两个命名空间,防止它们之间的任何网络通信
-
team-a 命名空间内的 Pod 可相互通信
;team-b 命名空间内的 Pod 可相互通信;team-a 和 team-b 之间的所有网络流量都被阻断
# 4-deny-cross-team-traffic.yaml
# 策略1:在 team-a 命名空间,拒绝来自 team-b 的流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-from-team-b
namespace: team-a
spec:
podSelector: {} # 应用于 team-a 中的所有 Pod
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
# 关键:只允许来自本命名空间(team-a)的流量
name: team-a
# 策略2:在 team-b 命名空间,拒绝来自 team-a 的流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-from-team-a
namespace: team-b
spec:
podSelector: {} # 应用于 team-b 中的所有 Pod
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: team-b
5、最佳实践
a、从 "默认拒绝" 开始:首先在每个命名空间应用一个default-deny-all 策略
b、采用白名单模式:只明确允许业务所必需的通信路径
c、标签是核心:使用清晰、一致的标签(如 app,version)来标识 Pod 和命名空间,因为 NetworkPolicy 的选择器基于标签
d、结合命名空间进行逻辑分组:使用命名空间来划分环境(如 dev, prod)或团队,并配合 NetworkPolicy 实现隔离
e、不要忘记出口策略:入口控制很重要,但出口控制可防止数据泄露和恶意软件回连
f、测试策略:在应用策略后,使用 kubectl exec 进入一个 Pod 并使用 curl 或 nc 等工具测试网络连通性,确保策略按预期工作
更多推荐



所有评论(0)