代码之家  ›  专栏  ›  技术社区  ›  Limnic

库伯内特斯的两个独立的榛铸件团

  •  1
  • Limnic  · 技术社区  · 7 年前

    为了在Kubernetes命名空间中的两个不同服务的pod之间共享事件,我打算使用Hazelcast。这不是问题,但是,每个服务都有一个包含其所有pod的集群。

    所以,我有两个集群使用相同的豆荚。我通过为其中一个集群设置组名来实现集群的分离,而另一个集群具有默认的组配置。对于一个测试应用程序的多个实例,这在本地工作得很好。但是,这是在启用多播的情况下进行的。

    然而,在库伯内特斯,黑兹卡斯特使用 HazelcastKubernetesDiscoveryStrategy 已禁用多播。

    两种服务都有一个标签:

    metadata:
      name: service-1
      labels:
        hazelcast-group: bc-events
    
    metadata:
      name: service-2
      labels:
        hazelcast-group: bc-events
    

    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上 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;
    }
    

    对于hazelcast端口配置,此方法检查kubernetes客户端返回的每个端点的其他属性。如果不存在,它使用默认的5701。我猜这是需要配置的,但是,它不能影响其他集群,所以我可能必须用我自己的一些逻辑来扩展策略。

    1 回复  |  直到 7 年前
        1
  •  2
  •   Rafał Leszko    7 年前

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

    示例应用程序

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

    配置步骤

    应用程序中有两个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部署模板中,需要配置两个端口: 5701 5702

    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集群。