java - kubernetes 中两个独立的 hazelcast 集群

标签 java kubernetes hazelcast

为了在 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-eventsdev),显然这是不同的。但随后这会被列入黑名单(我相信),从而阻止对具有相同组名的其他实例进行验证检查。

我不知道下一步该去哪里。我无法在本地测试此配置,因为如果没有多播,它无法找到用于加入集群的其他节点。我也不认为配置有什么问题。

使用的库是:

<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。我猜这是需要配置的,但是,它不能影响其他集群,所以我可能必须用我自己的一些逻辑来扩展该策略。

最佳答案

可以将多个 Hazelcast 实例嵌入到部署在单个 POD 中的应用程序中。然后,您可以控制集群的形成方式。它需要额外的配置,但您不必修改 HazelcastKubernetesDiscoveryStrategy

示例应用程序

我创建了一个示例应用程序来展示它的工作原理。请在这里查看:https://github.com/leszko/hazelcast-code-samples/tree/kubernetes-embedded-multiple/hazelcast-integration/kubernetes/samples/embedded .

配置步骤

Hazelcast 配置

您的应用程序中有两个 Hazelcast 实例,因此您需要指定它们使用的端口。另外,使用 hazelcast-kubernetes 的参数插件,您可以配置哪些 Hazelcast 实例一起形成集群。

例如,假设第一个 Hazelcast 实例应与当前 Kubernetes 命名空间中的所有其他 Hazelcast 实例形成一个集群,其配置如下所示。

Config config = new Config();
config.getNetworkConfig().setPort(5701);
config.getProperties().setProperty("hazelcast.discovery.enabled", "true");
JoinConfig joinConfig = config.getNetworkConfig().getJoin();
joinConfig.getMulticastConfig().setEnabled(false);

HazelcastKubernetesDiscoveryStrategyFactory discoveryStrategyFactory = new HazelcastKubernetesDiscoveryStrategyFactory();
Map<String, Comparable> properties = new HashMap<>();
joinConfig.getDiscoveryConfig().addDiscoveryStrategyConfig(new DiscoveryStrategyConfig(discoveryStrategyFactory, properties));

然后,第二个 Hazelcast 实例只能使用相同的应用程序来形成集群。我们可以通过为它提供一个带有环境变量值的 service-name 参数来实现这种分离。

Config config = new Config();
config.getNetworkConfig().setPort(5702);
config.getProperties().setProperty("hazelcast.discovery.enabled", "true");
JoinConfig joinConfig = config.getNetworkConfig().getJoin();
joinConfig.getMulticastConfig().setEnabled(false);

HazelcastKubernetesDiscoveryStrategyFactory discoveryStrategyFactory = new HazelcastKubernetesDiscoveryStrategyFactory();
Map<String, Comparable> properties = new HashMap<>();
String serviceName = System.getenv("KUBERNETES_SERVICE_NAME");
properties.put("service-name", serviceName);
properties.put("service-port", "5702");
joinConfig.getDiscoveryConfig().addDiscoveryStrategyConfig(new DiscoveryStrategyConfig(discoveryStrategyFactory, properties));

GroupConfig groupConfig = new GroupConfig("separate");

Kubernetes 模板

然后,在 Kubernetes 部署模板中,您需要配置两个端口:57015702

ports:
- containerPort: 5701
- containerPort: 5702

以及带有服务名称的环境变量:

env:
- name: KUBERNETES_SERVICE_NAME
  value: hazelcast-separate-1

此外,您需要为每个 Hazelcast 实例创建两个服务。

kind: Service
metadata:
  name: hazelcast-shared-1
spec:
  type: ClusterIP
  selector:
    app: hazelcast-app
  ports:
  - name: hazelcast-shared
    port: 5701

kind: Service
metadata:
  name: hazelcast-separate-1
spec:
  type: ClusterIP
  selector:
    app: hazelcast-app
  ports:
  - name: hazelcast-separate
  port: 5702

显然,以同样的方式,您可以使用服务标签而不是服务名称来分隔 Hazelcast 集群。

关于java - kubernetes 中两个独立的 hazelcast 集群,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52734960/

相关文章:

java - 使用 Hazelcast/Redis 满足数据库支持的缓存需求

java - 如何在 Java 中生成 xml?

java - RxJava : How to extract object from observable?

kubernetes - 图片垃圾收集失败:无法找到容器/的数据

kubernetes RBAC DENY 不阻止访问

hazelcast - 服务器重启时 Hazelcast 客户端重新连接时出错

java - Hazelcast - 通用 map 配置

java - 将 Mat 中的图像转换为 BufferedImage

java - 工厂设计模式——不使用静态方法,因为单元测试是个问题

kubernetes - 从私有(private)注册表中提取镜像失败 - ImagePullBackOff