使用 Let's Encrypt 和 Ingress 设置 kubernetes - Gnutls_handshake() 失败:收到意外的 TLS 数据包
Setting up kubernetes with Let's Encrypt and Ingress - Gnutls_handshake() failed: An unexpected TLS packet was received
我正在使用标准程序为我在 Kubernetes 上 运行 的应用程序启用 HTTPS 终止,使用:
- 入口 nginx
- AWS ELB 经典
- Let's encrypt
的证书管理器
我之前能够使 Ingress 与 HTTP 一起工作,但我在使用 HTTPS 时遇到问题,当我尝试 cURL 应用 URL:
$ curl -iv https://<SERVER>
* Rebuilt URL to: <SERVER>
* Trying <IP_ADDR>...
* Connected to <SERVER> (<IP_ADDR>) port 443 (#0)
* found 148 certificates in /etc/ssl/certs/ca-certificates.crt
* found 592 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* gnutls_handshake() failed: An unexpected TLS packet was received.
* Closing connection 0
curl: (35) gnutls_handshake() failed: An unexpected TLS packet was received.
这是我目前拥有的:
kube-system 命名空间中的证书管理器运行:
$ kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
cert-manager-5f8db6f6c4-c4t4k 1/1 Running 0 2d1h
cert-manager-webhook-85dd96d87-rxc7p 1/1 Running 0 2d1h
cert-manager-webhook-ca-sync-pgq6b 0/1 Completed 2 2d1h
ingress-nginx 命名空间中的入口设置:
$ kubectl get all -n ingress-nginx
NAME READY STATUS RESTARTS AGE
pod/default-http-backend-587b7d64b5-ftws2 1/1 Running 0 2d1h
pod/nginx-ingress-controller-68bb4bfd98-zsz8d 1/1 Running 0 12h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/default-http-backend ClusterIP <IP_ADDR_1> <none> 80/TCP 2d1h
service/ingress-nginx NodePort <IP_ADDR_2> <none> 80:32327/TCP,443:30313/TCP 2d1h
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deployment.apps/default-http-backend 1 1 1 1 2d1h
deployment.apps/nginx-ingress-controller 1 1 1 1 12h
应用命名空间中的应用程序和入口:
$ kubectl get all -n app
NAME READY STATUS RESTARTS AGE
pod/appserver-0 1/1 Running 0 2d1h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/appserver ClusterIP <IP_ADDR> <none> 22/TCP,80/TCP 2d1h
NAME DESIRED CURRENT AGE
statefulset.apps/appserver 1 1 2d1h
$ kubectl describe ingress -n app
Name: appserver
Namespace: app
Address:
Default backend: default-http-backend:80 (<none>)
TLS:
letsencrypt-prod terminates <SERVER>
Rules:
Host Path Backends
---- ---- --------
<SERVER>
/ appserver:80 (<none>)
Annotations:
certmanager.k8s.io/cluster-issuer: letsencrypt-prod
kubernetes.io/ingress.class: nginx
Events: <none>
这是入口资源的样子:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
certmanager.k8s.io/cluster-issuer: letsencrypt-prod
name: appserver
namespace: app
spec:
tls:
- hosts:
- <SERVER>
secretName: letsencrypt-prod
rules:
- host: <SERVER>
http:
paths:
- backend:
serviceName: appserver
servicePort: 80
path: /
我完成的额外检查:
已检查证书是否已正确生成:
$ kubectl describe cert -n app
Name: letsencrypt-prod
...
Status:
Conditions:
Last Transition Time: 2019-03-20T14:23:07Z
Message: Certificate is up to date and has not expired
Reason: Ready
Status: True
Type: Ready
已检查来自证书管理器的日志:
$ kubectl logs -f cert-manager-5f8db6f6c4-c4t4k -n kube-system
...
I0320 14:23:08.368872 1 sync.go:177] Certificate "letsencrypt-prod" for ingress "appserver" already exists
I0320 14:23:08.368889 1 sync.go:180] Certificate "letsencrypt-prod" for ingress "appserver" is up to date
I0320 14:23:08.368894 1 controller.go:179] ingress-shim controller: Finished processing work item "app/appserver"
I0320 14:23:12.548963 1 controller.go:183] orders controller: syncing item 'app/letsencrypt-prod-1237734172'
I0320 14:23:12.549608 1 controller.go:189] orders controller: Finished processing work item "app/letsencrypt-prod-1237734172"
目前还不太确定还有什么值得检查的?
您似乎在使用带有证书管理器的 nginx-ingress 的旧版本,这可能是您出错的罪魁祸首。
我建议您尝试使用最新版本的 Helm 部署 nginx-ingress(确保 nginx-ingress-controller 的镜像标签为 v0.23.0)。还要确保在 helm 部署期间使用最新版本 (--version v0.7.0) 部署证书管理器。默认情况下,您应该看到三个 pods:cert-manager、cert-manager-cainjector 和 cert-manager-webhook。
我不得不禁用 webhook,因为它阻止了证书的颁发,尽管它提供了正确的参数,所以你可能也必须这样做。
希望对您有所帮助!
毕竟,问题似乎与我如何在 AWS 上的 ELB classic 上设置监听器有关。
我完成了以下操作:
HTTP 80 -> HTTP <INGRESS_SVC_NODE_PORT_1>
HTTP 443 -> HTTP <INGRESS_SVC_NODE_PORT_2>
第一个错误是我对 443 端口使用了 HTTP 而不是 HTTPS。当我尝试使用 HTTPS 时,我必须输入 SSL 证书,这对我来说没有意义,因为我正在使用 Let's encrypt 在 Ingress 级别进行 SSL 终止。
因此,以下侦听器配置有效:
TCP 80 -> TCP <INGRESS_SVC_NODE_PORT_1>
TCP 443 -> TCP <INGRESS_SVC_NODE_PORT_2>
我正在使用标准程序为我在 Kubernetes 上 运行 的应用程序启用 HTTPS 终止,使用: - 入口 nginx - AWS ELB 经典 - Let's encrypt
的证书管理器我之前能够使 Ingress 与 HTTP 一起工作,但我在使用 HTTPS 时遇到问题,当我尝试 cURL 应用 URL:
$ curl -iv https://<SERVER>
* Rebuilt URL to: <SERVER>
* Trying <IP_ADDR>...
* Connected to <SERVER> (<IP_ADDR>) port 443 (#0)
* found 148 certificates in /etc/ssl/certs/ca-certificates.crt
* found 592 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* gnutls_handshake() failed: An unexpected TLS packet was received.
* Closing connection 0
curl: (35) gnutls_handshake() failed: An unexpected TLS packet was received.
这是我目前拥有的:
kube-system 命名空间中的证书管理器运行:
$ kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
cert-manager-5f8db6f6c4-c4t4k 1/1 Running 0 2d1h
cert-manager-webhook-85dd96d87-rxc7p 1/1 Running 0 2d1h
cert-manager-webhook-ca-sync-pgq6b 0/1 Completed 2 2d1h
ingress-nginx 命名空间中的入口设置:
$ kubectl get all -n ingress-nginx
NAME READY STATUS RESTARTS AGE
pod/default-http-backend-587b7d64b5-ftws2 1/1 Running 0 2d1h
pod/nginx-ingress-controller-68bb4bfd98-zsz8d 1/1 Running 0 12h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/default-http-backend ClusterIP <IP_ADDR_1> <none> 80/TCP 2d1h
service/ingress-nginx NodePort <IP_ADDR_2> <none> 80:32327/TCP,443:30313/TCP 2d1h
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deployment.apps/default-http-backend 1 1 1 1 2d1h
deployment.apps/nginx-ingress-controller 1 1 1 1 12h
应用命名空间中的应用程序和入口:
$ kubectl get all -n app
NAME READY STATUS RESTARTS AGE
pod/appserver-0 1/1 Running 0 2d1h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/appserver ClusterIP <IP_ADDR> <none> 22/TCP,80/TCP 2d1h
NAME DESIRED CURRENT AGE
statefulset.apps/appserver 1 1 2d1h
$ kubectl describe ingress -n app
Name: appserver
Namespace: app
Address:
Default backend: default-http-backend:80 (<none>)
TLS:
letsencrypt-prod terminates <SERVER>
Rules:
Host Path Backends
---- ---- --------
<SERVER>
/ appserver:80 (<none>)
Annotations:
certmanager.k8s.io/cluster-issuer: letsencrypt-prod
kubernetes.io/ingress.class: nginx
Events: <none>
这是入口资源的样子:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
certmanager.k8s.io/cluster-issuer: letsencrypt-prod
name: appserver
namespace: app
spec:
tls:
- hosts:
- <SERVER>
secretName: letsencrypt-prod
rules:
- host: <SERVER>
http:
paths:
- backend:
serviceName: appserver
servicePort: 80
path: /
我完成的额外检查:
已检查证书是否已正确生成:
$ kubectl describe cert -n app
Name: letsencrypt-prod
...
Status:
Conditions:
Last Transition Time: 2019-03-20T14:23:07Z
Message: Certificate is up to date and has not expired
Reason: Ready
Status: True
Type: Ready
已检查来自证书管理器的日志:
$ kubectl logs -f cert-manager-5f8db6f6c4-c4t4k -n kube-system
...
I0320 14:23:08.368872 1 sync.go:177] Certificate "letsencrypt-prod" for ingress "appserver" already exists
I0320 14:23:08.368889 1 sync.go:180] Certificate "letsencrypt-prod" for ingress "appserver" is up to date
I0320 14:23:08.368894 1 controller.go:179] ingress-shim controller: Finished processing work item "app/appserver"
I0320 14:23:12.548963 1 controller.go:183] orders controller: syncing item 'app/letsencrypt-prod-1237734172'
I0320 14:23:12.549608 1 controller.go:189] orders controller: Finished processing work item "app/letsencrypt-prod-1237734172"
目前还不太确定还有什么值得检查的?
您似乎在使用带有证书管理器的 nginx-ingress 的旧版本,这可能是您出错的罪魁祸首。
我建议您尝试使用最新版本的 Helm 部署 nginx-ingress(确保 nginx-ingress-controller 的镜像标签为 v0.23.0)。还要确保在 helm 部署期间使用最新版本 (--version v0.7.0) 部署证书管理器。默认情况下,您应该看到三个 pods:cert-manager、cert-manager-cainjector 和 cert-manager-webhook。
我不得不禁用 webhook,因为它阻止了证书的颁发,尽管它提供了正确的参数,所以你可能也必须这样做。
希望对您有所帮助!
毕竟,问题似乎与我如何在 AWS 上的 ELB classic 上设置监听器有关。
我完成了以下操作:
HTTP 80 -> HTTP <INGRESS_SVC_NODE_PORT_1>
HTTP 443 -> HTTP <INGRESS_SVC_NODE_PORT_2>
第一个错误是我对 443 端口使用了 HTTP 而不是 HTTPS。当我尝试使用 HTTPS 时,我必须输入 SSL 证书,这对我来说没有意义,因为我正在使用 Let's encrypt 在 Ingress 级别进行 SSL 终止。
因此,以下侦听器配置有效:
TCP 80 -> TCP <INGRESS_SVC_NODE_PORT_1>
TCP 443 -> TCP <INGRESS_SVC_NODE_PORT_2>