Table of contents
1.
Introduction
2.
Pre-Migration
2.1.
Inventory external resources
2.1.1.
Inside your application
2.1.2.
On the application server(s)
2.1.3.
Datasources
2.1.4.
All other external resources
2.2.
Inventory secrets
2.2.1.
Passwords and secure strings
2.3.
Determine whether the file system is used
2.3.1.
Read-only static content
2.3.2.
Dynamically published static content
2.3.3.
Dynamic or internal content
2.4.
Identify session persistence mechanism
2.5.
Special cases
2.5.1.
Determine whether the application relies on scheduled jobs
2.5.2.
Determine whether AccessLogValve is used
2.6.
Parameterize the configuration
3.
Migration
3.1.
Provision container registry and AKS
3.2.
Prepare the deployment artifacts
3.2.1.
Open ports for clustering, if needed
3.2.2.
Add JNDI resources
3.3.
Build and push the image
3.4.
Provision of a public IP address
3.5.
Deploy to AKS
3.6.
Configure persistent storage
3.7.
Configure KeyVault FlexVolume
4.
Post-migration
5.
Frequently Asked Questions
5.1.
What do you mean by Tomcat on Azure?
5.2.
Can I utilize the Azure App service with Tomcat clustering?
5.3.
How does the Tomcat server work?
5.4.
Can Apache and Tomcat run together?
5.5.
How is Apache Tomcat put to use?
6.
Conclusion
Last Updated: Mar 27, 2024

Migrate Tomcat applications to containers on Azure Kubernetes Service

Author Manan Singhal
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

In this article, you will understand how to transfer our existing tomcat application to run on Azure Kubernetes Service(AKS).

Microsoft Azure

Pre-Migration

Before you begin, complete the assessment and inventory activities outlined in the following sections to ensure a successful migration.

Inventory external resources

Through the Java Naming and Directory Interface, external resources, including data sources, JMS message brokers, and others, are inserted (JNDI). Some of these resources might need to be relocated or reconfigured.

Inside your application

Examine the context.xml file under META-INF. Within the <Context> element, look for <Resource> elements.

On the application server(s)

Examine the.xml files located in the $CATALINA_BASE/conf/[engine-name]/[host-name] directories, as well as the $CATALINA_BASE/conf/context.xml and $CATALINA_BASE/conf/server.xml files.

JNDI resources will be described via the <Resource> components inside the top-level <Context> element in context.xml files.

The <Resource> elements in the <GlobalNamingResources> element in server.xml files will define JNDI resources.

Datasources

Make a note of the following details for each data source:

  1. What's the name of the data source?
     
  2. What is the configuration of the connection pool?
     
  3. What location is the JDBC driver JAR file located?
     

All other external resources

We can't list all potential external dependencies in this tutorial. Your team is in charge of ensuring you can satisfy any external dependencies of your application following the move.

Inventory secrets

Passwords and secure strings

Secure Password

On the production server(s), search all properties and configuration files for any secret strings or passwords. Carefully look through the files in $CATALINA_BASE/conf called server.xml and context.xml. Inside your application, you could potentially discover configuration files that include passwords or other login information. META-INF/context.xml, applications.properties, or application.yml files are examples of possible candidates.

Determine whether the file system is used

Any use of the application server's file system requires configuration changes or, in rare circumstances, architecture changes. You may recognize any or all of the following circumstances.

Read-only static content

You'll need a different place for static content if your application currently delivers it. You might want to think about adding Azure CDN for lightning-fast downloads worldwide and migrating static material to Azure Blob Storage.

Dynamically published static content

Use Azure CDN and Azure Blob Storage, along with an Azure Function to handle uploads and CDN refreshes if your application permits static content uploaded or produced by your application but is immutable after it has been created.

Dynamic or internal content

You can connect Azure Storage shares as persistent volumes for files often written to and read by your application or static files that are only visible to your application.

Identify session persistence mechanism

Examine the context.xml files in your application and the Tomcat settings to determine the session persistence manager used. Find the Manager> element, then note the className attribute's value.

StandardManager and FileStore, two built-in PersistentManager implementations in Tomcat, aren't intended for usage with a distributed, scalable platform like Kubernetes. While AKS can transparently restart any pod at any moment and load balance across multiple pods, it is not advised to persist mutable state to a file system.

Use an alternative PersistentManager implementation that will write to an external data store, such as VMware Tanzu Session Manager with Redis Cache, if session persistence is necessary.

Special cases

Special Cases

Some production scenarios might call for more modifications or impose more restrictions. Even if they might not happen often, it's crucial to ensure they don't apply to your application or are handled properly.

