背景: 我们在客户那里部署了一套服务, 服务运行在客户提供的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
即可.