ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Cilium Gateway API 实战:用 BackendTLSPolicy 为 Gateway 到后端服务的流量启用 TLS

2026/9/14 22:34:03 拓冰建站 浏览量
Cilium Gateway API 实战:用 BackendTLSPolicy 为 Gateway 到后端服务的流量启用 TLS Cilium Gateway API 实战用 BackendTLSPolicy 为 Gateway 到后端服务的流量启用 TLS【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium本篇基于 Cilium 仓库中的Documentation/network/servicemesh/gateway-api/backendtlspolicy.rst示例文档展开完整演示如何在 Cilium Gateway 中利用 Gateway API 的BackendTLSPolicy资源让网关数据面 Envoy与后端服务之间建立并验证 TLS 连接。读完本文你可以掌握如何用mkcert生成演示证书、如何将证书装入 Kubernetes Secret/ConfigMap、如何把后端echo-server切换为 TLS 模式以及 Cilium operator 侧是如何校验BackendTLSPolicy并把策略下发到数据面的。背景BackendTLSPolicy 解决什么问题Cilium 的 Gateway API 支持分两段处理 TLS客户端到 Gateway 的 TLS由 Gateway Listener 的tls字段处理与 Gateway 到后端服务的 TLS。BackendTLSPolicy属于后者它挂在 Gateway 的命名空间中通过targetRefs指向一个后端 Service告诉网关访问该后端时必须使用 TLS 连接并可以用指定 CA 验证后端证书。该示例使用 Gateway API 社区的echo-server演示应用镜像gcr.io/k8s-staging-gateway-api/echo-basic。这个应用读取环境变量TLS_SERVER_CERT与TLS_SERVER_PRIVKEY当两个变量都设置时它会额外在 8443 端口启动 TLS 监听且当请求经过 TLS 时响应 JSON 中会多出一个tls字段用于验证加密确实生效。整个任务使用自签名 CA仅用于演示目的不要直接照搬到生产环境。第一步部署 echo-server 与 Gateway/HTTPRoute示例清单位于 echo-server.yaml 与 echo-server-gatewaypi-httproute.yaml直接kubectl apply即可。核心内容如下Service 与 Deployment初始为纯 HTTP3000 端口apiVersion: v1 kind: Service metadata: name: backend labels: app: backend service: backend spec: ports: - name: http port: 3000 targetPort: 3000 selector: app: backend --- apiVersion: apps/v1 kind: Deployment metadata: name: backend spec: replicas: 1 selector: matchLabels: app: backend version: v1 template: metadata: labels: app: backend version: v1 spec: serviceAccountName: backend containers: - image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e imagePullPolicy: IfNotPresent name: backend ports: - containerPort: 3000 env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespaceGateway 与 HTTPRoutegatewayClassName: cilium即由 Cilium 处理该 GatewayapiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: my-gateway spec: gatewayClassName: cilium listeners: - name: http protocol: HTTP port: 80 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: backend spec: parentRefs: - name: my-gateway hostnames: - www.example.com rules: - backendRefs: - group: kind: Service name: backend port: 3000 weight: 1 matches: - path: type: PathPrefix value: /用 curl 验证基线把GATEWAY_IP_ADDRESS替换为你的 Gateway 地址$ curl -v --resolve www.example.com:80:GATEWAY_IP_ADDRESS http://www.example.com/get正常应返回请求信息的 JSON例如{ path: /get, host: www.example.com, method: GET, proto: HTTP/1.1, headers: { Accept: [*/*], User-Agent: [curl/8.20.0], X-Envoy-Internal: [true], X-Forwarded-For: [172.19.0.1], X-Forwarded-Proto: [http], X-Request-Id: [bb913f3e-7538-4873-88e4-25499fe5b3ff] }, namespace: default, ingress: , service: , pod: backend-86c6c76f-ptczl }响应中出现了X-Envoy-Internal: true头说明请求确实经过了 Cilium 内置的 Envoy 数据面。此时尚无tls字段因为后端走的是明文 HTTP。第二步用 mkcert 生成演示证书需要安装mkcert上游项目文档通过github-mkcert链接引用。它会生成一个本地自签名 CA并为指定域名签发该 CA 签名的证书。在本地目录执行mkcert www.example.com完成后当前目录会生成两个文件www.example.com.pem—— 服务端证书www.example.com-key.pem—— 服务端私钥。再执行一次mkcert -install或按 mkcert 提示可以信任本地 CA本示例不走系统信任而是把 CA 通过 ConfigMap 交给 Gateway 做后端校验因此无需安装到系统。再次强调自签名 CA 只用于演示生产环境应使用正式的证书签发体系如 cert-manager、云厂商证书服务等。第三步把证书和 CA 装入集群把服务端证书与私钥存入一个 TLS Secretkubectl create secret tls example-cert --keywww.example.com-key.pem --certwww.example.com.pem把 CA 证书存入 ConfigMap键名必须是ca.crtkubectl create configmap example-ca --from-fileca.crtwww.example.com.pem键名ca.crt不是可有可无的约定——Cilium operator 的校验逻辑会显式检查这一点。在 operator/pkg/gateway-api/policychecks/backendtlspolicy.go 中可以看到ConfigMap 中不存在ca.crt键时策略被标记为拒绝原因是InvalidCACertificateRef消息为 CA Certificate ConfigMap does not contain aca.crtkeyca.crt的内容还会经过helpers.IsValidPemFormat校验不是合法 PEM 编码的证书同样会被拒绝does not contain at least one valid PEM-encoded certificate。此外该校验还要求CACertificateRefs与wellKnownCACertificates不可同时设置CACertificateRefs最多只能有一个引用引用必须是group: 、kind: ConfigMap否则会以InvalidKind拒绝见同文件 ValidateSpec。这些约束解释了为什么后文的BackendTLSPolicy示例中group为空字符串、kind为ConfigMap。第四步把后端切换为 TLS 模式用kubectl patch给backendDeployment 挂载证书 Secret并注入两个环境变量kubectl patch deployment backend --typejson --patch - op: add path: /spec/template/spec/containers/0/volumeMounts value: - name: secret-volume mountPath: /etc/secret-volume - op: add path: /spec/template/spec/volumes value: - name: secret-volume secret: secretName: example-cert items: - key: tls.crt path: crt - key: tls.key path: key - op: add path: /spec/template/spec/containers/0/env/- value: name: TLS_SERVER_CERT value: /etc/secret-volume/crt - op: add path: /spec/template/spec/containers/0/env/- value: name: TLS_SERVER_PRIVKEY value: /etc/secret-volume/key 说明两点Secret 中的tls.crt/tls.key两个键分别映射为容器内/etc/secret-volume/crt与/etc/secret-volume/key环境变量TLS_SERVER_CERT与TLS_SERVER_PRIVKEY是echo-basic镜像识别 TLS 模式的开关设置后应用会在 8443 端口启用 TLS 监听。然后更新backendService把端口暴露为 443 并把流量引到后端的 8443apiVersion: v1 kind: Service metadata: labels: app: backend service: backend name: backend spec: selector: app: backend ports: - name: https port: 443 protocol: TCP targetPort: 8443注意https这个端口名后面会被BackendTLSPolicy的sectionName引用。第五步创建 BackendTLSPolicy 并指向 443创建策略告诉 Cilium Gateway 以 TLS 方式访问该后端并用example-caConfigMap 中的 CA 验证后端证书、期望主机名为www.example.comapiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: enable-backend-tls namespace: default spec: targetRefs: - group: kind: Service name: backend sectionName: https validation: caCertificateRefs: - name: example-ca group: kind: ConfigMap hostname: www.example.com字段要点spec.targetRefs定位要施加 TLS 的后端此处是default命名空间的backendService 的https端口sectionName: https对应上一步 Service 中的端口名spec.validation.hostname期望后端证书的 SNI/主机名即www.example.com与mkcert签发时使用的域名一致spec.validation.caCertificateRefs验证后端证书所用的 CA必须是含ca.crt键的 ConfigMap见第三步源码分析。最后把 HTTPRoute 中后端引用端口从 3000 改为 443让路由指向新的 TLS 端口kubectl patch HTTPRoute backend --typejson --patch - op: replace path: /spec/rules/0/backendRefs/0/port value: 443 验证curl 观察响应中的 TLS 详情再次通过 Gateway 访问$ curl -vI --resolve www.example.com:80:YOUR_GATEWAY_EXTERNAL_IP http://www.example.com:80/get应收到200 OK。与最初基线响应的差别在于现在响应中出现了tls字段{ tls: { version: TLSv1.3, serverName: www.example.com, negotiatedProtocol: http/1.1, cipherSuite: TLS_AES_128_GCM_SHA256 } }这证明 Gateway 与后端之间的连接已经升级为 TLS本例协商出 TLSv1.3 与TLS_AES_128_GCM_SHA256加密套件SNI 为www.example.com。而客户端到 Gateway 这一段仍然是第 1 步里配置的 HTTP Listener80 端口明文两段连接的安全属性由不同资源分别控制。深入Cilium 侧如何处理 BackendTLSPolicy 事件除了上面的操作步骤仓库源码还能回答改动了 CA ConfigMap 之后集群如何感知并重新下发数据面配置这个问题。在 operator/pkg/gateway-api/watch-handlers/backendtlspolicy.go 中注册了两类事件处理器EnqueueRequestForBackendTLSPolicy当某个BackendTLSPolicy变化时从targetRefs中收集 Service 引用updateReconcileRequestsForBackendTLSPolicy会把它们整理为命名空间/服务名再利用BackendServiceHTTPRouteIndex字段索引反查出所有backendRefs引用了这些 Service 的 HTTPRoute最终汇总出需要 reconcile 的 Gateway 集合。也就是说策略 → Service → HTTPRoute → Gateway 这条反向所有链是 operator 主动推导的EnqueueRequestForBackendTLSPolicyConfigMap当 ConfigMap如 CA 证书变化时通过BackendTLSPolicyConfigMapIndex索引查出引用它的 BackendTLSPolicy再走同样的反查逻辑入队。这意味着你只更新 ConfigMap 里的ca.crtoperator 也会自动重新触发相关 Gateway 的调和无需手工 patch 策略。校验层面调和流程会调用 BackendTLSPolicyInput.ValidateSpec校验失败时通过setRejectedConditions在status.ancestors上写入AcceptedFalse与ResolvedRefsFalse条件并附具体原因可用kubectl get backendtlspolicy enable-backend-tls -o yaml观察这些条件来排错例如忘记在 ConfigMap 中建ca.crt键、PEM 内容损坏、引用了 Secret 而非 ConfigMap 等场景都有明确报错文案。策略与 Gateway 的关联调和细节另见 operator/pkg/gateway-api/gateway_reconcile.go相关测试用例覆盖在 operator/pkg/gateway-api/testdata/gateway 目录下如httproute-backendtlspolicy-reencrypt、httproute-backendtlspolicy-invalid-kind等场景。小结本文按仓库示例文档走通了 Cilium Gateway 后端 TLS 的完整闭环部署echo-server建立明文基线 →mkcert生成演示证书 → Secret/ConfigMap 入集群CA 键名必须为ca.crt→ patch Deployment 启用 8443 端口 TLS 并把 Service 切到 443 → 创建BackendTLSPolicy绑定targetRefs与validation→ 修改 HTTPRoute 端口 → 用 curl 响应中的tls字段确认生效。源码层面的校验与事件反查逻辑说明Cilium operator 会把 BackendTLSPolicy、CA ConfigMap 的变化自动传导到对应 Gateway 的数据面配置中配置错误也会以标准 Gateway API 条件形式暴露在资源状态里便于排查。【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考