Manually deploy a Java application with Open Liberty or WebSphere Liberty on an Azure Kubernetes Service (AKS) cluster

This article demonstrates how to:

  • Run your Java, Java EE, Jakarta EE, or MicroProfile application on the Open Liberty or WebSphere Liberty runtime.
  • Build the application Docker image using Liberty container images.
  • Deploy the containerized application to an AKS cluster using the Open Liberty Operator.

The Open Liberty Operator simplifies the deployment and management of applications running on Kubernetes clusters. With the Open Liberty Operator, you can also perform more advanced operations, such as gathering traces and dumps.

For more information on Open Liberty, see the Open Liberty project page. For more information on IBM WebSphere Liberty, see the WebSphere Liberty product page.

This article is step-by-step manual guidance for running Open/WebSphere Liberty on Azure. For a more automated solution that accelerates your journey to AKS, see Deploy a Java application with Open Liberty/WebSphere Liberty on an Azure Kubernetes Service (AKS) cluster.

If you don't have an Azure subscription, create a free account before you begin.

Prerequisites

  • Use Azure Cloud Shell using the bash environment.

    Launch Cloud Shell in a new window

  • If you prefer, install the Azure CLI to run CLI reference commands.

    • If you're using a local install, sign in with Azure CLI by using the az login command. To finish the authentication process, follow the steps displayed in your terminal. See Sign in with Azure CLI for additional sign-in options.
    • When you're prompted, install Azure CLI extensions on first use. For more information about extensions, see Use extensions with Azure CLI.
    • Run az version to find the version and dependent libraries that are installed. To upgrade to the latest version, run az upgrade.
  • This article requires at least version 2.31.0 of Azure CLI. If using Azure Cloud Shell, the latest version is already installed.
  • If running the commands in this guide locally (instead of Azure Cloud Shell):
    • Prepare a local machine with Unix-like operating system installed (for example, Ubuntu, macOS, Windows Subsystem for Linux).
    • Install a Java SE implementation (for example, Eclipse Open J9).
    • Install Maven 3.5.0 or higher.
    • Install Docker for your OS.
  • Make sure you have been assigned either the Owner role or the Contributor and User Access Administrator roles in the subscription. You can verify the assignment by following the steps in List Azure role assignments using the Azure portal.

Create a resource group

An Azure resource group is a logical group in which Azure resources are deployed and managed.

Create a resource group called java-liberty-project using the az group create command in the eastus location. This resource group will be used later for creating the Azure Container Registry (ACR) instance and the AKS cluster.

export RESOURCE_GROUP_NAME=java-liberty-project
az group create --name $RESOURCE_GROUP_NAME --location eastus
az configure --defaults group=$RESOURCE_GROUP_NAME

Create an ACR instance

Use the az acr create command to create the ACR instance. The following example creates an ACR instance named youruniqueacrname. Make sure youruniqueacrname is unique within Azure.

export REGISTRY_NAME=youruniqueacrname
az acr create --resource-group $RESOURCE_GROUP_NAME --name $REGISTRY_NAME --sku Basic --admin-enabled

After a short time, you should see a JSON output that contains:

  "provisioningState": "Succeeded",
  "publicNetworkAccess": "Enabled",
  "resourceGroup": "java-liberty-project",

Connect to the ACR instance

You'll need to sign in to the ACR instance before you can push an image to it. Run the following commands to verify the connection:

export LOGIN_SERVER=$(az acr show -n $REGISTRY_NAME --query 'loginServer' -o tsv)
export USER_NAME=$(az acr credential show -n $REGISTRY_NAME --query 'username' -o tsv)
export PASSWORD=$(az acr credential show -n $REGISTRY_NAME --query 'passwords[0].value' -o tsv)

docker login $LOGIN_SERVER -u $USER_NAME -p $PASSWORD

You should see Login Succeeded at the end of command output if you've logged into the ACR instance successfully.

Create an AKS cluster

Use the az aks create command to create an AKS cluster. The following example creates a cluster named myAKSCluster with one node. This command will take several minutes to complete.

export CLUSTER_NAME=myAKSCluster
az aks create --resource-group $RESOURCE_GROUP_NAME --name $CLUSTER_NAME --node-count 1 --generate-ssh-keys --enable-managed-identity

After a few minutes, the command completes and returns JSON-formatted information about the cluster, including the following output:

  "nodeResourceGroup": "MC_java-liberty-project_myAKSCluster_eastus",
  "privateFqdn": null,
  "provisioningState": "Succeeded",
  "resourceGroup": "java-liberty-project",

Connect to the AKS cluster

To manage a Kubernetes cluster, you use kubectl, the Kubernetes command-line client. If you use Azure Cloud Shell, kubectl is already installed. To install kubectl locally, use the az aks install-cli command:

az aks install-cli

To configure kubectl to connect to your Kubernetes cluster, use the az aks get-credentials command. This command downloads credentials and configures the Kubernetes CLI to use them.

az aks get-credentials --resource-group $RESOURCE_GROUP_NAME --name $CLUSTER_NAME --overwrite-existing --admin

