4. Calico网络策略实战:创建租户A与租户B的隔离策略

在多租户Kubernetes集群中,网络隔离是保障租户安全的第一道防线。Calico作为CNI插件,通过其强大的网络策略引擎,能够实现基于Kubernetes原生NetworkPolicy的细粒度隔离,同时支持更高级的全局网络策略(GlobalNetworkPolicy)。本节将实战演示如何为租户A和租户B创建隔离策略,确保租户之间的流量完全隔离,而同一租户内的Pod可以正常通信。

4.1 隔离模型设计

在开始创建策略之前,我们需要明确隔离的边界。本实战采用“默认拒绝,按需放行”的原则,为每个租户的命名空间设置独立的网络策略。

租户 命名空间 隔离要求 策略类型
租户A tenant-a 禁止所有入站流量(除同命名空间外);允许出站到集群DNS 默认拒绝入站 + 允许同命名空间
租户B tenant-b 禁止所有入站流量(除同命名空间外);允许出站到集群DNS 默认拒绝入站 + 允许同命名空间
跨租户 — 租户A与租户B之间完全隔离,禁止任何流量互通 由命名空间级别的默认拒绝策略实现
设计要点: 隔离策略的核心在于“默认拒绝”策略的部署。一旦为命名空间应用了拒绝所有入站流量的策略,任何未显式允许的入站连接都会被Calico的iptables规则丢弃。这比依赖应用层认证更底层、更安全。

4.2 创建租户A的隔离策略

首先,为租户A的命名空间 tenant-a 创建网络策略。该策略包含两部分:拒绝所有入站流量(默认行为)和允许同命名空间内的所有流量。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: tenant-a
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress: []
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-same-namespace
  namespace: tenant-a
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: tenant-a

应用策略后,验证租户A内的Pod是否可以互相通信,以及租户B的Pod是否无法访问租户A。

# 在租户A的Pod中测试同命名空间通信
kubectl exec -n tenant-a deploy/app-a-1 -- curl -s --connect-timeout 3 http://app-a-2.tenant-a.svc.cluster.local:8080

# 在租户B的Pod中测试跨租户通信(预期失败)
kubectl exec -n tenant-b deploy/app-b-1 -- curl -s --connect-timeout 3 http://app-a-1.tenant-a.svc.cluster.local:8080
验证结果: 第一个命令应返回HTTP响应(如200 OK),第二个命令应超时或返回连接拒绝。这表明入站隔离策略已生效。

4.3 创建租户B的隔离策略

租户B的策略与租户A完全对称,确保两个租户的隔离策略一致,避免出现策略漏洞。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: tenant-b
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress: []
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-same-namespace
  namespace: tenant-b
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: tenant-b

同样,验证租户B内部的连通性以及跨租户的隔离性。

4.4 隔离策略的流量拓扑

下图展示了策略生效后的网络流量拓扑。租户A和租户B各自形成一个独立的通信域,所有跨域流量被Calico的eBPF或iptables规则在节点层面阻断。

Calico多租户隔离策略流量拓扑 Calico多租户隔离策略流量拓扑 租户A (tenant-a) Pod: app-a-1 Pod: app-a-2 允许 租户B (tenant-b) Pod: app-b-1 Pod: app-b-2 允许 阻断 Calico iptables/eBPF规则:跨命名空间流量被丢弃 策略生效规则 1. 默认拒绝所有入站流量(default-deny-ingress) 2. 仅允许同命名空间内的Pod互相访问(allow-same-namespace)

4.5 策略生效的底层机制

Calico网络策略的生效依赖于其数据平面组件(如Felix)将Kubernetes资源转换为节点上的iptables或eBPF规则。理解这一机制有助于排查策略不生效的问题。

  • Felix代理: 运行在每个Kubernetes节点上,监听API Server中的NetworkPolicy变化。
  • 规则编排: Felix根据策略中的 podSelector、namespaceSelector 和 ipBlock 生成对应的iptables链。
  • 数据包处理: 当Pod发送或接收数据包时,内核根据iptables规则进行匹配。匹配到“拒绝”规则则丢弃,匹配到“允许”规则则放行。
  • 性能优化: 在支持eBPF的内核上,Calico可以使用eBPF模式,绕过iptables,实现更高的吞吐量和更低的延迟。
常见陷阱: 如果策略中使用了 ipBlock 来允许特定外部IP,请确保该IP不在Pod的子网范围内,否则可能导致策略冲突。另外,policyTypes 字段必须显式声明 Ingress 或 Egress,否则策略可能不会按预期生效。

4.6 策略验证与回滚准备

在生产窗口内进行回滚验证前,必须确认当前策略的正确性。建议执行以下验证步骤:

  1. 连通性测试: 使用 kubectl exec 或部署专用的测试Pod,验证同命名空间和跨命名空间的连通性是否符合预期。
  2. 策略审计: 使用 calicoctl get networkpolicy -n tenant-a -o yaml 检查策略的YAML定义是否与预期一致。
  3. 日志检查: 查看Calico Felix的日志(kubectl logs -n calico-system daemonset/calico-node),确认没有策略同步错误。
  4. 备份策略: 在回滚前,使用 kubectl get networkpolicy -n tenant-a -o yaml > tenant-a-policy-backup.yaml 备份当前策略,以便快速恢复。
回滚准备要点: 由于网络策略是声明式资源,回滚操作本质上是重新应用旧的策略YAML。因此,确保备份文件完整且与当前集群版本兼容至关重要。建议将备份文件存储在版本控制系统中,并附带时间戳和变更说明。