【问题标题】:Https connection refused, using ingress-nginxHTTPS连接被拒绝,使用ingress-nginx
【发布时间】:2020-04-24 19:25:35
【问题描述】:

我在 Ubuntu 19.10 上安装了 kubernetes。 我已经设置了 ingress-nginx 并且可以使用 http 访问我的测试服务。 但是,当我尝试通过 https 访问时,我收到“连接被拒绝”。

[编辑] 我试图让 https 在入口处终止,并将未加密的流量传递给我的服务,就像 http 一样。我已经根据我见过的许多示例实现了以下内容,但运气不佳。

Yaml

kind: Service
apiVersion: v1
metadata:
  name: messagemanager-service
  namespace: default
  labels:
    name: messagemanager-service
spec:
  type: NodePort
  selector:
    app: messagemanager
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080
    nodePort: 31212
    name: http

  externalIPs:
    - 192.168.0.210


---
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
  name: messagemanager
  labels:
        app: messagemanager
        version: v1
spec:
  replicas: 3
  selector:
      matchLabels:
        app: messagemanager
  template:
    metadata:
      labels:
        app: messagemanager
        version: v1
    spec:  
      containers:
      - name: messagemanager
        image: test/messagemanager:1.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080
          protocol: TCP
---

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: messagemanager-ingress
  annotations: 
    nginx.ingress.kubernetes.io/ssl-passthrough: false
    ingress.kubernetes.io/rewrite-target: /
spec:
  tls:
    - secretName: tls-secret  
  rules:
  - http:
      paths:
        - path: /message
          backend:
            serviceName: messagemanager-service
            servicePort: 8080

https 测试

curl -kL https://192.168.0.210/message -verbose
*   Trying 192.168.0.210:443...
* TCP_NODELAY set
* connect to 192.168.0.210 port 443 failed: Connection refused
* Failed to connect to 192.168.0.210 port 443: Connection refused
* Closing connection 0
curl: (7) Failed to connect to 192.168.0.210 port 443: Connection refused

http 测试

curl -kL http://192.168.0.210/message -verbose
*   Trying 192.168.0.210:80...
* TCP_NODELAY set
* Connected to 192.168.0.210 (192.168.0.210) port 80 (#0)
> GET /message HTTP/1.1
> Host: 192.168.0.210
> User-Agent: curl/7.65.3
> Accept: */*
> Referer: rbose
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: text/plain;charset=UTF-8
< Date: Fri, 24 Apr 2020 18:44:07 GMT
< connection: keep-alive
< content-length: 50
<
* Connection #0 to host 192.168.0.210 left intact
$ kubectl -n ingress-nginx get svc
NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.105.92.236   <pending>     80:31752/TCP,443:32035/TCP   2d
ingress-nginx-controller-admission   ClusterIP      10.100.223.87   <none>        443/TCP                      2d

$ kubectl get ingress -o wide
NAME                     CLASS    HOSTS   ADDRESS   PORTS     AGE
messagemanager-ingress   <none>   *                 80, 443   37m

密钥创建

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
kubectl create secret tls tls-secret --key tls.key --cert tls.crt
$ kubectl describe ingress
Name:             messagemanager-ingress
Namespace:        default
Address:
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
TLS:
  tls-secret terminates
Rules:
  Host        Path  Backends
  ----        ----  --------
  *
              /message   messagemanager-service:8080 ()
Annotations:  Events:
  Type        Reason  Age   From                      Message
  ----        ------  ----  ----                      -------
  Normal      CREATE  107s  nginx-ingress-controller  Ingress default/messagemanager-ingress

我假设 TLS 将在入口处终止,并且请求将作为 http 传递给服务。 我必须在服务中添加外部 IP 才能使 HTTP 正常工作。 我是否缺少 HTTPS 的类似内容?

感谢任何帮助和指导。

谢谢

标记

【问题讨论】:

标签: ssl kubernetes https kubernetes-ingress


【解决方案1】:

我已经在我的实验室中重现了您的场景,在您对入口进行了一些更改后,它可以按照您的描述工作。

在我的实验室中,我使用了一个 nginx 图像,该图像在端口 80 上提供默认登录页面,并且使用此 Ingress 规则,可以在端口 80 和 443 上提供它。

kind: Deployment
apiVersion: apps/v1
metadata:
  name: nginx
  labels:
        app: nginx
        version: v1
spec:
  replicas: 3
  selector:
      matchLabels:
        app: nginx
  template:
    metadata:
      labels:
        app: nginx
        version: v1
    spec:  
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          protocol: TCP
---
kind: Service
apiVersion: v1
metadata:
  name: nginx-service
  namespace: default
  labels:
    name: nginx-service
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 31000
    name: http          
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: nginx
  labels:
    app: nginx  
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /  
spec:
  tls:
    - secretName: tls-secret  
  rules:
  - http:
      paths:
      - path: /nginx
        backend:
          serviceName: nginx-service
          servicePort: 80

我的 ingress 和你的唯一区别是我删除了 nginx.ingress.kubernetes.io/ssl-passthrough: false。在documentation我们可以阅读:

注意 SSL 直通默认禁用

所以你不需要指定。

我使用了和你一样的秘密:

$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
$ kubectl create secret tls tls-secret --key tls.key --cert tls.crt

在您的问题中,我的印象是您正试图通过 IP 192.168.0.210 到达您的入口。这是您的服务 IP,而不是您的 Ingress IP。

如果您使用的是云托管 Kubernetes,则必须运行以下命令来查找您的 Ingress IP:

$ kubectl get ingresses nginx 
NAME    HOSTS   ADDRESS        PORTS     AGE
nginx   *       34.89.108.48   80, 443   6m32s

如果您在 Bare Metal 上运行而没有任何 LoadBalancer 解决方案,如 MetalLB,您可以看到您的 ingress-nginx 服务将在 Pending 上永远使用 EXTERNAL-IP

$ kubectl get service -n ingress-nginx 
NAME                                            TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-1587980954-controller             LoadBalancer   10.110.188.236   <pending>     80:31024/TCP,443:30039/TCP   23s

您可以执行与服务相同的操作并手动添加外部 IP:

 kubectl get service -n ingress-nginx 
NAME                                            TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-1587980954-controller             LoadBalancer   10.110.188.236   10.156.0.24   80:31024/TCP,443:30039/TCP   9m14s

在此更改之后,您的入口将具有与您在入口服务中定义的相同的 IP:

$ kubectl get ingress nginx 
NAME    CLASS    HOSTS   ADDRESS       PORTS     AGE
nginx   <none>   *       10.156.0.24   80, 443   118s
$ curl -kL https://10.156.0.24/nginx --verbose
*   Trying 10.156.0.24...
* TCP_NODELAY set
* Connected to 10.156.0.24 (10.156.0.24) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: O=Acme Co; CN=Kubernetes Ingress Controller Fake Certificate
*  start date: Apr 27 09:49:19 2020 GMT
*  expire date: Apr 27 09:49:19 2021 GMT
*  issuer: O=Acme Co; CN=Kubernetes Ingress Controller Fake Certificate
*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x560cee14fe90)
> GET /nginx HTTP/1.1
> Host: 10.156.0.24
> User-Agent: curl/7.52.1
> Accept: */*
> 
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 200 
< server: nginx/1.17.10
< date: Mon, 27 Apr 2020 10:01:29 GMT
< content-type: text/html
< content-length: 612
< vary: Accept-Encoding
< last-modified: Tue, 14 Apr 2020 14:19:26 GMT
< etag: "5e95c66e-264"
< accept-ranges: bytes
< strict-transport-security: max-age=15724800; includeSubDomains
< 
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
* Curl_http_done: called premature == 0
* Connection #0 to host 10.156.0.24 left intact

编辑:

似乎没有办法手动设置“外部 IP” 可以在服务中完成的入口。如果你知道一个请 让我知道 :-)。看来我最好的选择是尝试 MetalLB。

