4. CiliumNetworkPolicy 实战:创建允许特定微服务通信的策略、Deny 策略、基于 FQDN 的策略
本章通过三个实战场景,演示如何利用 CiliumNetworkPolicy (CNP) 实现微服务间的精细化访问控制。你将掌握从“允许特定通信”到“显式拒绝”再到“基于域名出口”的完整策略编写与验证流程。
4.1 实战场景与集群环境准备
假设我们有一个运行在 Kubernetes 上的电商应用,包含以下微服务:
| 微服务 | 标签 (Labels) | 说明 |
|---|---|---|
| frontend | app=frontend |
前端 Web 服务,接收用户请求 |
| checkout | app=checkout |
订单结算服务 |
| inventory | app=inventory |
库存查询服务 |
| payment | app=payment |
支付网关服务(仅内部调用) |
| monitoring | app=monitoring |
监控采集器(需访问外部 API) |
前提条件:确保集群已安装 Cilium 并启用 Hubble 可观测性组件。使用
kubectl get pods -n kube-system -l k8s-app=cilium 验证 Cilium 代理运行正常。
4.2 实战一:允许特定微服务通信的策略
目标:只允许 frontend 访问 checkout 的 8080 端口,拒绝其他所有流量。
策略定义:
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-frontend-to-checkout
namespace: default
spec:
endpointSelector:
matchLabels:
app: checkout
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
关键字段解析:
endpointSelector:策略作用的目标 Pod(checkout)。ingress.fromEndpoints:允许的源 Pod(frontend)。toPorts:限制目标端口为 8080/TCP。
验证方法:
- 进入 frontend Pod:
kubectl exec -it deploy/frontend -- sh - 测试允许的访问:
curl http://checkout:8080/health(应返回 200)。 - 测试拒绝的访问:
curl http://checkout:8081/health(应超时或拒绝)。 - 从 inventory Pod 测试:
curl http://checkout:8080/health(应被拒绝)。
策略生效验证:使用
hubble observe --from-pod default/frontend-xxx --to-pod default/checkout-yyy 查看 Hubble 流量日志,确认策略命中情况。
4.3 实战二:Deny 策略——显式拒绝特定通信
Cilium 支持 Deny 策略,优先级高于 Allow 策略。当同时存在 Allow 和 Deny 规则时,Deny 规则优先生效。
场景:禁止 monitoring 服务访问 payment 服务,即使其他策略允许。
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: deny-monitoring-to-payment
namespace: default
spec:
endpointSelector:
matchLabels:
app: payment
ingressDeny:
- fromEndpoints:
- matchLabels:
app: monitoring
Deny 策略与 Allow 策略的对比:
| 特性 | Allow 策略 | Deny 策略 |
|---|---|---|
| 默认行为 | 未匹配则拒绝(白名单模式) | 未匹配则允许(黑名单模式) |
| 优先级 | 低 | 高(覆盖 Allow) |
| 适用场景 | 最小权限原则 | 紧急阻断、合规隔离 |
| 语法字段 | ingress / egress |
ingressDeny / egressDeny |
注意:Deny 策略的
endpointSelector 指向的是被拒绝的目标 Pod(payment),而不是发起方。这与直觉相反,请务必确认方向。
验证 Deny 策略:
- 进入 monitoring Pod:
kubectl exec -it deploy/monitoring -- sh - 尝试访问 payment:
curl http://payment:9090/metrics(应被拒绝)。 - 从其他 Pod(如 frontend)访问 payment:应正常(前提是有 Allow 策略)。
4.4 实战三:基于 FQDN 的策略——安全的外部出口
场景:monitoring 服务需要访问外部监控 API(例如 api.example.com),但禁止访问其他外部地址。
FQDN 策略使用 toFQDNs 字段,基于 DNS 解析结果动态生成网络规则。
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: fqdn-egress-monitoring
namespace: default
spec:
endpointSelector:
matchLabels:
app: monitoring
egress:
- toFQDNs:
- matchName: "api.example.com"
toPorts:
- ports:
- port: "443"
protocol: TCP
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
matchLabels:
k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
策略说明:
- 第一条规则:允许访问
api.example.com的 443 端口。 - 第二条规则:允许访问集群 DNS(CoreDNS),这是 FQDN 策略工作的前提——Cilium 需要拦截 DNS 请求来学习域名与 IP 的映射。
FQDN 策略工作原理:Cilium 通过 eBPF 在节点上拦截 Pod 发出的 DNS 查询,将解析到的 IP 地址动态注入到网络策略的允许列表中。DNS TTL 过期后,IP 映射自动更新。
4.5 三种策略的协同关系与架构图
下图展示了三种策略在集群中的协同工作方式:
4.6 策略编写最佳实践
- 先 Deny 后 Allow:先部署 Deny 策略阻断高风险流量,再逐步开放 Allow 策略。
- FQDN 策略必须放行 DNS:缺少 DNS 规则会导致域名解析失败,FQDN 策略无法生效。
- 使用标签而非 IP:始终基于 Kubernetes 标签选择端点,避免硬编码 IP 导致策略漂移。
- 启用 Hubble 监控:通过
hubble observe --verdict DROPPED快速定位被拒绝的流量。 - 策略命名规范:建议格式
<action>-<source>-to-<target>,例如allow-frontend-to-checkout。
生产环境建议:在 CI/CD 流水线中集成
cilium connectivity test 命令,自动验证策略变更不会破坏现有通信链路。