【Kubernetes从入门到精通】第56篇:NetworkPolicy安全实战——用零信任网络把微服务“关进笼子“
上一篇【第55篇】SecurityContext——容器安全配置的"三件套"
下一篇【第57篇】Secret管理的最佳实践——Vault/SealedSecrets/External Secrets
摘要
第047篇我们讲了NetworkPolicy的语法,第047篇也提了"默认拒绝"的思路。但语法≠架构。真要在生产环境搭一套安全的网络,你需要的是从安全原则出发的整体设计,而不是零散的几条规则。
这就是零信任(Zero Trust)网络——它的核心信条是"永不信任,始终验证"。在K8s里翻译成大白话:默认所有Pod之间都不通,然后一条条精确放通"必须通"的链路。
这篇文章从零信任三原则讲起,给你一套三层应用的完整微隔离方案(前端→后端→数据库),再讲namespace之间的流量控制,最后看看Cilium怎么把策略做到HTTP级别。读完你就能照着给自己的集群"上锁"。
一、零信任的三条铁律
1.1 原则
【零信任网络的三条铁律】
铁律1: 默认拒绝一切 (Default Deny)
• 没有任何策略时 = 全通(危险!)
• 安全做法: 先锁死,再发钥匙
铁律2: 最小权限 (Least Privilege)
• 只放通"业务必须的"那条链路
• frontend→backend:8080 放行
• frontend→database:5432 绝不放行(越级访问!)
铁律3: 假设已被突破 (Assume Breach)
• 即使一个Pod被攻陷,它的"活动范围"已被策略锁死
• 攻击者横向移动的成本被极大抬高
要点:零信任的精髓是心态转变——从"内部是可信的"变成"内部也不可信"。传统网络像公司大楼,进了大门就能到处走;零信任像银行金库,每个房间都要单独授权。在K8s里,NetworkPolicy就是你实现这种"金库模型"的工具。
二、三层应用微隔离实战
2.1 架构目标
【我们要实现的安全拓扑】
Internet
│ (只放Ingress Controller进frontend)
▼
[Ingress Nginx] ──allow 80/443──► [frontend]
│ (只放frontend→backend:8080)
▼
[backend]
│ (只放backend→database:5432)
▼
[database]
│
└─ allow DNS (否则全崩)
禁止的访问(策略自动挡):
• frontend → database (越级!)
• Internet → backend (绕过前端!)
• frontend → 其他namespace (乱窜!)
2.2 完整策略集
# ① 基础锁:默认拒绝所有入站+出站(必须先有这条)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: shop
spec:
podSelector: {}
policyTypes: [Ingress, Egress]
# ② 放行DNS(否则Pod连名字都解析不了,应用直接崩)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: shop
spec:
podSelector: {}
policyTypes: [Egress]
egress:
- to:
- namespaceSelector: {}
ports:
- {protocol: UDP, port: 53}
- {protocol: TCP, port: 53}
# ③ Ingress Controller → frontend
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: frontend-from-ingress
namespace: shop
spec:
podSelector:
matchLabels: {app: frontend}
policyTypes: [Ingress]
ingress:
- from:
- namespaceSelector:
matchLabels: {kubernetes.io/metadata.name: ingress-nginx}
ports:
- {protocol: TCP, port: 80}
# ④ frontend → backend:8080
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-from-frontend
namespace: shop
spec:
podSelector:
matchLabels: {app: backend}
policyTypes: [Ingress]
ingress:
- from:
- podSelector:
matchLabels: {app: frontend}
ports:
- {protocol: TCP, port: 8080}
# ⑤ backend → database:5432
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: db-from-backend
namespace: shop
spec:
podSelector:
matchLabels: {app: database}
policyTypes: [Ingress]
ingress:
- from:
- podSelector:
matchLabels: {app: backend}
ports:
- {protocol: TCP, port: 5432}
要点:这套策略的关键在顺序——先default-deny锁死,再DNS放行(否则应用崩),然后逐层放通链路。注意第⑤条database的策略只接受来自backend的流量,frontend根本不在白名单里,所以"frontend直连database"会被自动挡掉,实现了严格的层级隔离。
三、namespace之间的流量控制
3.1 多团队隔离
【跨namespace的流量控制——"部门墙"】
namespace: team-a (前端团队)
namespace: team-b (数据团队)
team-a 的Pod 默认不能访问 team-b 的Pod
→ 除非显式写策略允许
典型需求:team-a 的 backend 需要访问 team-b 的 mysql
→ 在 team-b 里写一条策略,from 指定 team-a 的namespace
# team-b (数据团队) 里允许 team-a 的backend访问mysql
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: mysql-allow-teama-backend
namespace: team-b
spec:
podSelector:
matchLabels: {app: mysql}
policyTypes: [Ingress]
ingress:
- from:
- namespaceSelector:
matchLabels: {team: team-a}
podSelector:
matchLabels: {app: backend}
ports:
- {protocol: TCP, port: 3306}
四、Cilium把策略做到L7
4.1 HTTP级别隔离
传统NetworkPolicy只能到L4(端口)。Cilium的CiliumNetworkPolicy能到L7:
# 只允许 frontend 对 backend 发 GET /api,拒绝一切其他请求
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: backend-l7
spec:
endpointSelector:
matchLabels: {app: backend}
ingress:
- fromEndpoints:
- matchLabels: {app: frontend}
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: "GET"
path: "/api/.*"
【L4 vs L7 策略——"能进门" vs "能碰保险柜"】
L4 (NetworkPolicy):
"允许 frontend → backend:8080"
→ 黑客可以 POST /admin/delete,照样进!
L7 (CiliumNetworkPolicy):
"允许 frontend → backend:8080 的 GET /api/*"
→ POST /admin/delete 被直接拦在L7
要点:L7策略是微服务安全的"终极形态"——它理解应用协议,能在方法/路径/Header级别做访问控制。但只有Cilium等支持eBPF的插件能做到(见第049篇)。对绝大多数场景,L4的NetworkPolicy已经能提供扎实的微隔离;对金融、多租户等高安全场景,上Cilium做L7。
五、验证你的零信任网络
# 1. 故意从frontend直连database(应该失败)
kubectl exec -it frontend-xxx -n shop -- \
nc -zv database 5432
# ❌ 超时/拒绝 → 策略生效!
# 2. 从backend连database(应该成功)
kubectl exec -it backend-xxx -n shop -- \
nc -zv database 5432
# ✅ 连接成功 → 链路放通正确
# 3. 看Calico/Cilium的策略是否真的落地
kubectl exec -n kube-system calico-node-xxx -- \
calicoctl get networkpolicy -o wide
本篇小结
零信任网络三铁律:默认拒绝、最小权限、假设已被突破。在K8s里落地就是"先default-deny锁死所有流量,再放行DNS,然后逐层精确放通业务链路"。三层应用(前端→后端→数据库)的隔离实战是最常见的模板,关键是database的策略只接受backend,越级访问自动被挡。
跨namespace用namespaceSelector做"部门墙"。需要HTTP/gRPC级别隔离(金融/多租户),上Cilium的L7策略。下一篇聊Secret管理——K8s里敏感信息的"保险箱"该怎么用才安全。
上一篇【第55篇】SecurityContext——容器安全配置的"三件套"
下一篇【第57篇】Secret管理的最佳实践——Vault/SealedSecrets/External Secrets
更多推荐


所有评论(0)