为ELB Ingress配置服务器名称指示(SNI)
SNI证书是一种扩展服务器证书,允许同一个IP地址和端口号下对外提供多个访问域名,可以根据客户端请求的不同域名来使用不同的安全证书,确保HTTPS通信的安全性。
在配置SNI时,用户需要添加绑定域名的证书,客户端会在发起SSL握手请求时就提交请求的域名信息,负载均衡收到SSL请求后,会根据域名去查找证书。如果找到域名对应的证书,则返回该证书;如果没有找到域名对应的证书,则返回服务器默认证书。
- 使用TLS类型的密钥证书配置SNI:需要将证书导入至Secret中,CCE会将该证书自动配置到ELB侧(证书名以k8s_plb_default开头),由CCE自动创建的证书在ELB侧不可修改或删除。
- 使用ELB服务中的证书配置SNI:直接使用ELB服务中创建的证书,无需手动配置集群Secret,且可以在ELB侧修改证书。
前提条件
- 集群中需提前部署可用的工作负载用于对外提供访问。若您无可用工作负载,可参考创建无状态负载(Deployment)、创建有状态负载(StatefulSet)或创建守护进程集(DaemonSet)部署工作负载。
- 为提供对外访问的工作负载配置Service,ELB Ingress支持的Service类型请参见ELB Ingress支持的Service类型。
- 已准备可信的证书,您可以从证书提供商处获取证书。操作详情请参见购买SSL证书。
使用TLS类型的密钥证书配置SNI
您可以使用以下方式使用TLS类型的密钥证书配置SNI。
- 当使用HTTPS协议时,才支持配置SNI。
- 用于SNI的证书需要指定域名,每个证书只能指定一个域名。支持泛域名证书。
- 安全策略选择(kubernetes.io/elb.tls-ciphers-policy)仅在1.17.11及以上版本的集群中支持。
- 登录CCE控制台,单击集群名称进入集群。
- 选择左侧导航栏的“服务”,在右侧选择“路由”页签,单击右上角“创建路由”。
- 设置Ingress参数。
本示例中展示配置SNI证书的关键参数,其余参数可按需配置,详情请参见通过控制台创建ELB Ingress。
表1 关键参数说明 参数
配置说明
示例
名称
自定义Ingress名称。
ingress-test
负载均衡器
选择对接的ELB实例或自动创建ELB实例。
共享型ELB
监听器配置
- 前端协议:为Ingress配置证书需选择“HTTPS”。
- 对外端口:ELB监听器端口,HTTPS协议的端口默认为443。
- 证书来源:选择“TLS密钥”。
- 服务器证书:支持使用kubernetes.io/tls和IngressTLS两种TLS密钥类型。
如果您没有可选择的密钥证书,可新建TLS类型的密钥证书,对应参数详情请参见创建密钥。
- SNI:输入域名并选择对应的SNI证书,SNI证书中需要包含域名信息,SNI证书支持使用kubernetes.io/tls和IngressTLS两种TLS密钥类型。
- 前端协议:“HTTPS”
- 对外端口:443
- 证书来源:“TLS密钥”
- 服务器证书:test
- SNI:
- 域名:example.com
- 证书:example-test
转发策略配置
- 域名:实际访问的域名地址,不配置时可通过IP地址访问Ingress。请确保所填写的域名已注册并备案,一旦配置了域名规则后,必须使用域名访问。
- 路径匹配规则:支持前缀匹配、精确匹配、正则匹配,请按需选择。
- 路径:后端应用对外提供访问的路径,此处添加的访问路径要求后端应用内存在相同的路径,否则转发无法生效。
- 目标服务名称:请选择已有Service或新建Service。页面列表中的查询结果已自动过滤不符合要求的Service。
- 目标服务访问端口:可选择目标Service的访问端口。
- 域名:example.com
- 路径匹配规则:前缀匹配
- 路径:/
- 目标服务名称:nginx
- 目标服务访问端口:80
图1 使用TLS类型的密钥证书配置SNI
- 配置完成后,单击“确定”。
本例中sni-test-secret为SNI证书,该证书指定的域名必须与证书中的域名一致。
- 请参见通过kubectl连接集群,使用kubectl连接集群。
- 创建名为“ingress-test.yaml”的YAML文件,此处文件名可自定义。
vi ingress-test.yaml
以自动创建关联ELB为例,YAML文件配置如下:
1.21及以下版本集群:apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: ingress-test annotations: kubernetes.io/elb.class: performance kubernetes.io/ingress.class: cce kubernetes.io/elb.port: '443' kubernetes.io/elb.autocreate: '{ "type": "public", "bandwidth_name": "cce-bandwidth-******", "bandwidth_chargemode": "bandwidth", "bandwidth_size": 5, "bandwidth_sharetype": "PER", "eip_type": "5_bgp", "available_zone": [ "ap-southeast-1a" ], "elb_virsubnet_ids":["b4bf8152-6c36-4c3b-9f74-2229f8e640c9"], "l7_flavor_name": "L7_flavor.elb.s1.small" }' kubernetes.io/elb.tls-ciphers-policy: tls-1-2 spec: tls: - secretName: ingress-test-secret - hosts: - example.com #签发证书时指定域名为example.com secretName: sni-test-secret #SNI证书 rules: - host: example.com #域名需要和tls字段中的hosts取值一致 http: paths: - path: '/' backend: serviceName: <your_service_name> #替换为您的目标服务名称 servicePort: 80 property: ingress.beta.kubernetes.io/url-match-mode: STARTS_WITH
1.23及以上版本集群:apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-test annotations: kubernetes.io/elb.class: performance kubernetes.io/elb.port: '443' kubernetes.io/elb.autocreate: '{ "type": "public", "bandwidth_name": "cce-bandwidth-******", "bandwidth_chargemode": "bandwidth", "bandwidth_size": 5, "bandwidth_sharetype": "PER", "eip_type": "5_bgp", "available_zone": [ "ap-southeast-1a" ], "elb_virsubnet_ids":["b4bf8152-6c36-4c3b-9f74-2229f8e640c9"], "l7_flavor_name": "L7_flavor.elb.s1.small" }' kubernetes.io/elb.tls-ciphers-policy: tls-1-2 spec: tls: - secretName: ingress-test-secret - hosts: - example.com #签发证书时指定域名为example.com secretName: sni-test-secret #SNI证书 rules: - host: example.com #域名需要和tls字段中的hosts取值一致 http: paths: - path: '/' backend: service: name: <your_service_name> #替换为您的目标服务名称 port: number: 80 #替换为您的目标服务端口 property: ingress.beta.kubernetes.io/url-match-mode: STARTS_WITH pathType: ImplementationSpecific ingressClassName: cce
- 创建Ingress。
kubectl create -f ingress-test.yaml
回显如下,表示Ingress服务已创建。
ingress/ingress-test created
- 查看已创建的Ingress。
kubectl get ingress
回显如下,表示Ingress服务创建成功。
NAME CLASS HOSTS ADDRESS PORTS AGE ingress-test cce example.com 121.**.**.** 80,443 10s
- 使用HTTPS协议访问Ingress,其中${ELB_IP}为Ingress访问的IP。
curl -H "Host:example.com" -k https://${ELB_IP}:443
可正常访问则表明证书配置成功。
使用ELB服务中的证书配置SNI
您可以使用以下方式为Ingress配置ELB服务中的证书。
- 当同时指定ELB证书和IngressTLS证书时,Ingress将使用ELB服务中的证书。
- CCE不校验ELB服务中的证书是否有效,只校验证书是否存在。
- 仅v1.19.16-r2、v1.21.5-r0、v1.23.3-r0及以上版本的集群支持使用ELB服务中的证书。
- 登录CCE控制台,单击集群名称进入集群。
- 选择左侧导航栏的“服务”,在右侧选择“路由”页签,单击右上角“创建路由”。
- 设置Ingress参数。
本示例中展示配置SNI证书的关键参数,其余参数可按需配置,详情请参见通过控制台创建ELB Ingress。
表2 关键参数说明 参数
配置说明
示例
名称
自定义Ingress名称。
ingress-test
负载均衡器
选择对接的ELB实例或自动创建ELB实例。
共享型ELB
监听器配置
- 前端协议:“HTTPS”
- 对外端口:443
- 证书来源:“ELB服务器证书”
- 服务器证书:cert-test
- SNI:cert-example
转发策略配置
- 域名:实际访问的域名地址,不配置时可通过IP地址访问Ingress。请确保所填写的域名已注册并备案,一旦配置了域名规则后,必须使用域名访问。
- 路径匹配规则:支持前缀匹配、精确匹配、正则匹配,请按需选择。
- 路径:后端应用对外提供访问的路径,此处添加的访问路径要求后端应用内存在相同的路径,否则转发无法生效。
- 目标服务名称:请选择已有Service或新建Service。页面列表中的查询结果已自动过滤不符合要求的Service。
- 目标服务访问端口:可选择目标Service的访问端口。
- 域名:无需填写
- 路径匹配规则:前缀匹配
- 路径:/
- 目标服务名称:nginx
- 目标服务访问端口:80
图2 使用ELB服务中的证书配置SNI
- 配置完成后,单击“确定”。
您可以通过指定kubernetes.io/elb.tls-certificate-ids注解,在Ingress使用ELB服务中的证书。
- 请参见通过kubectl连接集群,使用kubectl连接集群。
- 创建名为“ingress-test.yaml”的YAML文件,此处文件名可自定义。
vi ingress-test.yaml
以关联已有ELB为例,YAML文件配置如下:
1.21及以下版本集群:
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: ingress-test annotations: kubernetes.io/ingress.class: cce kubernetes.io/elb.port: '443' kubernetes.io/elb.id: 0b9a6c4d-bd8b-45cc-bfc8-ff0f9da54e95 kubernetes.io/elb.class: union kubernetes.io/elb.tls-certificate-ids: 058cc023690d48a3867ad69dbe9cd6e5,b98382b1f01c473286653afd1ed9ab63 spec: rules: - host: '' http: paths: - path: '/' backend: serviceName: <your_service_name> #替换为您的目标服务名称 servicePort: 80 property: ingress.beta.kubernetes.io/url-match-mode: STARTS_WITH
1.23及以上版本集群:apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-test namespace: default annotations: kubernetes.io/elb.port: '443' kubernetes.io/elb.id: 0b9a6c4d-bd8b-45cc-bfc8-ff0f9da54e95 kubernetes.io/elb.class: union kubernetes.io/elb.tls-certificate-ids: 058cc023690d48a3867ad69dbe9cd6e5,b98382b1f01c473286653afd1ed9ab63 spec: rules: - host: '' http: paths: - path: '/' backend: service: name: <your_service_name> #替换为您的目标服务名称 port: number: 80 #替换为您的目标服务端口 property: ingress.beta.kubernetes.io/url-match-mode: STARTS_WITH pathType: ImplementationSpecific ingressClassName: cce
表3 关键参数说明 参数
参数类型
描述
kubernetes.io/elb.tls-certificate-ids
String
ELB服务中的证书ID列表,不同ID间使用英文逗号隔开,列表长度大于等于1。列表中的首个ID为服务器证书,其余ID为SNI证书(SNI证书中必须带有域名)。
如果无法根据客户端请求的域名查找到对应的SNI证书,则默认返回服务器证书。
获取方法:在CCE控制台,单击顶部的“服务列表 > 网络 > 弹性负载均衡”,并选择“证书管理”。在列表中复制对应证书名称下的ID即可。
- 创建Ingress。
kubectl create -f ingress-test.yaml
回显如下,表示Ingress服务已创建。
ingress/ingress-test created
- 查看已创建的Ingress。
kubectl get ingress
回显如下,表示Ingress服务创建成功。
NAME CLASS HOSTS ADDRESS PORTS AGE ingress-test cce * 121.**.**.** 80,443 10s
- 使用HTTPS协议访问Ingress,其中${ELB_IP}为Ingress访问的IP。
curl -H "Host:example.com" -k https://${ELB_IP}:443
可正常访问则表明证书配置成功。