Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ISPN-15708 Refactor Infinispan Embedded Kubernetes tutorial #193

Merged
merged 1 commit into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
Add {brandname} as a dependency to your Java project and use embedded caches that increase application performance and give you capabilities to handle complex use cases.

include::{topics}/ref_embedded_tutorials.adoc[leveloffset=+1]
include::{topics}/ref_embedded_kubernetes_tutorial.adoc[leveloffset=+1]

// Restore the parent context.
ifdef::parent-context[:context: {parent-context}]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
[id='embedded-kubernetes_tutorial_{context}']
= Kubernetes and Openshift tutorial

This tutorial contains instructions on how to run Infinispan library mode (as a microservice) in Kubernetes/OpenShift.

Prerequisites: Maven and Docker daemon running in the background.

[discrete]
== Prerequisites

- A running Openshift or Kubernetes cluster

[discrete]
== Building the tutorial

This tutorial is built using the maven command:

[source,bash]
----
mvn package
----

Note that `target/` directory contains additional directories like `docker` (with generated Dockerfile) and `classes/META-INF/jkube` with Kubernetes and OpenShift deployment templates.

TIP: If the Docker Daemon is down, the build will omit processing Dockerfiles. Use `docker` profile to turn it on manually.

[discrete]
== Deploying the tutorial to Kubernetes

This is handle by the JKube maven plugin, just invoke:

[source,bash]
----
mvn k8s:build k8s:push k8s:resource k8s:apply -Doptions.image=<IMAGE_NAME> # <1>
----
<1> `IMAGE_NAME` must be replaced with the FQN of the container to deploy to Kubernetes. This container must be created
in a repository that you have permissions to push to and is accessible from within your Kubernetes cluster.

[discrete]
== Viewing and scaling up

Everything should be up and running at this point. Now login into the OpenShift or Kubernetes cluster and scale the application

[source,bash]
----
kubectl scale --replicas=3 deployment/$(kubectl get rs --namespace=myproject | grep infinispan | awk '{print $1}') --namespace=myproject
----

[discrete]
== Undeploying the tutorial

This is handled by the JKube maven plugin, just invoke:

```
mvn k8s:undeploy
```
79 changes: 0 additions & 79 deletions infinispan-embedded/kubernetes/README.adoc

This file was deleted.

94 changes: 66 additions & 28 deletions infinispan-embedded/kubernetes/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,18 @@
<name>Infinispan Simple Tutorials: Kubernetes</name>

<properties>
<!-- Project name used in the OpenShift -->
<fabric8.namespace>myproject</fabric8.namespace>
<!-- This let's you debug a local container -->
<!-- The FQN of the docker image used by the application -->
<options.image>infinispan/${project.artifactId}:${project.version}</options.image>
<!-- The name of the headless service used by DNS_PING to determine cluster members -->
<options.service>myservice</options.service>
<!-- Kubernetes namespace which the application is deployed to -->
<options.namespace>myproject</options.namespace>
<!-- Allows the container to be debugged -->
<options.debug>-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8787</options.debug>
<!-- Not sure, what's your configuration, so let's use IPv4 just in case -->
<options.useIPv4>-Djava.net.preferIPv4Stack=true</options.useIPv4>
<!-- This allows redeploying when using Fabric8 Maven Plugin -->
<fabric8.openshift.trimImageInContainerSpec>true</fabric8.openshift.trimImageInContainerSpec>
<!-- This is how we tell JGroups DNS_PING which service it should use to resolve cluster members -->
<options.dnsPing>-Djgroups.dns.query=${options.service}.${options.namespace}.svc.cluster.local</options.dnsPing>
</properties>

