K8s NetworkPolicy 落地:从全通模式到最小网络权限的迁移

一、集群里每个 Pod 都能访问任何其他 Pod,你的数据库也是一样

默认情况下,K8s 集群内的网络是全通模式——任何 Pod 可以访问任何其他 Pod 的任何端口。安全团队关心的是:如果攻击者拿到了一个前端 Pod 的 shell,他能直接连上你的数据库 Pod。

NetworkPolicy 的价值在于将默认的"全通"改为"默认拒绝 + 白名单放行"。但迁移过程充满挑战:你不可能在一天之内梳理完所有服务间的调用关系。

合理策略是渐进式收紧:先观察 → 再标记 → 最后阻断。

flowchart TD
    A[阶段1: 流量观察] --> B[阶段2: 策略设计]
    B --> C[阶段3: 审计模式]
    C --> D[阶段4: 逐步收紧]
    
    A --> A1[部署网络流量监控<br/>Hubble / Cilium Monitor]
    A1 --> A2[收集 1-2 周流量数据]
    A2 --> A3[生成服务间调用图]
    
    B --> B1[按 namespace 划分信任域]
    B1 --> B2[定义 app 级别策略]
    B2 --> B3[review 异常调用]
    
    C --> C1[NetworkPolicy + 日志记录]
    C1 --> C2[不阻断, 只审计]
    C2 --> C3[验证无误]
    
    D --> D1[先收紧核心 namespace<br/>如 production/database]
    D1 --> D2[监控异常]
    D2 --> D3[逐步扩展到全集群]

二、NetworkPolicy 的核心模型

NetworkPolicy 基于三层选择器:podSelector(谁应用)→ 流量方向(ingress/egress)→ 匹配规则(哪些来源/目标/端口)

关键概念:

  • 空 podSelector:匹配 namespace 内所有 Pod
  • namespaceSelector:跨 namespace 的选择
  • ipBlock:CIDR 范围的 IP 规则(用于集群外流量)
  • 不设置 egress 规则 = 允许所有出站流量

三、生产级 NetworkPolicy 配置

# 第一步:默认拒绝所有入站流量
# 这是安全基线——先封闭再打开,而不是先开放再封堵
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: production
spec:
  podSelector: {}  # 空选择器 = 本 namespace 所有 Pod
  policyTypes:
    - Ingress
  # 没有 ingress 规则 = 拒绝所有入站

---
# 第二步:允许同 namespace 内服务间通信
# 大多数微服务需要同 namespace 内互相调用
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-same-namespace
  namespace: production
spec:
  podSelector: {}
  ingress:
    - from:
        - podSelector: {}  # 同 namespace 所有 Pod
  policyTypes:
    - Ingress

---
# 第三步:允许 monitoring namespace 采集指标
# 可观测性是生产必需的——Prometheus 必须能 scrape
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-monitoring
  namespace: production
spec:
  podSelector: {}
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              name: monitoring
      ports:
        - port: 9090    # metrics port
          protocol: TCP
  policyTypes:
    - Ingress

---
# 第四步:仅允许特定服务访问数据库
# 最小权限原则的落地——只有 order-service 能连接 PostgreSQL
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-access-control
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: postgresql
  ingress:
    # 规则1: order-service 读写
    - from:
        - podSelector:
            matchLabels:
              app: order-service
      ports:
        - port: 5432
          protocol: TCP
    # 规则2: 备份 Job(在 backup namespace)
    - from:
        - namespaceSelector:
            matchLabels:
              name: backup
          podSelector:
            matchLabels:
              job-type: db-backup
      ports:
        - port: 5432
          protocol: TCP
  policyTypes:
    - Ingress

---
# 第五步:出站流量控制
# 限制 Pod 只能访问必要的外部服务
# 防止被攻破的 Pod 成为跳板机
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-control
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: order-service
  egress:
    # 允许 DNS 查询——这是几乎所有服务的基础依赖
    - to:
        - namespaceSelector:
            matchLabels:
              name: kube-system
      ports:
        - port: 53
          protocol: UDP
    # 允许访问 PostgreSQL
    - to:
        - podSelector:
            matchLabels:
              app: postgresql
      ports:
        - port: 5432
          protocol: TCP
    # 允许访问外部支付 API(通过 CIDR)
    - to:
        - ipBlock:
            cidr: 203.0.113.0/24  # 支付服务商的 IP 段
            except:
              - 203.0.113.5/32    # 排除已知的测试 IP
      ports:
        - port: 443
          protocol: TCP
  policyTypes:
    - Egress

四、渐进式迁移策略

第一步:流量可视化(1-2 周)

先用 Cilium Hubble 或 Calico 的流量日志收集所有的网络流。不要直接写策略——你写出来的策略大概率漏掉几个关键的调用。

# 用 Cilium 监控流量
cilium monitor --type drop -v
# 或导出 Hubble Flow
hubble observe --namespace production -o json > flows.json

第二步:审计模式(1 周)

创建 NetworkPolicy 但不做 deny-all。先加允许规则,观察是不是有流量被错误拦截。

第三步:核心 namespace 收紧(逐步)

从数据库、消息队列等基础设施 namespace 开始收紧。这些 namespace 的调用关系相对明确。稳定后再扩展到业务 namespace。

第四步:全集群基线

最终状态:每个 namespace 都有 default-deny-ingress + 精确的允许规则。

迁移检查清单

  • 是否所有监控/日志采集器的流量都被允许?
  • ingress controller 到后端服务的流量是否畅通?
  • DNS 解析(UDP 53)是否被允许?
  • K8s 的 liveness/readiness probe 是否会触发网络策略?
  • StatefulSet 的 Pod 间通信是否需要特殊规则?

五、总结

NetworkPolicy 落地的核心难点不是写 YAML,是在不破坏现有服务的前提下逐步收紧。从观察流量开始、在审计模式下验证、按 namespace 优先级逐步收紧——这个策略保证每一步都可逆、每个变更都有监控覆盖。全通模式是火灾隐患,最小权限是消防规范。迁移过程就是你从前者走向后者的道路。

Logo

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

更多推荐