Friday, December 22, 2017

Integration Testing a Java EE Application in the Containerized World Using Kubernetes and the Fabric8 Maven Plugin

Kubernetes is an open-source system for automating deployment, scaling, and management of containerized applications. With Kubernetes, you are able to quickly and efficiently respond to customer demand:

  • Deploy your applications quickly and predictably
  • Scale your applications on the fly
  • Roll out new features seamlessly
  • Limit hardware usage to required resources only

Fabric8 Maven plugin is a one-stop-shop for building and deploying Java applications for Docker, Kubernetes and OpenShift. It brings your Java applications on to Kubernetes and OpenShift. It provides a tight integration into Maven and benefits from the build configuration already provided. It focuses on three tasks:

  • Building Docker images
  • Creating OpenShift and Kubernetes resources
  • Deploy application on Kubernetes and OpenShift

My demo Java EE application uses the Fabric8 Maven plugin as an access point to Kubernetes: the application can be deployed on a WebSphere Liberty-based docker container running inside a Kubernetes cluster and the integration tests run dependent on the containerized application. Since the environment is containerized, any databases, messaging providers or other infrastructure components can be taken into account in the future also using appropriate containers.

The fabric8-maven-plugin configuration for the application:

The docker image for the application is created at build time; the goal resource is responsible for Kubernetes-related artifacts generation while the goal build is responsible for generation the Dockerfile and building the image that contains the application and related WebSphere Liberty artifacts (the server.xml and files). Both goals are included into the Maven build lifecycle.

The Docker image is described in the images/image section of the plugin configuration. The most important parts of the configuration are name - the reference to the built image - and the build - section that is going to be translated into the Dockerfile. The assembly part of the section describes the content of the being built Docker image. The format of the assembly is fully in line with the Assembly Descriptor of the Apache Maven Assembly plugin. The following three files are going to put into the Docker image: a Liberty profile server descriptor (server.xml), a file used by the descriptor for variable substitution and the web-application archive.

The fmp-service enricher is used by the plugin to expose the Liberty profile as a service in Kubernetes. Unlike images/image, enrichers are used to create and customize Kubernetes and OpenShift resource objects. The fmp-service enricher creates a default service if missing; in this case, the enricher exposes the liberty-microprofile-app service bound to port 9080 inside the container. In a strict sense, that enricher defined in liberty-microprofile-app/pom.xml isn't needed at all for the integration tests but I describe it here just for exposing the service during the fabric8:run goal execution and debug.

Also, the plugin is used in a separated module with the integration tests in order to run them:

As you can see, there isn't any build information for the ${docker.user}/ ${applicationArtifactId}:${project.version} Docker image because the image will be built during the liberty-microprofile-app buildcycle, not the liberty-microprofile-app-it one. The enricher defined here is must have for the integration tests: if no service had been exposed, the clients used by the integration tests wouldn't have been able to connect to the application deployed in Kubernetes.

The most important part of the plugin configuration is the executions. There are three executions defined for the plugin: the first one builds Kubernetes-related resources, the second one deploys the Docker images on the Kubernetes cluster and starts them during the pre-integration-test phase of the Maven build lifecycle and the last one halts the images after the execution of the test cases.

The plugin isn't able to generate a value of the nodePort parameter for the exposed service, so a Kubernetes implementation generates a new floating port number for the service after each execution of the fabric8:apply goal. The org.codehaus.gmaven:groovy-maven-plugin is used to get the dynamic bound nodePort value for the container with the demo application:

(The kubectl program must be declared in the environment variable $PATH.)

Unfortunately the fabric8:start command is a background one, so a pause is needed to let the Liberty profile start inside a container. The pause is implemented as a Thread.sleep(pause) call included into the org.codehaus.gmaven:groovy-maven-plugin plugin configuration after the service port number has been gotten.

To run the integration tests do the following commands:

  1. On Windows, please, download gofabric8.exe using

    # mvn fabric8:setup -Pfabric8

  2. If you use minikube, the cluster must be started. To start the cluster use the following command:

    # minikube start

  3. All environment variables must be set before using this plugin, see the instruction generated by:

    # gofabric8 docker-env

  4. Build the docker image for the liberty-microprofile-app application, deploy the image to Kubernetes and run the integration tests:

    # mvn clean verify -Pfabric8 -DtestProxyHost=

    (if you use VirtualBox to run the minikube virtual machine, -DtestProxyHost= helps you specify the virtual machine host.)

The sources of the demo application - liberty-microprofile-demo - can be found on GitHub.

Would you like to give a 'Like'? Please follow me on Twitter!

No comments:

Post a Comment