Note

The above command uses the default location for the Kubernetes configuration file, which is ~/.kube/config. You can specify a different location for your Kubernetes configuration file using --file.

To verify the connection to your cluster, use the kubectl get command to return a list of the cluster nodes.

kubectl get nodes

The following example output shows the single node created in the previous steps. Make sure that the status of the node is Ready:

NAME                                STATUS   ROLES   AGE     VERSION
aks-nodepool1-xxxxxxxx-yyyyyyyyyy   Ready    agent   76s     v1.23.8

Create an Azure SQL Database

The steps in this section guide you through creating an Azure SQL Database single database for use with your app.

  1. Create a single database in Azure SQL Database by following the steps in: Quickstart: Create an Azure SQL Database single database, carefully noting the differences in the box below. Return to this document after creating and configuring the database server.

    Note

    • At the Basics step, write down Resource group, Database name, Server name.database.windows.net, Server admin login and Password. The database Resource group will be referred to as <db-resource-group> later in this article.

    • At the Networking step, set Connectivity method to Public endpoint, Allow Azure services and resources to access this server to Yes, and Add current client IP address to Yes.

      Screenshot of configuring SQL database networking.

    • Also at the Networking step, under Encrypted connections, set the Minimum TLS version to TLS 1.0.

      Screenshot of configuring SQL database networking TLS 1.0.

Now that the database and AKS cluster have been created, we can proceed to preparing AKS to host Open Liberty.

Install Open Liberty Operator

After creating and connecting to the cluster, install the Open Liberty Operator by running the following commands.

# Install Open Liberty Operator
export OPERATOR_VERSION=0.8.2
mkdir -p overlays/watch-all-namespaces
wget https://raw.githubusercontent.com/OpenLiberty/open-liberty-operator/main/deploy/releases/${OPERATOR_VERSION}/kustomize/overlays/watch-all-namespaces/olo-all-namespaces.yaml -q -P ./overlays/watch-all-namespaces
wget https://raw.githubusercontent.com/OpenLiberty/open-liberty-operator/main/deploy/releases/${OPERATOR_VERSION}/kustomize/overlays/watch-all-namespaces/cluster-roles.yaml -q -P ./overlays/watch-all-namespaces
wget https://raw.githubusercontent.com/OpenLiberty/open-liberty-operator/main/deploy/releases/${OPERATOR_VERSION}/kustomize/overlays/watch-all-namespaces/kustomization.yaml -q -P ./overlays/watch-all-namespaces
mkdir base
wget https://raw.githubusercontent.com/OpenLiberty/open-liberty-operator/main/deploy/releases/${OPERATOR_VERSION}/kustomize/base/kustomization.yaml -q -P ./base
wget https://raw.githubusercontent.com/OpenLiberty/open-liberty-operator/main/deploy/releases/${OPERATOR_VERSION}/kustomize/base/open-liberty-crd.yaml -q -P ./base
wget https://raw.githubusercontent.com/OpenLiberty/open-liberty-operator/main/deploy/releases/${OPERATOR_VERSION}/kustomize/base/open-liberty-operator.yaml -q -P ./base
kubectl apply -k overlays/watch-all-namespaces

The output should be a series of lines following the format <object type> created. If you see any lines that don't conform to that format, troubleshoot and resolve the reason before continuing.

Configure and build the application image

To deploy and run your Liberty application on the AKS cluster, containerize your application as a Docker image using Open Liberty container images or WebSphere Liberty container images.

Follow the steps in this section to deploy the sample application on the Liberty runtime. These steps use Maven and the liberty-maven-plugin. To learn more about the liberty-maven-plugin, see Building a web application with Maven.

Check out the application

Clone the sample code for this guide. The sample is on GitHub. There are a few samples in the repository. We'll use java-app. Here's the file structure of the application.

java-app
├─ src/main/
│  ├─ aks/
│  │  ├─ db-secret.yaml
│  │  ├─ openlibertyapplication.yaml
│  ├─ docker/
│  │  ├─ Dockerfile
│  │  ├─ Dockerfile-local
│  │  ├─ Dockerfile-wlp
│  │  ├─ Dockerfile-wlp-local
│  ├─ liberty/config/
│  │  ├─ server.xml
│  ├─ java/
│  ├─ resources/
│  ├─ webapp/
├─ pom.xml

The directories java, resources, and webapp contain the source code of the sample application. The code declares and uses a data source named jdbc/JavaEECafeDB.

In the aks directory, we placed two deployment files. db-secret.xml is used to create Kubernetes Secrets with DB connection credentials. The file openlibertyapplication.yaml is used to deploy the application image.

In directory liberty/config, the server.xml is used to configure the DB connection for the Open Liberty and WebSphere Liberty cluster.

Build project

Now that you've gathered the necessary properties, you can build the application. The POM file for the project reads many properties from the environment. The reason for this parameterization is to avoid having to hard-code values such as database server names, passwords, and other identifiers into the example source code. This allows the sample source code to be easier to use in a wider variety of contexts. These variables are also used to populate JavaEECafeDB properties in server.xml and in yaml files located in src/main/aks.

