k8s中集群内访问​和集群外访问​两种场景说明

一、针对不同中间件的 ​业务服务器连接推荐方案,分为 ​集群内访问​ 和 ​集群外访问​ 两种场景:


1. Redis 集群(redis-clu-9 命名空间)​

  • Service:
    • redis-service (Headless, ClusterIP: None)
    • redis-cluster-access-service (NodePort)
  • 推荐方式
    • 集群内访问​(应用在 Kubernetes 集群内):
      yaml
       
      spring:
        redis:
          cluster:
            nodes:
              - redis-0.redis-service.redis-clu-9.svc.cluster.local:6379
              - redis-1.redis-service.redis-clu-9.svc.cluster.local:6379
              - redis-2.redis-service.redis-clu-9.svc.cluster.local:6379
          lettuce:
            cluster:
              refresh:
                adaptive: true  # 自动处理重定向
    • 集群外访问​(应用在 Kubernetes 集群外):
      yaml
       
      spring:
        redis:
          cluster:
            nodes: <Kubernetes节点IP>:32702  # 对应 redis-cluster-access-service 的 NodePort
  • 注意:客户端必须支持 Redis 集群模式(如 Lettuce 或 Jedis 集群模式)。

2. ZooKeeper 集群(zk 命名空间)​

  • Service:
    • zk-headless (Headless, ClusterIP: None)
    • zk-service (ClusterIP)
    • zkui (NodePort, ZooKeeper Web UI)
  • 推荐方式
    • 集群内访问​(直接连接 Pod):
      yaml
       
      zookeeper:
        servers: zk-0.zk-headless.zk.svc.cluster.local:2181,zk-1.zk-headless.zk.svc.cluster.local:2181,zk-2.zk-headless.zk.svc.cluster.local:2181
    • 集群外访问
      yaml
       
      zookeeper:
        servers: <Kubernetes节点IP>:32766  # 使用 zkui 的 NodePort(不推荐生产环境)
  • 注意:ZooKeeper 客户端应直接连接所有节点以保障高可用。

3. Kafka 集群(kafka 命名空间)​

  • Service:
    • kafka (Headless, ClusterIP: None)
    • kafka-nodeport (NodePort)
  • 推荐方式
    • 集群内访问​(生产者/消费者在集群内):
      yaml
       
      kafka:
        bootstrap-servers: kafka-0.kafka.kafka.svc.cluster.local:9092,kafka-1.kafka.kafka.svc.cluster.local:9092,kafka-2.kafka.kafka.svc.cluster.local:9092
    • 集群外访问​(生产者/消费者在集群外):
      yaml
       
      kafka:
        bootstrap-servers: <Kubernetes节点IP>:30092  # kafka-nodeport 的 NodePort
  • 注意:外网访问需开放防火墙对 NodePort 30092 的访问。

4. MinIO 对象存储(minio 命名空间)​

  • Service:
    • minio-headless (Headless, ClusterIP: None)
    • minio-svc (NodePort)
  • 推荐方式
    • 集群内访问
      yaml
       
      minio:
        endpoint: http://minio-svc.minio.svc.cluster.local:9000  # 使用 ClusterIP
        accessKey: minioadmin
        secretKey: minioadmin
    • 集群外访问
      yaml
       
      minio:
        endpoint: http://<Kubernetes节点IP>:30002  # minio-svc 的 NodePort
  • 注意:生产环境建议通过 Ingress 暴露 HTTPS 端点。

5. Nacos 注册中心(nacos 命名空间)​

  • Service:
    • nacos-headless (Headless, ClusterIP: None)
    • nacos-service (NodePort)
  • 推荐方式
    • 集群内访问
      yaml
       
      nacos:
        server-addr: nacos-service.nacos.svc.cluster.local:8848  # 使用 ClusterIP
    • 集群外访问​(管理控制台):
      bash
       
      http://<Kubernetes节点IP>:30080  # nacos-service 的 NodePort

6. MySQL 数据库(default 命名空间)​

  • Service:
    • mysql-svc (NodePort, 主库)
    • mysql-s-svc (NodePort, 从库)
  • 推荐方式
    • 集群内访问​(直连 Pod):
      yaml
       
      spring:
        datasource:
          url: jdbc:mysql://mysql-svc.default.svc.cluster.local:3306/db_name
    • 集群外访问
      yaml
       
      spring:
        datasource:
          url: jdbc:mysql://<Kubernetes节点IP>:32700/db_name  # mysql-svc 的 NodePort

7. 其他服务

  • EFAK (Kafka 监控):
    • 访问地址http://<Kubernetes节点IP>:30448 (对应 efak-service 的 NodePort)
  • KubePi (Kubernetes 管理面板):
    • 访问地址http://<Kubernetes节点IP>:30081 (对应 kubepi-service 的 NodePort)

