You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hazelcast实例重启后直接访问K8s Pod,如何强制走LoadBalancer外部IP?

问题描述

我在Minikube中部署了一个包含2个成员的Hazelcast集群,并配置了LoadBalancer服务来访问这些成员。部署在Minikube外部的Spring Boot应用通过以下代码初始化Hazelcast实例:

public Config getHazelcastConfig() {
    Config config = new Config("default");

    config.getNetworkConfig().setPort(5701);
    config.getNetworkConfig().setPortCount(1);
    config.getNetworkConfig().setPortAutoIncrement(false);

    config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false);
    config.getNetworkConfig()
            .getJoin()
            .getTcpIpConfig()
            .addMember("external-ip:port")
            .setEnabled(true);
    return config;
}
@Bean
public HazelcastInstance hazelcastInstance() {
    Config config = getHazelcastConfig();
    return Hazelcast.newHazelcastInstance(config);
}

首次重建后启动应用时,能成功将Minikube中的成员加入集群,最终形成3个成员的集群,符合预期。但重启应用后,它会尝试直接使用Kubernetes Pod的私有IP地址访问成员,相关日志如下:

2023-07-02 20:39:16.831  INFO 32243 --- [.IO.thread-in-0] c.h.i.server.tcp.TcpServerConnection     : [10.31.0.28]:5701 [dev] [4.2.1] Initialized new cluster connection between /192.168.105.1:50190 and /10.108.94.145:5701
2023-07-02 20:39:16.898  INFO 32243 --- [cached.thread-3] c.h.i.server.tcp.TcpServerConnector      : [10.31.0.28]:5701 [dev] [4.2.1] Connecting to /10.244.0.2:5701, timeout: 10000, bind-any: true
2023-07-02 20:39:26.902  INFO 32243 --- [cached.thread-3] c.h.i.server.tcp.TcpServerConnector      : [10.31.0.28]:5701 [dev] [4.2.1] Could not connect to: /10.244.0.2:5701. Reason: IOException[null to address /10.244.0.2:5701]
2023-07-02 20:39:26.903  INFO 32243 --- [cached.thread-3] c.h.internal.cluster.impl.TcpIpJoiner    : [10.31.0.28]:5701 [dev] [4.2.1] [10.244.0.2]:5701 is added to the blacklist.
2023-07-02 20:39:36.939  INFO 32243 --- [cached.thread-3] c.h.internal.cluster.impl.TcpIpJoiner    : [10.31.0.28]:5701 [dev] [4.2.1] [10.244.0.2]:5701 is added to the blacklist.

其中IP 10.244.0.2对应某个Kubernetes Pod(集群成员),但我的应用应仅通过LoadBalancer的外部IP访问成员。我不清楚为何它会尝试直接访问Pod。

请问如何强制我的Hazelcast实例始终通过LoadBalancer的外部IP访问成员?

注:我未使用ClientConfig,因为我希望将Kubernetes中部署的成员与Spring Boot应用启动的成员一起加入集群。我已参考官方文档搭建Minikube环境。


解决方案

问题的核心原因是:Hazelcast集群成员会互相交换自身的内部地址信息,外部Spring Boot应用首次加入集群后会记录Minikube中Pod的私有IP,重启后会优先尝试连接这些已记录的地址,而非仅依赖配置的LoadBalancer地址。

可以从以下两个层面配置解决:

1. 让Minikube中的Hazelcast成员对外暴露LoadBalancer地址

在Kubernetes部署Hazelcast时,需要修改成员配置,让它们向集群报告外部可访问的LoadBalancer地址,而非Pod私有IP。

方式一:直接配置Hazelcast参数

通过XML或Java配置设置public-address:

<network>
    <public-address>LOAD_BALANCER_IP:LOAD_BALANCER_PORT</public-address>
    <!-- 其他网络配置 -->
</network>

方式二:通过环境变量传递(适用于使用Kubernetes插件部署的场景)

在Hazelcast Deployment的YAML中添加环境变量:

env:
  - name: HZ_NETWORK_PUBLICADDRESS
    value: "LOAD_BALANCER_IP:LOAD_BALANCER_PORT"

这样Minikube中的Hazelcast成员向集群其他节点报告自身地址时,会发送LoadBalancer的地址,而非私有Pod IP。

2. 限制外部Spring Boot应用仅使用配置的成员地址

在Spring Boot应用的Hazelcast配置中,禁用成员列表自动刷新,强制实例始终使用初始化时配置的LoadBalancer地址:

public Config getHazelcastConfig() {
    Config config = new Config("default");

    // 保留原有配置...

    // 禁用成员列表自动刷新
    config.getNetworkConfig().getJoin().getTcpIpConfig()
            .setMemberListRefreshIntervalSeconds(0);
    config.getProperties().setProperty("hazelcast.cluster.member.list.refresh.interval", "0");
    
    // 可选:启用成员认证,仅信任初始配置的节点
    config.getProperties().setProperty("hazelcast.security.member.authentication.required", "true");

    return config;
}

setMemberListRefreshIntervalSeconds(0)会阻止实例自动从集群获取新的成员地址,确保它始终只使用你配置的LoadBalancer地址进行连接。

补充说明

  • 确保LoadBalancer的端口已正确映射到Hazelcast成员的5701端口,且外部应用可正常访问该端口。
  • 如果Minikube的LoadBalancer IP是动态分配的,可在部署脚本中自动获取IP并注入到Hazelcast的public-address配置中,避免手动维护的麻烦。

内容的提问来源于stack exchange,提问作者Sreyas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 23:55:00