cd <path-to-your-repo>/java-app

# The following variables will be used for deployment file generation
export LOGIN_SERVER=${LOGIN_SERVER}
export REGISTRY_NAME=${REGISTRY_NAME}
export USER_NAME=${USER_NAME}
export PASSWORD=${PASSWORD}
export DB_SERVER_NAME=<Server name>.database.windows.net
export DB_NAME=<Database name>
export DB_USER=<Server admin login>@<Server name>
export DB_PASSWORD=<Server admin password>

mvn clean install

(Optional) Test your project locally

Use your local ide, or liberty:run command to run and test the project locally before deploying to Azure.

  1. Start your local docker environment if you haven't done so already. The instructions for doing this vary depending on the host operating system. liberty:run will also leverage the environment variables defined previously.

Note

If you selected a "serverless" database deployment, verify that your SQL database has not entered pause mode. One way to do this is to log in to the database query editor as described in Quickstart: Use the Azure portal query editor (preview) to query Azure SQL Database.

  1. Start the application in liberty:run mode

    cd <path-to-your-repo>/java-app
    mvn liberty:run
    
  2. Verify the application works as expected. You should see a message similar to [INFO] [AUDIT] CWWKZ0003I: The application javaee-cafe updated in 1.930 seconds. in the command output if successful. Go to http://localhost:9080/ in your browser to verify the application is accessible and all functions are working.

  3. Press Ctrl+C to stop liberty:run mode.

Build image for AKS deployment

After successfully running the app in the Liberty Docker container, you can run the docker build command to build the image.

cd <path-to-your-repo>/java-app/target

# If you are running with Open Liberty
docker build -t javaee-cafe:v1 --pull --file=Dockerfile .

# If you are running with WebSphere Liberty
docker build -t javaee-cafe:v1 --pull --file=Dockerfile-wlp .

Upload image to ACR

Now, we upload the built image to the ACR created in the previous steps.

If you haven't already done so, log in to the container registry.

docker login -u ${USER_NAME} -p ${PASSWORD} ${LOGIN_SERVER}

Tag and push the container image.

docker tag javaee-cafe:v1 ${LOGIN_SERVER}/javaee-cafe:v1
docker login -u ${USER_NAME} -p ${PASSWORD} ${LOGIN_SERVER}
docker push ${LOGIN_SERVER}/javaee-cafe:v1

Deploy application on the AKS cluster

Follow steps below to deploy the Liberty application on the AKS cluster.

  1. Attach the ACR instance to the AKS cluster so that the AKS cluster is authenticated to pull image from the ACR instance.

    az aks update -n $CLUSTER_NAME -g $RESOURCE_GROUP_NAME --attach-acr $REGISTRY_NAME
    
  2. Apply the DB secret and deployment file by running the following command:

    cd <path-to-your-repo>/java-app/target
    
    # Apply DB secret
    kubectl apply -f db-secret.yaml
    
    # Apply deployment file
    kubectl apply -f openlibertyapplication.yaml
    
    # Check if OpenLibertyApplication instance is created
    kubectl get openlibertyapplication javaee-cafe-cluster
    
    NAME                        IMAGE                                                   EXPOSED   RECONCILED   AGE
    javaee-cafe-cluster         youruniqueacrname.azurecr.io/javaee-cafe:1.0.25         True         59s
    
    # Check if deployment created by Operator is ready
    kubectl get deployment javaee-cafe-cluster --watch
    
    NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
    javaee-cafe-cluster         0/3     3            0           20s
    
  3. Wait until you see 3/3 under the READY column and 3 under the AVAILABLE column, then use CTRL-C to stop the kubectl watch process.

Test the application

When the application runs, a Kubernetes load balancer service exposes the application front end to the internet. This process can take a while to complete.

To monitor progress, use the kubectl get service command with the --watch argument.

kubectl get service javaee-cafe-cluster --watch

NAME                        TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)          AGE
javaee-cafe-cluster         LoadBalancer   10.0.251.169   52.152.189.57   80:31732/TCP     68s

Once the EXTERNAL-IP address changes from pending to an actual public IP address, use CTRL-C to stop the kubectl watch process.

If some time has passed between executing the steps in this section and the preceding one, ensure the database is active, if necessary. See the note above regarding database pause.

Open a web browser to the external IP address of your service (52.152.189.57 for the above example) to see the application home page. You should see the pod name of your application replicas displayed at the top-left of the page. Wait for a few minutes and refresh the page to see a different pod name displayed due to load balancing provided by the AKS cluster.

Java liberty application successfully deployed on AKS.

Note

Currently the application is not using HTTPS. We recommend that you ENABLE TLS with your own certificates.

Clean up the resources

To avoid Azure charges, you should clean up unnecessary resources. When the cluster is no longer needed, use the az group delete command to remove the resource group, container service, container registry, and all related resources.

az group delete --name $RESOURCE_GROUP_NAME --yes --no-wait
az group delete --name <db-resource-group> --yes --no-wait

Next steps

You can learn more from references used in this guide: