土法炼钢 · 系统与基础设施

【Envoy Gateway】TLS / BackendTLSPolicy / SDS:两层证书与 v1.9 破坏面

文章导航

分类入口
kubernetesnetwork
标签入口
#envoy-gateway#tls#sds#backendtlspolicy#unix-socket#system-ca#envoypatchpolicy#v1.9.0

目录

南北向 TLS 经常被说成「网关开了 HTTPS」。这句话至少叠了两层:客户端到 Envoy 的 listener 终止,以及 Envoy 到后端的再加密。两层可以用完全不同的证书、CA 与发现方式。v1.9.0 又在 SDS 上改了 URL 形态和系统 CA 的 secret 名字——照着旧 patch 去改 xDS,会在升级后静默失配。

本文只钉这三块:Gateway listener TLS、BackendTLSPolicy、以及 v1.9 SDS 破坏面(unix://、共享 system_ca_certificates、旧 EnvoyPatchPolicy 名)。不写云厂商证书控制台步骤。证书 warming 与 ACK≠上量外链 envoy/11

本文是「Envoy Gateway / Gateway API」系列第 7 篇(共 16 篇)。→ 系列目录

篇目 核心内容
第 6 篇 · HTTPRoute / GRPCRoute 匹配进入 RDS
第 7 篇 · TLS / SDS listener 证书 vs 后端 TLS;v1.9 SDS 破坏面
第 8 篇 · L4 路由 TCP/UDP 升 v1 与静默跳过

上一篇HTTPRoute / GRPCRoute · 下一篇L4 路由

版本锚定:Envoy Gateway v1.9.0 Release Notes 的 TLS/SDS 节;Gateway API BackendTLSPolicy(Standard since v1.4.0);tag internal/xds/translator/sds.go。v1.9 默认是共享 system_ca_certificates,不是 per-resource /-ca。无伪造 SDS dump。


一、Gateway listener TLS

客户端看到的「HTTPS / TLS 入口」停在 Gateway listener。协议与 mode 决定证书出现在哪:

Listener 协议 TLS mode 证书在哪 解密后交给谁
HTTPS Terminate(HTTPS 语义) tls.certificateRefs HTTPRoute / GRPCRoute
TLS Terminate tls.certificateRefs TCPRoute(不看 SNI)或 TLSRoute(按 SNI)
TLS Passthrough listener 不终止 TLSRoute 按 SNI 把密文交给后端

EG v1.9 TLS Termination for TCP 把 Terminate 再分成两种后端选择:TCPRoute 不检查 SNI,一个 listener 只能对一个后端;TLSRoute 按客户端 SNI 扇出,多条 TLSRoute 可挂同一 listener。Passthrough 任务是另一页,本篇不写菜谱。

默认证书材料是 Kubernetes Secret,类型 kubernetes.io/tls。v1.9.0 还修了几类「证看起来对、Envoy 拒」的翻译错误,避免 mergeGateways 时一张坏证拖垮同代理上的全部 TLS:

同一地址端口上的 HTTPS listener,EG 会合并成一条 Envoy listener(System Design:按端口分组,兼容则折叠;不跨 Gateway 合并)。因此一张证没就绪,可以拖住同端口上所有 listener 的激活。SDS 任务页写明:Envoy 会等 SDS 证书到齐才激活 listener;外部 SDS 不可用时,共享该地址端口的连接可能被延迟或重置。这是数据面合并语义,不是「改 HTTPRoute 能修好」。

ClientTrafficPolicy 上的 TLS(客户端校验、cipher、握手超时等)作用在 下游(客户端 ↔︎ Envoy),与 BackendTLSPolicy 的上游 TLS 正交。v1.9 新增 allowExpiredCertificate、更多握手超时字段,属于第 9 篇 Policy,本篇只防止把「listener 要证」和「backend 要 CA」写成同一张工单。

v1.9.0 新能力:tls.certificateRefs 可以引用类型为 gateway.envoyproxy.io/sds 的 Secret,让 Envoy 在运行时从外部 SDS 服务器拉 listener 证书。默认关闭,需在 EnvoyGateway 配置里打开 extensionApis.enableSDSSecretRef。Secret 的 stringData 需要 url(带 scheme 的 SDS unix URL)与 secretName。文档示例:

apiVersion: v1
kind: Secret
metadata:
  name: sds-cert
type: gateway.envoyproxy.io/sds
stringData:
  url: unix:///var/run/secrets/workload-spiffe-uds/socket
  secretName: default

打开开关不会自动把 UDS 挂进 Envoy Pod;要用 EnvoyProxy patch 挂 volume。Kubernetes RBAC / ReferenceGrant 管的是这张「连接信息」Secret;SDS 服务器另用代理的 SDS 身份授权 secretName。文档警告:只在能创建/引用此类 Secret 的用户可信时启用。

SDS 证书对控制面是不透明的。多条合法 HTTPS listener 共享端口时,SDS 支持的 listener 默认 HTTP/1.1,以避免 HTTP/2 coalescing。同端口上、已知 DNS/SAN 与 SDS listener hostname 重叠的 inline 证书 listener 也会降到 HTTP/1.1;SDS listener 若省略 hostname(匹配全部主机),同端口所有合法 HTTPS listener 都降级。单独一条 SDS listener 仍保留 HTTP/2。受影响 listener 上报 gateway.envoyproxy.io/TLSCertificateNamesUnknown=True,reason SDSCertificateOpaque。可用 ClientTrafficPolicy 显式配置 ALPN 覆盖默认。


二、BackendTLSPolicy

BackendTLSPolicy 是 Gateway API 对象,描述 Gateway 数据面到后端 的 TLS(文档称 backend TLS termination):后端自己持证,网关要校验并设置 SNI。它不是 listener 证书的另一种写法。

EG v1.9 Concepts 与 BackendTLSPolicy 页写该资源 GA、Standard since v1.4.0。v1.9 任务示例仍使用 apiVersion: gateway.networking.k8s.io/v1alpha3。本篇不把任务页的 alpha 字符串改写成「唯一合法版本」,只记录:控制面把该策略编译进上游 TLS;安装的 CRD 必须实际 served 该版本。若集群只装了不含 BackendTLSPolicy 的托管 CRD 子集,v1.9 会跳过对该 kind 的 watch(发行说明:OpenShift Ingress-Operator 一类),而不是用 HTTP 500 提醒——与第 8 篇 L4 的「缺 CRD 则跳过」同一类控制器存活选择。

v1.9 任务页示例使用 apiVersion: gateway.networking.k8s.io/v1alpha3validation.caCertificateRefs 指向 ConfigMap 或 ClusterTrustBundle,hostname 作为 SNI。sectionName 在 Service 上对应 port name,在 EG Backend 上对应端口号。v1.9.0 修复:同一 backend 上带 section name 的策略优先于通配匹配。

校验材料二者取一,不能同时写:

字段 含义
caCertificateRefs PEM CA,引用同命名空间对象
wellKnownCACertificates: System 使用实现提供的系统 CA 集合

hostname 不允许 IP 与通配。v1.2 起的 subjectAltNames 把 SNI 与证书身份分开(例如 SPIFFE URI SAN 不是合法 SNI)。options 是实现扩展槽。

EG 还允许在 EnvoyProxy spec.backendTLS 上改最低/最高 TLS 版本等参数。v1.9.0 修复:上游 TLS 默认最高版本从被错误限制在 1.2,改为文档所写的 TLS 1.3。任务页用 minVersion: "1.3" 演示参数覆盖。这些参数替代 BackendTLSPolicy 的 CA/SNI。

v1.9 对 Backend 资源上的 spec.tls.wellKnownCACertificates: System 与 BackendTLSPolicy 使用同一套系统 CA SDS 机制(下一节)。不要把「系统 CA」理解成每张策略一份独立 secret——那是升级前的默认。


三、SDS unix://

这里有两套「SDS」,不要混:

  1. Envoy 内置 SDS:控制面把 Secret 编成 xDS type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret,经 EG 自己的 xDS 流下发。listener 的 kubernetes.io/tls 走这条。
  2. 外部 SDS 服务器:Envoy 再作为客户端,经 Unix domain socket 向另一个 SDS 进程要证。v1.9 的 gateway.envoyproxy.io/sds Secret 与部分后端/客户端证书 IR 走这条。

v1.9.0 破坏性变更:SDS 引用 secret 的 url 必须带 unix:// scheme。v1.9.0-rc.0 曾接受裸文件系统路径,正式版拒绝。文档与 notes 给的形态是 unix:///var/run/secrets/workload-spiffe-uds/socket

tag v1.9.0 internal/xds/translator/sds.go 与发行说明一致:从 URL 去掉 unix:// 前缀得到 pipe path,并为该 URL 建 STATIC cluster;cluster 名字带 path 的 hash 后缀,避免不同路径撞名。因此 EnvoyPatchPolicy 若匹配「由路径直接派生、无 hash」的旧 cluster 名,升级后不再命中。

同一发行说明还加了校验:UDS URL 必须形态合法——拒绝带 host 的成分、要求有 path——避免静默生成错误的 socket 地址。另修:类型 type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret初次 fetch 超时

翻译器在 Translate 末段调用 processSDSClusters,扫描 HTTP/TCP IR 与 BackendClusters 上的 SDS URL,去重排序后建 cluster。没有 unix:// 的 URL 在这一层不会被当成合法 UDS 去 TrimPrefix——应在更早的 API 校验被拒。本篇不编造校验错误文案。


四、共享 system_ca_certificates

v1.9.0 破坏性变更原文:所有使用 WellKnownCACertificates: SystemBackendTLSPolicy,以及 spec.tls.wellKnownCACertificates: SystemBackend,改为共享一份 SDS secret,名字是 system_ca_certificates;不再为每个资源生成名为 / -ca 的 per-resource secret。

发行说明给出的运维后果:

Performance 节补充动机:共享 secret 减少 WellKnownCACertificates: System 时的 inotify watch 数量。

v1.9 默认叙事是:系统 CA 是集群级共享信任锚,不是策略级私有文件。 把旧文档里的 per-resource -ca 当成现行默认,会在升级后对着空气 patch。


五、EnvoyPatchPolicy 旧 secret 名失效

把第三节、第四节合成一张「升级后 patch 打空」清单。这些都来自 v1.9.0 Breaking notes,不是推断:

旧匹配对象 v1.9.0 之后
裸路径 SDS url 必须 unix://
由 UDS 路径直接派生的 SDS cluster 名 名带 hash 后缀
per-resource / -ca 系统 CA secret 共享 system_ca_certificates
cluster validationContextSdsSecretConfig 指向旧 CA secret 必须改目标;且不可 patch 共享 secret
JWT jwt_authn.providers / requirementMap 的 route 派生键 改为内容派生稳定名(相关但非本篇主线)
DNS cluster 顶层 dns_refresh_rate 改到 envoy.cluster.dns typed config

JSON patch 匹配的是生成后的 xDS 名字。IR 没变、CR 没变,只升 EG,patch 就可以从「一直成功」变成 no-op。失败表象通常不是 HTTP 500,而是:mTLS/后端校验仍用系统 CA 默认、或 listener 仍用旧证——看起来像「策略写了不生效」。第 9 篇会把 EnvoyPatchPolicy 放进五类 Policy;本篇只要求:升 v1.9 前先搜 patch 里的 secret/cluster 名。

与第 5 篇衔接:patch 失败被当成用户错误,不会挡住其余 xDS 进快照。因此「控制面已推送」可以与「你那条 patch 再也匹配不到 secret」同时为真。要用 EnvoyPatchPolicy status / 生成配置对账,而不是看 Gateway Programmed

flowchart TB
  client["Client"] -->|"listener TLS"| env["Envoy"]
  env -->|"BackendTLSPolicy"| be["Backend"]
  subgraph listener["Listener layer"]
    k8s["Secret kubernetes.io/tls"]
    ext["Secret type gateway.envoyproxy.io/sds"]
  end
  subgraph sds["SDS"]
    xds["EG xDS Secret resources"]
    uds["unix:// SDS server"]
    sys["shared system_ca_certificates"]
  end
  k8s --> xds
  ext --> uds
  sys --> be
  xds --> env
  uds --> env

图:listener 证书(inline 或外部 SDS)与后端 TLS(BackendTLSPolicy / 系统 CA)不是同一层;v1.9 系统 CA 默认共享一个 SDS secret。


六、谱系、争论与开放问题

谱系

RFC 8446 TLS 1.3(握手、证书、SNI)
  → 反向代理边缘终止 vs 到上游再加密(两段 TLS)
  → Envoy SDS:证书不当静态 bootstrap,而作为可发现资源
  → SPIFFE / 工作负载身份常用 UDS SDS(工程实践)
  → Gateway API BackendTLSPolicy:把「到 Service 的校验与 SNI」写成可移植策略
  → EG v1.9:强制 unix://、共享系统 CA secret、可选 listener SDS Secret

边缘终止解决的是「客户端如何信任网关」;BackendTLSPolicy 解决的是「网关如何信任 Pod」。SDS 解决的是「证的旋转不要重配整棵 LDS」。三件事共享「TLS」这个词,排障坐标却不同。

争论:共享系统 CA vs per-resource secret

A 侧(v1.9 默认):所有 System 信任锚本就是同一套文件;共享 SDS secret 降低 watch 与重复 warming。

B 侧(opt-out PerResourceSystemCASecret:隔离变更半径——一张策略的 CA 更新不应触发全局 secret warming。发行说明承认升级时可能中断。

EG 的选择是默认共享、允许 flag 退回。需要定制 CA 的后端应走 CACertificateRefs,不要 patch 共享 secret。

开放问题

  1. SDS 不透明证书与同端口 HTTP/2 coalescing:默认降 HTTP/1.1 是否应成为多租户 HTTPS 的 SLO 项?需要在真实 ALPN 流量下测,本文未跑。
  2. 外部 SDS 身份与 Kubernetes Secret 授权是否足够:能创建 gateway.envoyproxy.io/sds Secret 的主体,等于能让 Envoy 向该 UDS 请求任意 secretName。文档已警告互不信任租户应拆代理身份。
  3. BackendTLSPolicy 与节点级透明加密(WireGuard 等)叠层时的责任划分,见 cilium/15;本篇不引用虚构延迟百分比。

七、小结

  1. Listener 证书终止客户端 TLS;BackendTLSPolicy 终止(实际是发起)到后端的 TLS。两套材料、两套失败模式。
  2. 外部 SDS 的 url 在 v1.9 必须 unix://;UDS cluster 名带 hash。
  3. WellKnownCACertificates: System 默认共享 system_ca_certificates;per-resource -ca 不是现行默认。
  4. EnvoyPatchPolicy 盯旧 secret/cluster 名会在升级后打空;不要 patch 共享系统 CA secret。

下一篇是版本门:TCPRoute/UDPRoute 改走 v1 之后,不升 Gateway API CRDs 会让 L4 路由静默消失


八、参考资料

规范 / 官方文档(A)

源码(A)

核心论文 / 规范传统

实验 / 工具

站内对照


上一篇:HTTPRoute / GRPCRoute · 系列目录 · 下一篇:L4 路由

读完这篇,下一步读什么

优先读同系列或同问题的下一篇,把单篇消费变成主题集群。

2026-08-19 · kubernetes / network

【Envoy Gateway】Provider 与 watch:哪些对象进入翻译输入集

钉清 Envoy Gateway v1.9.0 Kubernetes provider 如何把 Gateway API 与引用对象收成翻译输入集、Status Manager 如何写回,以及漏 watch、缺 CRD、namespace 范围收窄时的失败表象;并核对 System Design 对 file provider 的过时表述。


By .