通用原则

  1. 集群内访问优先使用 DNS 名称
    通过 <service-name>.<namespace>.svc.cluster.local 访问,避免硬编码 IP。
  2. 有状态服务使用 Headless Service
    如 Redis、ZooKeeper、Kafka 等需要直接连接节点的服务。
  3. 外部访问通过 NodePort 或 Ingress
    生产环境建议使用 Ingress + 域名 + TLS 证书。
  4. 避免暴露敏感端口
    如 MySQL 的 NodePort 应限制访问 IP 范围。

 

 

二、对于 Redis、ZooKeeper、Kafka 等分布式服务,直接连接节点而非依赖负载均衡是更优的选择,主要原因如下:


1. 数据分片与重定向机制

  • Redis 集群

    • 数据通过哈希槽(Hash Slot)分布在多个节点。客户端请求若命中错误节点,会收到 MOVED 重定向响应。
    • 负载均衡问题:若客户端通过负载均衡器随机连接节点,可能导致大量重定向请求,增加延迟和复杂度。
    • 直接连接优势:客户端缓存集群拓扑后,可直连正确节点,减少中间跳转。
  • Kafka

    • 数据按分区(Partition)分布在多个 Broker。生产者和消费者需知道分区 Leader 节点地址。
    • 负载均衡问题:负载均衡器无法感知分区分布,可能导致消息发送到非 Leader 节点,引发错误或性能下降。
    • 直接连接优势:客户端直接与 Leader 通信,确保高效读写。

2. 客户端拓扑感知与动态更新

  • ZooKeeper

    • 客户端需维护所有节点列表,以便在 Leader 故障时快速切换。
    • 负载均衡问题:负载均衡器可能隐藏后端节点状态,客户端无法及时感知节点变化(如 Leader 选举)。
    • 直接连接优势:客户端通过心跳检测节点健康状态,动态更新可用节点列表。
  • Redis 与 Kafka

    • 客户端通过集群元数据(如 Redis 的 CLUSTER NODES、Kafka 的 Metadata)主动维护拓扑信息。
    • 负载均衡问题:负载均衡器无法传递动态元数据,导致客户端无法优化路由。

3. 性能与延迟优化

  • 减少网络跳数

    • 直接连接节点可避免负载均衡器的额外转发,降低延迟(尤其是高频访问场景)。
    • 示例:Kafka 生产者直连分区 Leader,消息直接写入目标 Broker,无需代理中转。
  • 连接池管理

    • 客户端可为每个节点维护独立连接池,复用长连接,减少握手开销。
    • 负载均衡问题:负载均衡器通常复用单一连接池,无法针对不同节点优化。

4. 故障处理与高可用

  • 客户端重试逻辑

    • 当节点故障时,客户端可根据拓扑信息快速切换到其他节点(如 Redis 的 ASK 重定向、Kafka 的 Leader 切换)。
    • 负载均衡问题:负载均衡器的健康检查可能滞后,导致客户端持续连接故障节点。
  • 服务发现

    • 直接依赖服务发现机制(如 DNS SRV 记录、Kubernetes Headless Service)动态获取节点列表。
    • 负载均衡问题:静态负载均衡配置无法适应动态扩缩容。

5. 协议与客户端支持

  • 集群协议依赖

    • Redis Cluster、Kafka Protocol 等设计均要求客户端理解集群拓扑。
    • 负载均衡限制:通用负载均衡器(如 Nginx、HAProxy)无法解析应用层协议(如 Redis 的 MOVED 响应),导致协议不兼容。
  • 客户端能力

    • 成熟的客户端库(如 Lettuce、Kafka Client)已内置集群路由逻辑,无需依赖外部负载均衡。

例外场景与替代方案

虽然直接连接是主流方案,但在以下场景可谨慎使用负载均衡:

  1. 无状态服务接入层
    • 如 Redis 代理(Twemproxy、Redis Cluster Proxy)或 Kafka REST Proxy,对外提供负载均衡入口。
  2. 简化客户端逻辑
    • 当客户端无法处理集群协议时,通过代理隐藏复杂性(性能会有损耗)。
  3. 边缘服务访问
    • 外部系统通过 Ingress 或 API Gateway 访问集群,需负载均衡暴露统一端点。

总结

  • 核心原因:Redis、ZooKeeper、Kafka 等服务的分布式协议和客户端逻辑要求直接感知节点信息。
  • 优势:减少延迟、优化路由、快速故障恢复、避免协议冲突。
  • 替代方案:仅在客户端不支持集群协议或需要简化接入时使用负载均衡,但需接受性能折损。

 

posted @ 2025-03-05 13:57  Leonardo-li  阅读(347)  评论(0)    收藏  举报