Kubernetes 暴露 Neo4j 服务教程 (HTTP 与 Bolt 分离)

本教程将专注于“服务 (Service)”和“路由 (Ingress)”,解决你遇到的“浏览器(HTTP)”和“代码(Bolt)”访问的问题。

我们假设你已经成功部署了 Neo4j 的 StatefulSet (有状态负载),并且它已经通过 PersistentVolumeClaim (PVC) 挂载了持久化存储。

本教程的唯一目标是:正确地将 Neo4j 的两个端口暴露到集群外部,以便浏览器和代码都能访问。

  • 端口 7474 (HTTP): 用于浏览器 Web UI。
  • 端口 7687 (Bolt): 用于代码驱动连接。

核心问题

你不能使用同一个“应用负载型路由 (ALB)” 同时处理这两种流量。

  • ALB (Ingress): 专为 HTTP/HTTPS 流量设计 (第7层)。
  • Bolt 协议: 是一种原始 TCP 流量 (第4层),它不是 HTTP。

强行用 ALB 处理 Bolt 流量,就会导致 (looks like HTTP) 错误。

解决方案

我们将创建两个独立的服务来分别处理这两种流量:

  1. HTTP (7474): 使用 Ingress (ALB) 暴露。
  2. Bolt (7687): 使用 type: LoadBalancer (NLB) 暴露。

第一部分:暴露 7474 (HTTP) 端口给浏览器

这一部分的目标是让你的 Ingress (ALB) 能正确找到 Neo4j 的 Web 界面。

步骤 1.1: 创建一个 HTTP 内部服务 (ClusterIP)

我们首先创建一个 ClusterIP 类型的服务。这个服务本身不暴露到公网,它只作为集群内部的一个稳定目标,让 Ingress 可以找到它。

注意: 这个服务 包含 7474 端口。

# neo4j-http-service.yml
apiVersion: v1
kind: Service
metadata:
  # 我们给它一个清晰的名称
  name: neo4j-http-service 
  # 确保这个 serviceName 与你的 StatefulSet 中
  # spec.serviceName 字段的值一致
spec:
  type: ClusterIP # 只在集群内部可见
  selector:
    app: neo4j # 确保这与你的 StatefulSet Pod 标签一致
  ports:
  - port: 7474
    targetPort: 7474
    name: http

步骤 1.2: 创建 Ingress (ALB) 路由

现在,我们创建(或更新)你的 Ingress 资源,让它指向我们刚刚创建的 neo4j-http-service

注意: 你的 Ingress (ALB) 将会获得一个公网 IP。这个 IP 仅用于浏览器访问

# neo4j-http-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: neo4j-ingress
  annotations:
    # --- 重要:添加 WebSocket 支持 ---
    # 如果你使用 Nginx Ingress Controller,
    # 这些注解对于 Neo4j 浏览器的稳定性很重要
    # "nginx.ingress.kubernetes.io/proxy-read-timeout": "3600"
    # "nginx.ingress.kubernetes.io/proxy-send-timeout": "3600"
    # (请根据你的 Ingress Controller 类型查找相应注解)
spec:
  rules:
  - host: "neo4j.your-domain.com" # 替换为你的域名
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: neo4j-http-service # 指向步骤 1.1 中创建的服务
            port:
              name: http # 指向 7474 端口

至此,你的浏览器应该可以通过 http://neo4j.your-domain.com 正常访问 Neo4j UI 了。


第二部分:暴露 7687 (Bolt) 端口给代码

这一部分的目标是为你的代码驱动(Python, Java 等)提供一个原始 TCP 连接入口。

步骤 2.1: 创建一个 Bolt 外部服务 (LoadBalancer)

我们将创建第二个 Service,类型为 LoadBalancer。这将告诉你的云服务商为你创建一个网络负载均衡器 (NLB),它专门处理第4层 (TCP) 流量。

注意:

  • 这个服务 包含 7687 端口。
  • 它会获得一个新的、独立的公网 IP,与你的 Ingress (ALB) IP 不同
# neo4j-bolt-service.yml
apiVersion: v1
kind: Service
metadata:
  name: neo4j-bolt-service # 一个新名称
spec:
  # type: LoadBalancer 会创建一个 NLB (网络负载均衡器)
  type: LoadBalancer 
  selector:
    app: neo4j # 同样指向你的 Neo4j Pod
  ports:
  - port: 7687       # 负载均衡器监听 7687
    targetPort: 7687 # Pod 容器的 7687
    name: bolt

步骤 2.2: 获取 Bolt 服务的公网 IP

创建完 neo4j-bolt-service.yml 后,你需要等待几分钟,让云服务商分配公网 IP。

你可以通过 kubectl get service neo4j-bolt-service 来查看分配的 EXTERNAL-IP(外部 IP)。


概念解析:为什么 Bolt (7687) 不需要 Ingress 路由?

这是一个很关键的概念,理解它有助于你理解 Kubernetes 的网络。

简单来说,Bolt 不需要创建“路由规则”(Ingress),是因为 Ingress(路由)Bolt 协议 工作在完全不同的网络层级上。

1. 路由 (Ingress) = “精细分拣的信件服务” (第7层)

  • Ingress (应用负载型路由 ALB) 是专门为 HTTP/HTTPS 流量设计的。
  • 它就像一个智能的邮件分拣中心,会打开信封(数据包),查看里面的内容(比如 host: "neo4j.your-domain.com"),然后再决定把这封信(请求)送到哪个办公室(Service)。
  • 这就是为什么它非常适合用来处理你的浏览器访问(7474 端口),因为它能看懂 HTTP。

2. Bolt 协议 = “加急包裹专送服务” (第4层)

  • Bolt 协议 (7687 端口) 是一种原始 TCP 流量
  • 它就像一个密封的、加急的包裹。它不使用 HTTP 协议,它的“信封”上没有写 host 域名,它只是一个需要被直接送达的数据流。

当你试图让 Ingress(信件分拣中心)去处理 Bolt(加急包裹)时,Ingress 还是会习惯性地把它当成信件拆开,试图在里面寻找 HTTP 内容。当它什么也找不到,只看到一堆它不认识的 Bolt 数据时,就会BaoCuo——这也就是你看到的 (looks like HTTP) 错误。

我们的解决方案:type: LoadBalancer (包裹专线)

  • 在本教程的第二部分,我们创建的 neo4j-bolt-service 使用了 type: LoadBalancer
  • 这会创建一种完全不同的负载均衡器,叫做网络负载均衡器 (NLB)
  • NLB 就像一个“包裹专线”服务(第4层)。它从不打开包裹(数据包),它只看包裹上的端口号7687)。
  • 它收到任何发往 7687 端口的流量(不管里面是 Bolt 还是别的什么),都会原封不动地、快速地转发给你的 Neo4j Pod。

总结:如何连接

  1. 浏览器 (HTTP) 访问:

    • 使用你 Ingress (ALB) 的公网 IP 或域名。
    • 例如: http://neo4j.your-domain.com
  2. 代码 (Bolt) 连接:

    • 使用你 neo4j-bolt-service (NLB) 的新公网 IP
    • 端口号仍然是 7687
    • 连接字符串示例: bolt://[NLB 的新公网 IP]:7687

更多推荐