在 K8s Gateway API 中为多个 Hostname 使用单个证书
随着 Ingress NGINX 的退役,一些 Kubernetes 集群迁移到了 Gateway API 上。Gateway API 通过 hostname intersection 的机制对请求进行路由,具体可见文档 《Hostnames in Gateway API》。也就是说,默认情况下,SSL 证书的 CN 必须和 Host 一致,或者使用泛域名的 CN 和 Host 必须有交集。但在某些情况下,SSL 证书和请求的 Host 头可能不一致。比如典型的 SaaS 支持不同的第三方域名,使用 CDN(比如 Azure Front Door)管理这些域名的证书,但这些证书可能无法导出到 Kubernetes 中。在 Nginx 中,可以实现 SNI 和 Host 头不同,即使用自有域名的证书建立 TLS 连接,然后再通过请求里的 Host 进行路由。在 Gateway API 中,其实也可以做到。
Gateway 的配置 🔗
在创建 Gateway 时,不设置 Host,其部分定义如下:
listeners:
- allowedRoutes:
namespaces:
from: All
name: http
port: 80
protocol: HTTP
- allowedRoutes:
namespaces:
from: All
name: https-fallback
port: 443
protocol: HTTPS
tls:
certificateRefs:
- kind: Secret
name: <secret-name-for-certificate>
mode: Terminate
在创建 HttpRoute 时,可指定或者不指定 Hostname:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
#...
spec:
hostnames:
- abc.com
- bcd.com
- x.x.x.x # 甚至可以写 IP
#...
rules:
#...
测试 🔗
curl -v --connect-to <SNI Hostname>:<IP>:443 -H "Host: <HTTP Host Header Value>" https://<SNI Hostname>/ping