nginx 无法连接到Hetzner Cloud Kubernetes集群上的Neo4J服务器,而相同的设置在Azure AKS上有效

3htmauhk  于 8个月前  发布在  Nginx
关注(0)|答案(1)|浏览(98)

我正在Hetzner Cloud上创建一个Kubernetes集群,其配置与我在Azure AKS上使用的配置相同,但我面临着与Neo4j的连接问题。在Hetzner集群上,虽然我可以从我在Ingress中定义的路径访问Neo4J浏览器,但我无法使用bolt+s连接server.mydomain.com:7687 URL连接到Neo4j服务器,我的Node.js服务器pod中的Neo4j驱动程序也无法连接到Neo4j服务器(第二个连接有点解决,请参阅最后的更新)。AKS集群的情况并非如此。
从Neo4j浏览器debbug连接中,我看到握手失败:

Browser will attempt to open a websocket connection to bolt+s://server.mydomain.com:7687 and do an encrypted and an unencrypted bolt handshake.
bolt handshake
Status: 
Error
encrypted bolt handshake
Status: 
Error

从Chrome控制台,我看到2个错误:

Mixed Content: The page at 'https://server.mydomain.com/neo4j/browser/' was loaded over HTTPS, but requested an insecure resource 'http://server.mydomain.com:7687/'. This request has been blocked; the content must be served over HTTPS.

WebSocket connection to 'wss://server.mydomain.com:7687/' failed:

两个集群之间的一个区别是ingress控制器的负载均衡器配置,在Hetzner上,我在ingress-nginx Helm图表中设置了注解如下:

nginx:
  controller:
    watchIngressWithoutClass: true
    kind: DaemonSet
    config:
      use-forwarded-headers: "true"
      compute-full-forwarded-for: "true"
      use-proxy-protocol: "true"
    service:
      annotations:
        load-balancer.hetzner.cloud/name: server-lb
        load-balancer.hetzner.cloud/use-private-ip: "true"
        load-balancer.hetzner.cloud/disable-private-ingress: "true"
        load-balancer.hetzner.cloud/location: fsn1
        load-balancer.hetzner.cloud/type: lb11
        load-balancer.hetzner.cloud/uses-proxyprotocol: "true"
        load-balancer.hetzner.cloud/http-redirect-https: "true"
        load-balancer.hetzner.cloud/hostname: server.mydomain.com
        # nginx.ingress.kubernetes.io/websocket-services: neo4j

    extraArgs:
      default-ssl-certificate: "default/tls-secret"  

    # nodeSelector:
    #   server-type: server  
  tcp:
    7687: "default/neo4j:7687" 
    7474: "default/neo4j:7474"

AFAIK ingress-nginx控制器(我正在使用)自动处理WebSockets,不像nginx-ingress,它应该使用nginx.ingress.kubernetes.io/websocket-services: neo4j这样的注解Map到服务,我尝试使用注解,但没有什么区别。
我对Hetzner集群使用的完整过程是:我使用k3 s v1.27.4+ k3 s1在Hetzner Cloud上创建了一个Kubernetes单节点集群,安装了ingress-nginx v4.7.1,将TCP端口7474和7687暴露给Neo4j服务,如您在上面看到的(负载均衡器TCP端口暴露且健康)和Cert-manager v1.12.3 Helm charts。
在我的域DNS管理器中,我创建了一个指向负载均衡器IPv4的A记录,主机设置为sever,以便在我的CertificateIngress清单中使用它作为server.mydomain.com。正确创建tls-secret

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-service
  annotations:
    nginx.ingress.kubernetes.io/use-regex: 'true'
    nginx.ingress.kubernetes.io/rewrite-target: /$2$3$4
    ingress.kubernetes.io/ssl-redirect: 'true'
    nginx.ingress.kubernetes/cluster-issuer: letsencrypt-issuer

spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - server.mydomain.com
      secretName: tls-secret
  rules:

    ### Node.js server
    - http:
        paths:
          - path: /(/|$)(.*)
            # pathType: Prefix
            pathType: ImplementationSpecific
            backend:
              service:
                name: server-clusterip-service
                port:
                  number: 80
    - http:
        paths:
          - path: /server(/|$)(.*)
            # pathType: Prefix
            pathType: ImplementationSpecific
            backend:
              service:
                name: server-clusterip-service
                port:
                  number: 80

    ##### Neo4j

    - http:
        paths:
          - path: /bolt(/|$)(.*)
            # pathType: Prefix
            pathType: ImplementationSpecific
            backend:
              service:
                name: neo4j
                port:
                  number: 7687
    - http:
        paths:
          # show browser
          - path: /neo4j(/|$)(.*)
            # pathType: Prefix
            pathType: ImplementationSpecific
            backend:
              service:
                name: neo4j
                port:
                  number: 7474
    - http:
        paths:
          - path: /neo4j-admin(/|$)(.*)
            # pathType: Prefix
            pathType: ImplementationSpecific
            backend:
              service:
                name: neo4j-admin
                port:
                  number: 7474

