【发布时间】:2019-03-15 01:18:24
【问题描述】:
为了在 Kubernetes 命名空间中的两个不同服务的 pod 之间共享事件,我打算使用 Hazelcast。这不是问题,但是,每个服务也有一个包含其所有 pod 的集群。
所以,我有两个使用相同 pod 的集群。我通过为其中一个集群设置组名来实现集群的分离,而另一个集群具有默认组配置。这在本地运行良好,具有测试应用程序的多个实例。但是,这是启用了多播。
然而,在 Kubernetes 中,Hazelcast 使用 HazelcastKubernetesDiscoveryStrategy 并禁用了多播。
两个服务都有一个标签:
metadata:
name: service-1
labels:
hazelcast-group: bc-events
metadata:
name: service-2
labels:
hazelcast-group: bc-events
事件集群的 hazelcast 配置如下:
Config hzConfig = new Config("events-instance");
NetworkConfig nwConfig = new NetworkConfig();
JoinConfig joinConfig = new JoinConfig();
joinConfig.setMulticastConfig(new MulticastConfig().setEnabled(false));
joinConfig.setTcpIpConfig(new TcpIpConfig().setEnabled(false));
DiscoveryStrategyConfig k8sDiscoveryStrategy = new DiscoveryStrategyConfig("com.hazelcast.kubernetes.HazelcastKubernetesDiscoveryStrategy");
k8sDiscoveryStrategy.addProperty("namespace", "dev");
k8sDiscoveryStrategy.addProperty("resolve-not-ready-addresses", true);
k8sDiscoveryStrategy.addProperty("service-label-name", "hazelcast-group");
k8sDiscoveryStrategy.addProperty("service-label-value", "bc-events");
DiscoveryConfig discoveryConfig = new DiscoveryConfig();
discoveryConfig.addDiscoveryStrategyConfig(k8sDiscoveryStrategy);
joinConfig.setDiscoveryConfig(discoveryConfig);
nwConfig.setJoin(joinConfig);
hzConfig.setNetworkConfig(nwConfig);
hzConfig.setProperty("hazelcast.discovery.enabled", "true");
GroupConfig groupConfig = new GroupConfig("bc-events");
hzConfig.setGroupConfig(groupConfig);
而共享缓存集群(没有分组的)的配置是这样的(对于服务1,服务2是一样的):
Config hzConfig = new Config("service-1-app-hc");
NetworkConfig nwConfig = new NetworkConfig();
JoinConfig joinConfig = new JoinConfig();
joinConfig.setMulticastConfig(new MulticastConfig().setEnabled(false));
joinConfig.setTcpIpConfig(new TcpIpConfig().setEnabled(false));
DiscoveryStrategyConfig k8sDiscoveryStrategy = new DiscoveryStrategyConfig("com.hazelcast.kubernetes.HazelcastKubernetesDiscoveryStrategy");
k8sDiscoveryStrategy.addProperty("namespace", "dev");
k8sDiscoveryStrategy.addProperty("service-name", "service-1");
k8sDiscoveryStrategy.addProperty("resolve-not-ready-addresses", true);
DiscoveryConfig discoveryConfig = new DiscoveryConfig();
discoveryConfig.addDiscoveryStrategyConfig(k8sDiscoveryStrategy);
joinConfig.setDiscoveryConfig(discoveryConfig);
nwConfig.setJoin(joinConfig);
hzConfig.setNetworkConfig(nwConfig);
hzConfig.setProperty("hazelcast.discovery.enabled", "true");
hazelcast 实例找到彼此,但随后抱怨对方有不同的组名并将 IP 列入黑名单。
在调试代码时,在处理加入请求的配置验证期间,它会尝试比较组名(bc-events 与 dev),显然这是不同的。但随后这会被列入黑名单(我相信),从而阻止对具有相同组名的另一个实例进行验证检查。
我不确定下一步该去哪里。我无法在本地测试此配置,因为没有多播,它找不到用于加入集群的其他节点。我也不认为配置有什么问题。
使用的库是:
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast</artifactId>
<version>3.7.8</version>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-kubernetes</artifactId>
<version>1.1.0</version>
</dependency>
更新:
我应该注意到,当前的设置,具有组名称的集群通过服务名称发现(因此,它只包含一个服务的 pod)实际上是有效的。没有组的集群和有组的集群并排运行。只有当我切换到基于标签的发现(并且涉及其他服务)时,它才会中断。
更新:
当更改事件集群的端口时,我注意到它仍然尝试连接到 5701(默认),尽管它被放在 5801 上。当然这可行,因为第一个集群在 5701 上运行。在 HazelcastKubernetesDiscoveryStrategy 里面有以下方法:
protected int getServicePort(Map<String, Object> properties) {
int port = NetworkConfig.DEFAULT_PORT;
if (properties != null) {
String servicePort = (String) properties.get(HAZELCAST_SERVICE_PORT);
if (servicePort != null) {
port = Integer.parseInt(servicePort);
}
}
return port;
}
此方法检查为 Kubernetes 客户端返回的每个端点返回的附加属性,以获取 hazelcast 端口配置。如果不存在,它使用默认的 5701。我猜这是需要配置的,但是它不能影响其他集群,所以我可能不得不用我自己的一些逻辑来扩展策略。
【问题讨论】:
-
您是否在单个 POD 上运行多个 Hazelcast 实例(成员)?您能否详细说明“我有两个使用相同 pod 的集群”?
-
是的。 1 个 pod 上的多个 hazelcast 实例。基本上,有一个集群在同一服务的所有 pod 之间共享缓存,然后有另一个集群在每个服务的所有具有特定标签的 pod 之间共享事件。第一个集群没有组名(默认 = dev),事件集群有一个“bc-events”组名。有几个错误显示“不同的组名”或“不同的集群组”。我更改了事件集群的端口,并从中发现了可能的线索。请参阅问题答案以获取更新。
-
我真正想要的是一个单独的集群,服务可以加入(通过标签)如果他们想接听事件,同时离开他们可能单独拥有的任何其他集群。
标签: java kubernetes hazelcast