Determine whether the application relies on scheduled jobs

Containerized Tomcat deployments cannot use scheduled tasks like cron jobs or Quartz Scheduler activities. One planned job may run more than once throughout a scheduled time if your application is scaled out. There may be unforeseen repercussions in this case. List all scheduled tasks, whether on the application server or not.

Determine whether AccessLogValve is used

If AccessLogValve is utilized, the mounted Azure Files share or one of its subdirectories should be specified as the directory parameter.

Parameterize the configuration

You probably saw secrets and external dependencies, such as datasources, in the server.xml and context.xml files during the pre-migration. Replace each username, password, connection string, or URL with an environment variable for each object that has been identified in this way.

Assume that the element shown below is present in the context.xml file:

<Resource
    name="jdbc/dbconnection"
    driverClassName="org.postgresql.Driver"
    url="jdbc:postgresql://postgresdb.contoso.com/wickedsecret?ssl=true"
    type="javax.sql.DataSource"
    username="postgres"
    password="t00secure2gue$$"
/>

 

Change the above code to the following code:

<Resource
    name="jdbc/dbconnection"
    type="javax.sql.DataSource"
    url="${postgresdb.connectionString}"
    driverClassName="org.postgresql.Driver"
    username="${postgresdb.username}"
    password="${postgresdb.password}"
/>

Migration

We advise that you carry out the procedures listed below one at a time for each program (WAR file) you desire to migrate, except for the first step.

Provision container registry and AKS

Make an Azure Kubernetes cluster whose Service Principal has the Reader role on the registry and a container registry. Make careful you select the right network model for the networking needs of your cluster.

#1
az group create -g $resourceGroup -l eastus
#2
az acr create -g $resourceGroup -n $name --sku Standard
#3
az aks create -g $resourceGroup -n $name --attach-acr $acrName --network-plugin azure

 

Prepare the deployment artifacts

Github logo

Clone the GitHub source for the Tomcat On Containers Quickstart. There are several suggested optimizations in the Tomcat and Dockerfile configuration files. Before creating the container image and deploying it to AKS, you'll probably need to make the changes we've outlined in the steps below to these files.

Open ports for clustering, if needed

Make sure the required port ranges are available in the Dockerfile if Tomcat Clustering on AKS is something you want to employ. Use variable initialized to the pod's IP address upon container startup when specifying the server IP address in server.xml.

Alternatively, the session state might be saved in a different place and made accessible to replicas.

If your application employs clustering, check the server.xml file for the <Cluster> element inside the <Host> or <Engine> components.

Add JNDI resources

To include the resources you prepared during the pre-migration processes, such as Data Sources, edit server.xml.

For example:

<GlobalNamingResources>
    <!-- Editable user database -->
    <Resource name="UserDatabase" auth="Container"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              type="org.apache.catalina.UserDatabase"
              pathname="conf/tomcat-users.xml"
              description="User database"
              />

    <!-- Migrated datasources here: -->
    <Resource
        name="jdbc/dbconnection"
        type="javax.sql.DataSource"
        url="${postgresdb.connectionString}"
        driverClassName="org.postgresql.Driver"
        username="${postgresdb.username}"
        password="${postgresdb.password}"
    />
    <!-- End of migrated datasources -->
</GlobalNamingResources>

 

Build and push the image

The az acr build command is the simplest approach to create and upload the image to Azure Container Registry (ACR) for usage by AKS. Docker does not need to be set up on your machine to run this command. For instance, assuming the application package petclinic.war and the Dockerfile mentioned above are both present in the current directory, building the container image in ACR only requires the following step:

az acr build -t "${acrName}.azurecr.io/petclinic:{{.Run.ID}}" -r $acrName --build-arg APP_FILE=petclinic.war --build-arg=prod.server.xml

 

As an alternative, you might create the image locally using Docker CLI. This method can make testing and improving the image easier before the first ACR deployment. However, it needs the Docker daemon to be running, and the Docker CLI installed.

sudo docker build . --build-arg APP_FILE=petclinic.war -t "${acrName}.azurecr.io/petclinic:1"
sudo docker run -d -p 8080:8080 "${acrName}.azurecr.io/petclinic:1"
sudo az acr login -n $acrName
sudo docker push "${acrName}.azurecr.io/petclinic:1"

 

Provision of a public IP address

A public static IP address is necessary if your application can be accessed from outside your physical or virtual network(s). This IP address must be provisioned within the cluster's node resource group.

#Line1
nrg=$(az aks show -g $resourceGroup -n $aksName --query 'nodeResourceGroup' -o tsv)
#Line2
publicIp=$(az network public-ip create -g $nrg -n applicationIp --sku Standard --allocation-method Static --query 'publicIp.ipAddress' -o tsv)
#Line3
echo "Your public IP address is ${publicIp}."

 

Deploy to AKS

Azure Kubernetes Service

Make a YAML file for Kubernetes and apply it. Ensure that the IP address provisioned in the previous step is used as the LoadBalancerIP whenever you create an external load balancer (whether for your application or an ingress controller).

As environment variables, add externalized parameters. Leave out the secrets (such as passwords, API keys, and JDBC connection strings). The Configure KeyVault FlexVolume section contains information on secrets.

Configure persistent storage

Configure one or more Persistent Volumes if your application needs non-volatile storage.

You might want to construct a persistent volume using Azure Files mounted to the Tomcat logs directory to store logs centrally.

Configure KeyVault FlexVolume

Make an Azure KeyVault, then fill it with all the required secrets. Then set up a KeyVault FlexVolume so that pods can access those secrets.

You must change the startup script to import the certificates into the local key store on the container.

Application Deployed

Post-migration

You should check to see if your application still functions as expected after moving it to AKS. We have some suggestions for you that can help your application become more Cloud-native after you've done that.

  1. Think about giving the IP address assigned to your ingress controller or application load balancer a DNS name.
     
  2. For your application, you might want to include HELM charts. You can parameterize your application deployment so that a wider range of users can utilize and customize it.
     
  3. Create and put into action a DevOps plan. Consider automating testing and deployments with Azure Pipelines to preserve dependability while accelerating your development pace.
     
  4. For the cluster, enable Azure Monitoring to enable the collecting of container logs and the tracking of utilization, among other things.
     
  5. Think about using Prometheus to expose application-specific metrics. A widely used open-source metrics framework in the Kubernetes community is Prometheus. Instead of maintaining your own Prometheus server, you may configure Prometheus Metrics scraping in Azure Monitor to enable metrics aggregation from your apps and automated response to or escalation of abnormal events.
     
  6. Create and put into action a business continuity and catastrophe recovery plan. Consider a multi-region deployment architecture for mission-critical applications.
     
  7. Review the policy on Kubernetes Version Support. Make sure your AKS cluster constantly runs a supported version by performing regular updates.
     
  8. Review the relevant AKS best practices with all team members in charge of cluster administration and application development.
     
  9. Look at the logging.properties file's contents. To enhance performance, think about removing or lowering part of the logging output.
     
  10. To further enhance performance, consider keeping an eye on the code cache size and adding the -XX:InitialCodeCacheSize and -XX:ReservedCodeCacheSize arguments to the JAVA_OPTS variable in the Dockerfile.

Must Read, kubernetes interview questions

Frequently Asked Questions

What do you mean by Tomcat on Azure?

The Apache Software Foundation (ASF) created the Java Servlet Container, Tomcat, which is open-source. An extremely well-liked open-source relational database management system is MySQL.

Can I utilize the Azure App service with Tomcat clustering?

The Azure App Service does not allow Tomcat clustering. Instead of requiring Tomcat-specific capabilities, you can configure and manage scalability and load balancing with Azure App Service. To make the session state accessible across replicas, you can store it in a different place.

How does the Tomcat server work?

A web container called Tomcat manages your servlets and their mappings. Tomcat checks the URL mappings after any request for a servlet is made to apache, and the result is generated in a way browsers can understand.

Can Apache and Tomcat run together?

Running Apache and Tomcat on the same computer is no problem. It's pretty common to run Tomcat on port 8080, run Apache on port 80/443, and use mod_proxy to allow Apache to serve apps hosted by Tomcat.

How is Apache Tomcat put to use?

One of Tomcat's connectors receives a request from a client. Tomcat routes this request to the proper Engine for processing. The range of Tomcat's search for the right Engine is constrained because these Engines are included within other elements like hosts and servers.

Conclusion

In this article, we have learned why we need to transfer our existing tomcat application to run on Azure Kubernetes Service(AKS). To continue learning more about Azure, check out our other blogs on the AWS vs azure vs google cloudMicrosoft AzureAzure Service Fabric, and Microsoft Azure certification.

Refer to our guided paths on Coding Ninjas Studio to learn about Data Structure and Algorithms, Competitive Programming, JavaScript, etc. Enroll in our courses and refer to our mock test available. Have a look at the interview experiences and interview bundle for placement preparations.

Happy Coding!

Thank You
Live masterclass