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
- 集群内访问(应用在 Kubernetes 集群内):
- 注意:客户端必须支持 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(不推荐生产环境)
- 集群内访问(直接连接 Pod):
- 注意: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
- 集群内访问(直连 Pod):
7. 其他服务
- EFAK (Kafka 监控):
- 访问地址:
http://<Kubernetes节点IP>:30448(对应efak-service的 NodePort)
- 访问地址:
- KubePi (Kubernetes 管理面板):
- 访问地址:
http://<Kubernetes节点IP>:30081(对应kubepi-service的 NodePort)
- 访问地址:
通用原则
- 集群内访问优先使用 DNS 名称:
通过<service-name>.<namespace>.svc.cluster.local访问,避免硬编码 IP。 - 有状态服务使用 Headless Service:
如 Redis、ZooKeeper、Kafka 等需要直接连接节点的服务。 - 外部访问通过 NodePort 或 Ingress:
生产环境建议使用 Ingress + 域名 + TLS 证书。 - 避免暴露敏感端口:
如 MySQL 的 NodePort 应限制访问 IP 范围。
二、对于 Redis、ZooKeeper、Kafka 等分布式服务,直接连接节点而非依赖负载均衡是更优的选择,主要原因如下:
1. 数据分片与重定向机制
-
Redis 集群:
- 数据通过哈希槽(Hash Slot)分布在多个节点。客户端请求若命中错误节点,会收到
MOVED重定向响应。 - 负载均衡问题:若客户端通过负载均衡器随机连接节点,可能导致大量重定向请求,增加延迟和复杂度。
- 直接连接优势:客户端缓存集群拓扑后,可直连正确节点,减少中间跳转。
- 数据通过哈希槽(Hash Slot)分布在多个节点。客户端请求若命中错误节点,会收到
-
Kafka:
- 数据按分区(Partition)分布在多个 Broker。生产者和消费者需知道分区 Leader 节点地址。
- 负载均衡问题:负载均衡器无法感知分区分布,可能导致消息发送到非 Leader 节点,引发错误或性能下降。
- 直接连接优势:客户端直接与 Leader 通信,确保高效读写。
2. 客户端拓扑感知与动态更新
-
ZooKeeper:
- 客户端需维护所有节点列表,以便在 Leader 故障时快速切换。
- 负载均衡问题:负载均衡器可能隐藏后端节点状态,客户端无法及时感知节点变化(如 Leader 选举)。
- 直接连接优势:客户端通过心跳检测节点健康状态,动态更新可用节点列表。
-
Redis 与 Kafka:
- 客户端通过集群元数据(如 Redis 的
CLUSTER NODES、Kafka 的Metadata)主动维护拓扑信息。 - 负载均衡问题:负载均衡器无法传递动态元数据,导致客户端无法优化路由。
- 客户端通过集群元数据(如 Redis 的
3. 性能与延迟优化
-
减少网络跳数:
- 直接连接节点可避免负载均衡器的额外转发,降低延迟(尤其是高频访问场景)。
- 示例:Kafka 生产者直连分区 Leader,消息直接写入目标 Broker,无需代理中转。
-
连接池管理:
- 客户端可为每个节点维护独立连接池,复用长连接,减少握手开销。
- 负载均衡问题:负载均衡器通常复用单一连接池,无法针对不同节点优化。
4. 故障处理与高可用
-
客户端重试逻辑:
- 当节点故障时,客户端可根据拓扑信息快速切换到其他节点(如 Redis 的
ASK重定向、Kafka 的Leader 切换)。 - 负载均衡问题:负载均衡器的健康检查可能滞后,导致客户端持续连接故障节点。
- 当节点故障时,客户端可根据拓扑信息快速切换到其他节点(如 Redis 的
-
服务发现:
- 直接依赖服务发现机制(如 DNS SRV 记录、Kubernetes Headless Service)动态获取节点列表。
- 负载均衡问题:静态负载均衡配置无法适应动态扩缩容。
5. 协议与客户端支持
-
集群协议依赖:
- Redis Cluster、Kafka Protocol 等设计均要求客户端理解集群拓扑。
- 负载均衡限制:通用负载均衡器(如 Nginx、HAProxy)无法解析应用层协议(如 Redis 的
MOVED响应),导致协议不兼容。
-
客户端能力:
- 成熟的客户端库(如 Lettuce、Kafka Client)已内置集群路由逻辑,无需依赖外部负载均衡。
例外场景与替代方案
虽然直接连接是主流方案,但在以下场景可谨慎使用负载均衡:
- 无状态服务接入层:
- 如 Redis 代理(Twemproxy、Redis Cluster Proxy)或 Kafka REST Proxy,对外提供负载均衡入口。
- 简化客户端逻辑:
- 当客户端无法处理集群协议时,通过代理隐藏复杂性(性能会有损耗)。
- 边缘服务访问:
- 外部系统通过 Ingress 或 API Gateway 访问集群,需负载均衡暴露统一端点。
总结
- 核心原因:Redis、ZooKeeper、Kafka 等服务的分布式协议和客户端逻辑要求直接感知节点信息。
- 优势:减少延迟、优化路由、快速故障恢复、避免协议冲突。
- 替代方案:仅在客户端不支持集群协议或需要简化接入时使用负载均衡,但需接受性能折损。

浙公网安备 33010602011771号