在默认的 Kubernetes 集群里,只要 Pod 拿到 IP,就能跨命名空间自由互访——这种”扁平网络”在开发环境方便,到了生产却是一颗定时炸弹。一旦某个边缘服务被攻破,攻击者可以横向移动直达数据库。Calico 作为最主流的 CNI 插件之一,用 Kubernetes 原生的 NetworkPolicy 网络策略把 Pod 间的流量管起来,配合零信任思路实现真正的网络隔离。本文从架构讲到生产落地,给你一套能直接抄的实战方案。
一、为什么需要 Kubernetes 网络策略
Kubernetes 的网络模型要求所有 Pod 互通,但这只是”能通”,并不等于”应该通”。CNI 插件只负责打通底层网络,而”谁能访问谁”的安全策略,需要 NetworkPolicy 来定义。需要强调的是:NetworkPolicy 只是一种声明,真正生效依赖 CNI 的实现。Flannel 这类插件默认不执行策略,而 Calico、Cilium 等才会真正拦截流量。
二、Calico 架构与数据面
Calico 的核心组件包括:Felix(运行在每个节点上,负责写 iptables/eBPF 规则)、BIRD(BGP 路由广播,让集群路由可达外部网络)、Typha(大规模集群下缓存数据面状态,降低对 etcd 的压力)。
数据面选型:iptables 还是 eBPF?
Calico 数据面有两种模式:传统的 iptables 和更新的 eBPF。eBPF 模式性能更好、可观测性更强,是 Calico 3.13+ 的推荐方向。说到这里不得不提它的”老对手” Cilium,后者把 eBPF 玩得更彻底;选型时二者各有侧重,Calico 胜在成熟稳定与企业级支持。
三、快速安装 Calico
官方提供一键清单,适合大多数单集群场景:
# 安装 Calico(含 CRD 与 Typha)
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/tigera-operator.yaml
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/custom-resources.yaml
# 确认节点就绪(Felix 以 DaemonSet 运行)
kubectl get pods -n calico-system
kubectl get nodes # STATUS 应变为 Ready
安装完成后,集群的网络连通性不变,但此时所有 Pod 依旧互通——策略是”默认允许”,我们要把它反转。
四、第一个策略:默认拒绝(Default Deny)
零信任的第一步是”先全部关上,再按需放开”。对某个命名空间下发一个不挑 Pod 的拒绝入站策略:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: prod
spec:
podSelector: {} # 选中该命名空间下所有 Pod
policyTypes:
- Ingress # 只管入站,出站默认仍放行
下发后,prod 命名空间内任何 Pod 都不再接受来自命名空间外的连接(命名空间内互访仍允许)。这是最安全的起点。
五、精细化放行:按标签、端口、命名空间
关上大门后,把真正需要的流量开个小口。下面这条策略允许 frontend 命名空间里带 app: web 标签的 Pod,通过 TCP 80 访问 prod 命名空间里带 app: api 标签的 Pod:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-web-to-api
namespace: prod
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: frontend
podSelector:
matchLabels:
app: web
ports:
- protocol: TCP
port: 80
NetworkPolicy 的几类选择器很容易混淆,记住这张对照表:
| 字段 | 作用范围 | 典型用法 |
| podSelector | 本策略所在命名空间内的 Pod | 圈定”被保护对象” |
| namespaceSelector | 对端 Pod 所在的命名空间 | 只允许特定命名空间访问 |
| podSelector(ingress.from) | 对端具体 Pod | 精确到某类应用 |
| policyTypes | Ingress / Egress | 分别控制入站与出站 |
六、分层隔离策略设计(实战建议)
在真实集群里,我会按三层组织策略:
- 命名空间边界层:每个业务命名空间先 default-deny,杜绝跨域横移。
- 应用服务层:按”前端→网关→后端→数据库”的调用链逐段放行(网关侧可参考 K8s Ingress 实战 暴露入口)。
- 出口层:对需要访问外部数据库或第三方 API 的 Pod 单独开 Egress,避免 Pod 成为外联跳板。
另外,网络策略只管”流量”,管不了”配置是否合规”。建议把策略模板随应用清单一起进 Git,交给 Kubernetes 准入控制 在部署时校验,做到”策略即代码,合规自动化”。
七、调试与排错
策略不生效或误拦,是最常见的两个坑。先用 calicoctl 看数据面是否真的写出了规则:
# 查看某节点的实际生效策略
calicoctl get workloadendpoint -n prod -o wide
# 检查 Felix 是否健康(AllocateIPs / BIRD 状态)
kubectl -n calico-system logs ds/calico-node | grep -i felix
# 排错三连:
# 1) 策略是否选中了目标 Pod(label 是否对齐)
# 2) 命名空间标签是否正确(namespaceSelector 用的是 ns 的 label)
# 3) 出方向是否也被误关(policyTypes 含 Egress 但没配 egress 规则 = 全拦)
最隐蔽的坑是 policyTypes 里写了 Egress 却没有对应的 egress 规则——Kubernetes 会按”默认拒绝”处理出站,Pod 突然连不上外网。排错时优先确认这一点。
八、生产落地清单
| 检查项 | 要点 |
| CNI 是否支持策略 | 确认 Calico 已就绪,Flannel 需叠加 kube-router |
| 是否先 default-deny | 每个业务命名空间先关后开 |
| label 命名规范 | 统一 app / tier 标签,避免策略选不中 |
| 出口策略 | 明确允许外联,避免误拦 DNS / 镜像仓库 |
| 策略即代码 | 随 Git 管理,配合 CI(GitHub Actions)做变更评审 |
| 监控 | 用 Prometheus 采集 Felix/BIRD 指标,规则异常早告警 |
结语
Calico 让 Kubernetes 的零信任网络隔离从”理念”变成可执行的 YAML。核心就三步:装好 CNI、先默认拒绝、再按需精细化放行。配合准入控制与 GitOps,网络策略就能像代码一样被评审、被回滚。把这套机制落到生产,横向移动的风险会大幅下降——毕竟,能不开的端口,就别开。容器网络的底层原理可回顾 Docker 容器网络 一文。