<profiles>
Expand All @@ -33,8 +37,8 @@
<build>
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>fabric8-maven-plugin</artifactId>
<groupId>org.eclipse.jkube</groupId>
<artifactId>kubernetes-maven-plugin</artifactId>
<executions>
<execution>
<goals>
Expand All @@ -53,41 +57,75 @@
<pluginManagement>
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>fabric8-maven-plugin</artifactId>
<version>4.4.2</version>
<groupId>org.eclipse.jkube</groupId>
<artifactId>kubernetes-maven-plugin</artifactId>
<version>1.15.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>fabric8-maven-plugin</artifactId>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.infinispan.tutorial.simple.kubernetes.InfinispanKubernetes</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.eclipse.jkube</groupId>
<artifactId>kubernetes-maven-plugin</artifactId>
<configuration>
<images>
<image>
<name>infinispan/${project.artifactId}:${project.version}</name>
<name>${options.image}</name>
<alias>infinispan</alias>
<build>
<from>fabric8/s2i-java:2.0</from>
<assembly>
<basedir>/deployments</basedir>
<descriptorRef>artifact-with-dependencies</descriptorRef>
</assembly>
<ports>
<!-- KUBE_PING requires exposing ping port -->
<port>8888</port>
</ports>
<from>registry.access.redhat.com/ubi9/openjdk-21-runtime</from>
<env>
<!-- This is how we tell KUBE_PING in which project it should operate -->
<OPENSHIFT_KUBE_PING_NAMESPACE>${fabric8.namespace}</OPENSHIFT_KUBE_PING_NAMESPACE>
<JAVA_MAIN_CLASS>org.infinispan.tutorial.simple.kubernetes.InfinispanKubernetes</JAVA_MAIN_CLASS>
<JAVA_OPTIONS>${options.debug} ${options.useIPv4}</JAVA_OPTIONS>
<JAVA_APP_JAR>/maven/${project.artifactId}-${project.version}.jar</JAVA_APP_JAR>
<JAVA_OPTS>${options.debug} ${options.useIPv4} ${options.dnsPing}</JAVA_OPTS>
</env>
</build>
</image>
</images>
<!-- We are not interested in creating any services -->
<ignoreServices>true</ignoreServices>
<namespace>${options.namespace}</namespace>
<resources>
<controller>
<controllerName>embedded-infinispan</controllerName>
<imagePullPolicy>Always</imagePullPolicy>
<replicas>2</replicas>
</controller>
<services>
<service>
<name>${options.service}</name>
<headless>true</headless>
<ports>
<port>
<port>8888</port>
<targetPort>8888</targetPort>
</port>
</ports>
</service>
</services>
</resources>
</configuration>
</plugin>
</plugins>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
package org.infinispan.tutorial.simple.kubernetes;

import java.io.IOException;
import java.net.Inet4Address;
import java.time.Instant;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.infinispan.Cache;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.Configuration;
Expand All @@ -8,51 +15,46 @@
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
import org.infinispan.manager.DefaultCacheManager;

import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.time.Instant;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class InfinispanKubernetes {

public static void main(String[] args) throws UnknownHostException {
public static void main(String[] args) {
System.out.println("Starting Embedded Infinispan Application...");
//Configure Infinispan to use default transport and Kubernetes configuration
GlobalConfiguration globalConfig = new GlobalConfigurationBuilder().defaultCacheName("defaultCacheName")
GlobalConfiguration globalConfig = new GlobalConfigurationBuilder()
.transport()
.defaultTransport()
.addProperty("configurationFile", "default-configs/default-jgroups-kubernetes.xml")
.build();


// We need a distributed cache for the purpose of this demo
Configuration cacheConfiguration = new ConfigurationBuilder()
.clustering()
.cacheMode(CacheMode.REPL_SYNC)
.build();

DefaultCacheManager cacheManager = new DefaultCacheManager(globalConfig, cacheConfiguration);
cacheManager.defineConfiguration("default", cacheConfiguration);
Cache<String, String> cache = cacheManager.getCache("default");

//Each cluster member will update its own entry in the cache
String hostname = Inet4Address.getLocalHost().getHostName();
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> {
String time = Instant.now().toString();
cache.put(hostname, time);
System.out.println("[" + time + "][" + hostname + "] Values from the cache: ");
System.out.println(cache.entrySet());
},
0, 2, TimeUnit.SECONDS);

try {
//This container will operate for an hour and then it will die
TimeUnit.HOURS.sleep(1);
} catch (InterruptedException e) {
scheduler.shutdown();
cacheManager.stop();
try (DefaultCacheManager cacheManager = new DefaultCacheManager(globalConfig)) {
// We need a distributed cache for the purpose of this demo
Configuration cacheConfiguration = new ConfigurationBuilder()
.clustering()
.cacheMode(CacheMode.REPL_SYNC)
.build();

Cache<String, String> cache = cacheManager.createCache("kubernetes", cacheConfiguration);

// Each cluster member will update its own entry in the cache
String hostname = Inet4Address.getLocalHost().getHostName();
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> {
String time = Instant.now().toString();
cache.put(hostname, time);
System.out.println("[" + time + "][" + hostname + "] Values from the cache: ");
System.out.println(cache.entrySet());
},
0, 2, TimeUnit.SECONDS);

try {
// Execute indefinitely until the process is interrupted by Kubernetes
Thread.currentThread().join();
} catch (InterruptedException e) {
scheduler.shutdown();
cacheManager.stop();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}