kubernetesvert.xinfinispan

Infinispan dual roles on Kubernetes as a Vert.x cluster manager and cache manager. Cache not being shared problem


The goal of the project is to wire up Vert.x applications(verticles) in a cluster with the help of Infinispan, where verticles share single replicated cache collection, which is also managed by Infinispan.

I can see the Infinispan's cluster management feature functioning fine when deployed on k8s. Below is the deployment information on kubernetes.

root@vertx-ollama-control-plane:/# kubectl get all
NAME                                       READY   STATUS    RESTARTS        AGE
pod/backend-deployment-9dd7d994c-d6w5m     1/1     Running   1 (7m34s ago)   8m13s
pod/backend-deployment-9dd7d994c-d7ttq     1/1     Running   0               8m13s
pod/backend-deployment-9dd7d994c-zgjhx     1/1     Running   1 (7m34s ago)   8m13s
pod/frontend-deployment-6557dd4466-bf2gj   1/1     Running   0               8m13s
pod/frontend-deployment-6557dd4466-f6fqz   1/1     Running   0               8m13s
pod/ollama-858d4f8c8d-fggwb                1/1     Running   0               8m13s

NAME                    TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/clustered-app   ClusterIP      None            <none>        7800/TCP       8m13s
service/frontend        LoadBalancer   10.96.229.141   <pending>     80:32375/TCP   8m13s
service/kubernetes      ClusterIP      10.96.0.1       <none>        443/TCP        3h26m
service/ollama          ClusterIP      10.96.54.50     <none>        11434/TCP      8m13s

NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/backend-deployment    3/3     3            3           8m13s
deployment.apps/frontend-deployment   2/2     2            2           8m13s
deployment.apps/ollama                1/1     1            1           8m13s

NAME                                             DESIRED   CURRENT   READY   AGE
replicaset.apps/backend-deployment-9dd7d994c     3         3         3       8m13s
replicaset.apps/frontend-deployment-6557dd4466   2         2         2       8m13s
replicaset.apps/ollama-858d4f8c8d                1         1         1       8m13s

And the exposed ip addresses of verticles through the headless service are here:

root@vertx-ollama-control-plane:/# kubectl get endpoints
NAME            ENDPOINTS                                                        AGE
clustered-app   10.244.0.80:7800,10.244.0.81:7800,10.244.0.82:7800 + 2 more...   9m16s
frontend        10.244.0.83:8080,10.244.0.84:8080                                9m16s
kubernetes      172.18.0.4:6443                                                  3h27m
ollama          10.244.0.79:11434                                                9m16s

But the problem is that Pods do not share the cache of Infinispan (with the name of "embeddings"), rather have their own local collection. Here's some configuration and code I tried to manage the shared cache over cluster.


        // Configure default cache manager
        DefaultCacheManager cacheManager = new DefaultCacheManager(
                new GlobalConfigurationBuilder()
                        .transport()
                        .defaultTransport()
                        .build()
        );
        clusterManager = new InfinispanClusterManager(cacheManager);

        // Configure the cache for embeddings
        Configuration cacheConfig = new ConfigurationBuilder().clustering()
                .cacheMode(CacheMode.REPL_ASYNC)
                .encoding()
                .mediaType(MediaType.APPLICATION_OBJECT_TYPE)
                .build();
        
        ... 

        if (cacheManager.cacheExists("embeddings")) {
            logger.info(String.format("Cache %s exists with the hashcode of %d on %s node.",
                    "embeddings",
                    cacheManager.getCache("embeddings").hashCode(),
                    cacheManager.getNodeAddress())
            );
            collection = cacheManager.getCache("embeddings");
        } else {
            logger.info(String.format("Cache %s does not exist, a new cache is created on %s node.",
                    "embeddings",
                    cacheManager.getNodeAddress()
            ));
            collection = cacheManager.createCache("embeddings", cacheConfig);
        }

    // ...

    public static void main(String[] args) {
        Vertx.clusteredVertx(new VertxOptions().setClusterManager(clusterManager))
                .compose(v -> v.deployVerticle(new Main()))
                .onFailure(Throwable::printStackTrace);
    }

I am injecting the Jgroup Kubernetes xml config file as environment when deploying the pod like -Dvertx.jgroups.config=default-configs/default-jgroups-kubernetes.xml.


However, when storing embedding information in the Infinispan cache multiple times, I notice that each pod creates its own cache named 'embeddings.'

http POST :8080/embed prompt="Llamas are members of the camelid family meaning they're pretty closely related to vicuñas and camels"
HTTP/1.1 200 OK
content-length: 105

Embedding entry stored with key: 451439790
From: backend-deployment-9dd7d994c-zgjhx (Collection Size: 1)

...**(logs from the Pod A)** 
Dec 14, 2024 4:10:26 AM cynicdog.io.api.OllamaAPI
INFO: **Cache embeddings does not exist**, a new cache is created on backend-deployment-9dd7d994c-d6w5m-37175 node
http POST :8080/embed prompt="Llamas are members of the camelid family meaning they're pretty closely related to vicuñas and camels"
HTTP/1.1 200 OK
content-length: 105

Embedding entry stored with key: 451439790
From: backend-deployment-9dd7d994c-d6w5m (Collection Size: 1)

...**(logs from the Pod B) **
INFO: Model mxbai-embed-large:latest pulled.
Dec 14, 2024 4:10:26 AM cynicdog.io.api.OllamaAPI
INFO: **Cache embeddings does not exist**, a new cache is created on backend-deployment-9dd7d994c-d6w5m-37175 node.

Is there anything I'm missing? I'm attaching the project GitHub repository if needed for detailed inspection :(

https://github.com/CynicDog/Vertx-Kubernetes-Integration/tree/main/clustered-embedding-stores


Solution

  • When you create a cluster manager using a custom cache manager, this cache manager must be configured with the required caches:

    <cache-container default-cache="distributed-cache">
     <distributed-cache name="distributed-cache"/>
     <replicated-cache name="__vertx.subs"/>
     <replicated-cache name="__vertx.haInfo"/>
     <replicated-cache name="__vertx.nodeInfo"/>
     <distributed-cache-configuration name="__vertx.distributed.cache.configuration"/>
    </cache-container>
    

    This is XML configuration but you should be able to do the same programmatically.

    Secondly, you must follow the steps for configuring Infinispan on K8S

    But note that, as indicated in the comments, the vertx.jgroups.config is ignored when the cluster manager is created with a custom cache manager.

    So you must configure the JGroups programmatically.