背景: 我们在客户那里部署了一套服务, 服务运行在客户提供的 ACK 集群, 我们删除了客户 ACK 自带的 nginx ingress, 通过自建的方式部署了两套 ingress, 一套绑定了公网 CLB, 一套绑定了内网 CLB, 也就是说是 CLB 转发到 ingress, 然后通过 ingress 转发到其他服务. 现在需要配置 Https 证书, 客户不同意我们配置证书到 ingress, 客户将证书放在了 CLB 上, 给了一个证书 ID
查询阿里云文档
阿里云的文档还是很详细, 通过 google 查询到文档地址: 通过Annotation配置传统型负载均衡CLB
具体可以查看这里
HTTPS 请求会在 CLB 层解密,然后以 HTTP 请求的形式发送给后端的 Pod。
配置 LoadBalancer 类型的 Service
因为我们的 CLB 是只给 ingress 使用, 所以修改 ingress 的 Service 配置 yaml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| apiVersion: v1 kind: Service metadata: annotations: service.beta.kubernetes.io/alibaba-cloud-loadbalancer-force-override-listeners: 'true' service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id: lb-<负载均衡ID>
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-protocol-port: "https:443,http:80" service.beta.kubernetes.io/alibaba-cloud-loadbalancer-cert-id: "<证书的ID>" labels: app.kubernetes.io/component: public-controller app.kubernetes.io/instance: public-ingress-nginx app.kubernetes.io/name: public-ingress-nginx app.kubernetes.io/part-of: public-ingress-nginx app.kubernetes.io/version: 1.6.4 name: public-ingress-nginx-controller namespace: nginx-ingress spec: ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - appProtocol: http name: http port: 80 protocol: TCP targetPort: http nodePort: 31080 - appProtocol: https name: https port: 443 protocol: TCP nodePort: 31443 targetPort: https selector: app.kubernetes.io/component: public-controller app.kubernetes.io/instance: public-ingress-nginx app.kubernetes.io/name: public-ingress-nginx type: LoadBalancer
|
遇到的问题
照着上面步骤配置了以后, Https 访问证书是生效了, 但是没法转发到后端, 会报错: The plain HTTP request was sent to HTTPS port
原因分析:
简单画个图
这里 https 请求在 CLB 解密后, 请求后面的 Ingress 是用 http 协议来请求的, 按道理是所有请求都到 pod 的 80 才对, 但是作为用户访问的域名是 https, https 默认的端口是 443, 这样就会造成 CLB 是使用 HTTP 协议来请求 ingress 的 HTTPS 端口, 所以造成了上面的结果.
解决方案
解决方法其实很简单, 只需要将 service 的 443 端口也转发到 pod 的 80 端口即可. 对应的 yaml 文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| apiVersion: v1 kind: Service metadata: annotations: service.beta.kubernetes.io/alibaba-cloud-loadbalancer-force-override-listeners: 'true' service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id: lb-<负载均衡ID> service.beta.kubernetes.io/alibaba-cloud-loadbalancer-protocol-port: "https:443,http:80" service.beta.kubernetes.io/alibaba-cloud-loadbalancer-cert-id: "<证书的ID>" labels: app.kubernetes.io/component: public-controller app.kubernetes.io/instance: public-ingress-nginx app.kubernetes.io/name: public-ingress-nginx app.kubernetes.io/part-of: public-ingress-nginx app.kubernetes.io/version: 1.6.4 name: public-ingress-nginx-controller namespace: nginx-ingress spec: ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - appProtocol: http name: http port: 80 protocol: TCP targetPort: http nodePort: 31080 - appProtocol: https name: https port: 443 protocol: TCP nodePort: 31443 - targetPort: https + targetPort: http selector: app.kubernetes.io/component: public-controller app.kubernetes.io/instance: public-ingress-nginx app.kubernetes.io/name: public-ingress-nginx type: LoadBalancer
|
把这里的 targetPort: https
改成 targetPort: http
即可.