上一篇【第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


Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