MetalLB 将是生产的最佳选择。如果您只为实验室运行它,您可以选择添加节点公共 IP(您可以通过运行 kubectl get nodes -o wide 获得相同的 IP)并将其附加到您的 NGINX 入口控制器。

将节点 IP 添加到 NGINX 入口控制器

spec:
  externalIPs:
  - 192.168.0.210

创建一个名为ingress-nginx-svc-patch.yaml 的文件并粘贴上面的内容。

接下来使用以下命令应用更改:

kubectl patch service ingress-nginx-controller -n kube-system --patch "$(cat ingress-nginx-svc-patch.yaml)"

结果:

$ kubectl get service -n kube-system ingress-nginx-controller
NAME                       TYPE           CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller   LoadBalancer   10.97.0.243   192.168.0.210   80:31409/TCP,443:30341/TCP   39m

【讨论】:

  • 谢谢。所以入口永远不会被请求击中,它始终是通过外部 IP 的服务。这是有道理的,并解释了 https 的连接被拒绝错误。似乎没有办法像在服务中那样手动设置入口的“外部 IP”。如果你知道一个,请告诉我:-)。看来我最好的选择是尝试 MetalLB。
  • 我编辑了我的答案,包括与您的问题相关的内容。如果您还有其他问题,请告诉我。如果我的回答对你有帮助,请不要忘记accept and upvote它。
  • MetaLB 已安装并按预期工作。安装非常简单快捷。再次感谢。
  • 很高兴听到这个消息。享受您的 Ingress。
【解决方案2】:

我不是专家,但每当我看到服务处理 http 和 https 流量时,它都会在 svc yaml 中指定两个端口,一个用于 http,一个用于 https。显然有办法解决这个问题,阅读here 可能是一个好的开始。

两个端口,看官方k8s例子here

【讨论】:

  • 谢谢。这两个端口是 TLS 通行证,尽管我可以收集到。如果我在服务中添加端口 443,我会得到不正确的 TLS 版本。我相信这意味着该服务没有处理正确的 https。我想让 https 在入口处终止并作为 http 传递给服务。从我看到的示例中,这应该可以工作.....我只是无法弄清楚我做错了什么或缺少什么。
【解决方案3】:

我在同样的情况下苦苦挣扎了一段时间,正准备开始使用 metalLB,但在运行 kubectl -n ingress-nginx get svc 后意识到 ingress-nginx 已经创建了自己的 nodePort,我可以通过它访问集群。

我不是专家,但它可能不适合生产,但我不明白为什么不这样做。

【讨论】:

    猜你喜欢
    • 2020-09-21
    • 2021-01-16
    • 2018-03-05
    • 2013-03-02
    • 2020-09-16
    • 1970-01-01
    • 2019-10-06
    • 2021-06-27
    • 2015-09-09
    相关资源
    最近更新 更多