为了安装Neo4j chart,我为Neo4j配置设置了以下值:

config:
    server.bolt.enabled: 'true'
    server.bolt.tls_level: 'REQUIRED'
    server.bolt.listen_address: '0.0.0.0:7687'
    dbms.ssl.policy.bolt.client_auth: 'NONE'
    dbms.ssl.policy.bolt.enabled: 'true'

    # dbms.connector.bolt.advertised_address: '0.0.0.0:7687' #server.mydomain.com:7687 # new for hetzner (no connection still)

    ## apoc
    server.directories.plugins: '/var/lib/neo4j/labs'
    dbms.security.procedures.unrestricted: 'apoc.*'
    server.config.strict_validation.enabled: 'false'
    dbms.security.procedures.allowlist: 'gds.*,apoc.*'

    ### apoc config
    dbms.directories.plugins: "/var/lib/neo4j/labs"
    dbms.config.strict_validation: "false"


  apoc_config:
    apoc.trigger.enabled: "true"
    apoc.jdbc.neo4j.url: "jdbc:foo:bar"
    apoc.import.file.enabled: "true"

  startupProbe:
    failureThreshold: 1000
    periodSeconds: 50

  ssl:
    # setting per "connector" matching neo4j config
    bolt:
      privateKey:
        secretName: tls-secret
        subPath: tls.key
      publicCertificate:
        secretName: tls-secret
        subPath: tls.crt
      trustedCerts:
        sources: []
      revokedCerts:
        sources: []

我尝试使用任何IP 0.0.0.0:7687值和特定的dns server.mydomain.com:7687值来设置dbms.connector.bolt.advertised_address(Azure上的dough未设置),但这也没有什么区别。在Hetzner防火墙规则中,我为端口80(http)和443(https)创建了规则,以允许端口7474和7687。我也尝试禁用防火墙作为测试,但仍然无法达到Neo4j服务器。你能发现一些其他的配置,我需要添加或更改此设置?非常感谢

更新

我注意到Azure上的nginx-ingress-controller External IP实际上显示了来自负载均衡器的IPv4地址,而在Hetzner上它显示了DNS名称server.mydomain.com,所以我从ingress-nginx服务注解 Helm 图表中删除了load-balancer.hetzner.cloud/hostname: server.mydomain.com注解,没有它,我的Node.js服务器Pod中的Neo4j驱动程序成功连接到Neo4j。
不幸的是,我在网络浏览器中从Neo4j Browser应用程序连接时仍然会遇到两个错误:

Mixed Content: The page at 'https://server.mydomain.com/neo4j/browser/' was loaded over HTTPS, but requested an insecure resource 'http://server.mydomain.com:7687/'. This request has been blocked; the content must be served over HTTPS.

WebSocket connection to 'wss://server.mydomain.com:7687/' failed:

更新二

我重新开始,在颁发Let'sEncrypt证书时,如果我不使用注解load-balancer.hetzner.cloud/hostname: server.mydomain.com,证书颁发会挂起,而它会按预期完成。
我完全在这里兜圈子。

dkqlctbz

dkqlctbz1#

我联系了Neo4j团队,显然这个问题可能与Hetzner网络或他们的负载均衡器有关,所以我的实现在Azure上工作时将2个tcp端口暴露给neo4j默认服务(如下所述),在Hetzner上不起作用。
还有其他选项,例如可以配置为支持TCP连接的nginx-ingress控制器,但在本指南中,我们将尽可能简单地使用标准Kubernetes资源类型。
现在,我最终使用的解决方案是首选的Neo4j方式,即使用专用的LoadBalancer服务,并使用注解,就像我在ingress-nginx图表中所做的那样,我创建了另一个Hetzner负载均衡器,这意味着为它创建第二个tls证书颁发,当然是一个更昂贵的解决方案。
服务类型:LoadBalancer是Neo4j唯一合适的选项。无法使用Ingress,因为Neo4j的驱动程序协议在TCP级别进行通信,而大多数Ingress仅支持HTTP通信。节点端口服务不能与静态IP地址相关联,这使得设置DNS和SSL非常困难。使用NodePort可能会给一些Neo4j应用程序带来配置挑战,这些应用程序希望使用端口7687专门与Neo4j通信。因此,我们建议只使用LoadBalancer服务。
当Neo4j在Ingress后面时,他们正在努力使其无缝工作,其中之一是使用类似Haproxy的东西,他们正在创建Helm Chart,但现在他们只是评估各种方法。目前还没有定论。

相关问题