跳到内容

第 7 卷 / 第 11 章 / 第 1 课

11.1 Kubernetes 流量边界:Gateway API 与 NetworkPolicy ​

生产集群的流量边界要回答两类问题:外部请求怎样进入服务,以及工作负载之间允许怎样通信。前者属于 L4/L7 入口治理,后者通常由 NetworkPolicy 在 L3/L4 建立最小通信面。

从 Ingress 迁移到 Gateway API ​

Ingress API 仍是稳定 API,但规范已冻结,Kubernetes 官方建议新设计优先采用 Gateway API。更关键的是,社区已在 2026 年 3 月 24 日退役 ingress-nginx,此后不再提供发布、错误修复或安全更新。现有 Ingress 对象不会因此自动失效,但继续使用已退役 controller 与继续使用 Ingress API 是两回事。

Gateway API 把职责拆给不同角色:

对象常见所有者责任
GatewayClass基础设施提供者选择 controller 实现
Gateway平台团队listener、地址、证书与接入边界
HTTPRoute应用团队hostname、path、filter 与 backend

这样应用团队可以管理路由,又不必获得修改共享负载均衡器的全部权限。

下面假设 Gateway API CRD 和对应实现已安装,managed-l7 GatewayClass、edge namespace 与其中的 TLS Secret wildcard-example-com 已存在。atlas-prod 中还需有 atlas-api Service,暴露 Service 端口 8080 并指向就绪后端。跨 namespace 挂接要求路由所在 namespace 符合 listener 的选择器:

yaml
apiVersion: v1
kind: Namespace
metadata:
  name: atlas-prod
  labels:
    gateway-access: public
yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: public-web
  namespace: edge
spec:
  gatewayClassName: managed-l7
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      hostname: "*.example.com"
      tls:
        mode: Terminate
        certificateRefs:
          - kind: Secret
            name: wildcard-example-com
      allowedRoutes:
        namespaces:
          from: Selector
          selector:
            matchLabels:
              gateway-access: public
yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: atlas-api
  namespace: atlas-prod
spec:
  parentRefs:
    - name: public-web
      namespace: edge
  hostnames: ["api.example.com"]
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /v1
      backendRefs:
        - name: atlas-api
          port: 8080

这里由 allowedRoutes 允许跨 namespace 的 Route 挂接;若 Route 又引用其他 namespace 的 backend,目标 namespace 还需相应的 ReferenceGrant。示例 backend 与 Route 同属 atlas-prod,不需要这项授权。

创建对象成功不代表流量已可用。核对 Gateway 的 Accepted、Programmed,以及对应 Route parent 的 Accepted、ResolvedRefs 条件,并确认 observedGeneration 对应当前配置。然后实际验证 DNS、TLS、Service endpoints 和请求路径;条件为真也不能替代请求测试。所需 filter 和扩展还要匹配实现支持范围。

入口策略从威胁模型推导 ​

生产入口至少要明确:

  • TLS 在哪里终止,证书由谁签发和轮换;
  • 客户端真实 IP 与转发头由谁信任和重写;
  • 认证、限流、请求体上限和超时在哪一层执行;
  • canary 权重变化由谁审批,失败如何归零;
  • controller、云负载均衡器和 Route 状态如何监控。

不要把某个 controller 的私有 annotation 当成可移植的 Kubernetes 能力。使用扩展前要记录实现依赖与迁移路径。

NetworkPolicy 默认不是防火墙 ​

隔离按方向分别生效:只有策略选中 Pod 且包含相应 policyTypes,该方向才进入隔离状态。多条策略的允许规则取并集,没有按顺序匹配的显式 deny;因此一条宽泛的 allow 可以重新打开默认拒绝收窄的范围。只有网络插件真正实现 NetworkPolicy,策略才会被执行;API 接受 YAML 并不证明数据面已经拦截。

常见基线先拒绝,再逐条放行:

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
  namespace: atlas-prod
spec:
  podSelector: {}
  policyTypes: [Ingress, Egress]

随后允许 Gateway 数据面到 API。这里假设实际代理 Pod 位于 edge,标签为 app.kubernetes.io/name: gateway-proxy,API Pod 的目标端口也是 8080。应按实现替换;管理配置的 controller Pod 不一定承载用户流量:

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-gateway-to-api
  namespace: atlas-prod
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: atlas-api
  policyTypes: [Ingress]
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: edge
          podSelector:
            matchLabels:
              app.kubernetes.io/name: gateway-proxy
      ports:
        - protocol: TCP
          port: 8080

同一个 from 元素中的 namespaceSelector 与 podSelector 是 AND:指定 namespace 中匹配的 Pod。写成两个列表项则是 OR,权限会扩大。源 Pod 的 egress 与目标 Pod 的 ingress 还必须同时允许这条连接;已允许连接的响应流量会隐式放行,不必为每个响应另开一条相反方向的规则。

默认拒绝 Egress 后先恢复基础依赖 ​

全拒绝 egress 通常会同时切断 DNS、身份服务、遥测出口和云元数据访问。放行 DNS 时要按实际 CNI 和 DNS 部署验证 namespace、Pod label、协议与端口,不能照抄网上的 kube-dns 标签。使用 NodeLocal DNSCache 或 hostNetwork 代理时,看到的源/目标可能是节点地址,Pod 选择器未必覆盖该路径;应核实实现中的节点流量例外。

对外部服务若只用 ipBlock,还要考虑 NAT、负载均衡器和供应商 IP 变化。NetworkPolicy 不是域名防火墙,也不理解 HTTP path 或服务身份;需要 L7 策略时,应使用具备相应能力且经过验证的数据面。

策略测试必须从连接两端执行 ​

发布前至少验证:

text
允许源 → 目标端口:成功
允许源 → 非目标端口:失败
非允许源 → 目标端口:失败
应用 → DNS/身份/遥测:成功
应用 → 未声明外网:失败

现有长连接在策略变化后的行为可能依赖实现,不能只测一次新建连接。集群升级或更换 CNI 后也要重跑策略测试。

边界之外仍需工作负载安全 ​

网络隔离不能替代服务认证和容器安全。生产工作负载还应按风险使用:非 root、只读根文件系统、删除不必要 capability、seccomp、受限的 ServiceAccount、Pod Security Admission,以及短期工作负载身份。网络边界失守时,身份与应用授权仍是下一道防线。

下一课处理流量到达后最难迁移的部分:有状态工作负载的身份、存储和恢复。

参考资料 ​

Built with VitePress | Software Systems Atlas