This document aims to outline the process, best practices, and tools for using Anthos to modernize legacy monolithic Java applications.
This document is intended for CTOs, CIOs, enterprise architects, application developers, IT security administrators, application developers, DevOps teams, and Site Reliability Engineering (SRE) teams. It assumes a basic knowledge of containerization and its operational and developmental benefits.
This document proposes a two-phased approach to modernization:
- Containerize. In this phase, you containerize and deploy suitable candidate applications to the Anthos platform (whether on-premises or in Google Cloud). This phase uses various services and technologies such as Migrate to Containers, modern continuous integration/continuous deployment (CI/CD) practices, and system integrator tools.
- Refactor and replatform. Over time, you refactor and replatform legacy monolithic applications to modern Java frameworks (like Spring Boot) and microservices.
This document provides guidance and resources for each of these phases. It also offers an alternate path in case you plan to keep your enterprise on virtual machines (VMs).
A case for modernization
Many organizations struggle to keep their business applications running while also trying to innovate. Development and operations teams must cater to new demands for application services and also maintain, operate, and improve existing application portfolios.
This new demand comes from digital business initiatives and the goal of digital transformation to improve existing functions. Yet, according to a Gartner report (Building a Multiplatform Application Modernization Business Case, November 2019), 90% of current applications will still be in use by 2025, and the technical debt to support and manage these applications will continue to compound, consuming more than 40% of current IT budgets.
Although enterprises develop and adopt new applications, the majority of their applications are still conventional, monolithic applications. Many of these legacy applications run on proprietary and commercial application servers such as IBM WebSphere or Oracle® WebLogic. Because these applications are often well-optimized, maintained, and managed, enterprises are challenged to innovate on top of them. Moreover, proprietary application servers can increase operational overhead and require (in many cases) cost-prohibitive licensing agreements.
A number of studies suggest that organizations can save time and money by modernizing conventional applications instead of rewriting existing application code. Any strategy to modernize legacy applications must focus on reducing both the time and cost to modernize.
Modern applications can help you deliver better experiences for your customers, which can result in customer retention and satisfaction and therefore increased profitability. The tenets of modern application and platform development highlight the benefits that come with digital transformation. The following sections explain these tenets.
Increasing developer and operator productivity
Legacy applications are often monolithic applications. These applications have a large codebase that performs several functions. As the applications grow, along with the teams that develop and manage them, it becomes difficult to maintain and release new features rapidly. Many dependencies exist between teams that must be reconciled and approved before a change can be released into production and to the customer. This dynamic can lead to lower developer and operator productivity and customer dissatisfaction.
Modern applications are built using microservices. Different domains of a monolithic application are split into separate services, each responsible for a specific function (hence the term microservices). This architecture provides several benefits:
- For developers. Decoupling the services from one another lets your developers work on their specific feature independently of other services. This approach increases developer productivity because developers can add features to their service without tight dependencies to other services and teams.
- For operators. Each microservice release implements small changes, which is much easier for your operations team to manage than one large, complex change. Deploying smaller changes in this controlled fashion carries fewer risks if a release fails, leading to increased productivity for operations.
- For customers. The developmental and operational efficiencies of a modern architecture can help your teams deliver new features to customers more quickly than with a monolithic architecture.
Focusing on services and APIs
Legacy applications are often considered in terms of infrastructure. Servers, virtual machines (VMs), networking, and storage are key design elements for a monolithic application. Modern applications are considered in terms of services and APIs. This focus on services and APIs offers several advantages:
- Service redundancy and resilience. You can run services anywhere, often in many places—such as VMs, containers, or clusters.
- Service availability. Operating with a focus on services can increase the overall availability of your application. As long as the service is available, infrastructure failures are moot and irrelevant. Designing and thinking in terms of services and APIs instead of infrastructure emphasizes uptime—and uptime helps you meet your service level objective (SLO).
Running as microservices in containers
Legacy applications typically run as VMs or on bare metal. These platforms are expensive, inefficiently used (with under-used CPUs and RAM), and harder to manage than modern cloud-based platforms (especially for bare metal servers). Modern applications run as microservices in containers, which provides several benefits, including the following:
- Smaller, more efficient applications. Containers can package a microservice with a footprint that is two to three orders of magnitude smaller than a monolithic application.
- Linux user space isolation. You can run multiple containers on a single host, using the host efficiently.
- Portability between different environments and infrastructure. Because containers encapsulate the application with all its dependencies and required libraries, you can run containers in any environment—whether in an on-premises data center or public cloud environment.
Building on open standards
Legacy applications often use commercial or licensed products for functionality. This approach is not only expensive because of licensing costs but also makes the application highly dependent on commercial platforms.
In some cases, the commercial software is limited by the infrastructure or hardware it can run on. For example, if the software can only run on-premises, your enterprise must manage costly data centers and infrastructure (such as networking, storage, servers, power, and HVAC).
Modern applications and services are often built by using open source software, providing several advantages:
- Extensibility and portability. You can run services anywhere.
- Support. Well-adopted open source technologies like Kubernetes and Docker often have strong communities (composed of many companies) building features that are not bound by or for the benefit of a single company. This open source approach results in an overall better feature set for the product. The more you adopt an open source technology (like Kubernetes), the stronger your feature set becomes as compared to almost any commercial equivalent.
- Flexibility. In this model, your enterprise is no longer locked in with a single vendor for your application platform or infrastructure. Adopting open standards lets you make application and infrastructure decisions based on customer and business requirements.
The modern platform
Modern applications need a modern platform. The modern platform must meet several needs.
Fast, reliable, and secure feature rollout
Modern platforms must support fast, reliable, and secure rollouts of new features.
- Fast. This requirement depends on sufficient automation to deploy services and new features. Automation eliminates human work and errors and increases delivery speeds.
- Reliable. The platform must let teams gradually release features or revert features to their original state if they do not work.
- Secure. The platform must support granular access controls. Only authorized operators should be able to access services or deploy features and services to the platform.
A priority on services
Modern applications are designed, developed, and run with a view to services and not infrastructure. This priority on services depends on platforms that are resilient to infrastructure failures. Modern platforms have built-in functionality that recover services (and the platform itself) from hardware and software failures.
Hybrid and multi-cloud approach with a consistent control plane
As part of their digital transformation, many enterprises are moving towards a multi-cloud or hybrid-cloud strategy for their services portfolio. Perhaps you cannot move certain applications from on-premises data centers to the public cloud (for regulatory, compliance, or security reasons) but still want to use the cloud for other services. Modern platforms can (and often do) run across multiple environments such as on-premises data centers, private clouds, or one or more public clouds. While running on various infrastructure, modern platforms must provide a unified consistent control plane experience to the developers and operators, which increases operational efficiency.
Everything as declarative code
Legacy platforms (like VMs) are imperative in nature. Operators often create resources and provide scripts and configurations that execute at application runtime. When operators change an application, they make the change directly to the VM where the application runs. This process can cause configuration drift, meaning that at any point in time, there is no guarantee that the application and platform are in the intended state. In such an environment, troubleshooting and recovering from failures can be difficult.
Modern platforms are declarative systems where all the resources are defined as code—also known as Infrastructure as Code (IAC). Infrastructure, services, deployments, security, and policy are codified into resource documents that define the intended state of the platform. This declarative approach lets operators define their services, security, and policy through a unified language. Because these resources are code, they can be stored in a code repository and undergo the same scrutiny of code checks as do applications. When the state of the platform resides in a Git repository (along with the history of all commits for every state change), it's easier to recover to an earlier state when a system failure or disaster occurs.
The Anthos platform
Anthos is Google Cloud's modern application platform. With the open, hybrid, multi- cloud Anthos platform, you can modernize your existing applications, build new ones, and run them anywhere in a more secure manner. Built on open source technologies pioneered by Google—including Kubernetes, Istio, and Knative—Anthos helps you achieve consistency between on-premises and cloud environments and accelerate application development.
The following diagram shows the Anthos components and their interactions in a typical enterprise environment.
The following sections briefly describe the core components of Anthos.
Anthos clusters: Container orchestration
The primary computing environment for Anthos relies on Anthos clusters to manage Kubernetes installations in the environments where you intend to deploy your applications. These offerings bundle upstream Kubernetes releases and let you create, scale, and upgrade conformant Kubernetes clusters.
Kubernetes has two main parts: the control plane and the node components. When you use GKE, Google Cloud hosts the control plane, and the Kubernetes API server is the only control plane component that customers can access. GKE manages the node components in the customer's project by using instances in Compute Engine. When you use Anthos clusters, all components are hosted in the customer's on-premises virtualization environment.
With Kubernetes installed and running, you can access a common orchestration layer that manages application deployment, configuration, upgrade, and scaling.
Anthos Config Management: Policy management
Anthos Config Management lets you manage single clusters, multi-tenant clusters, and multi-cluster Kubernetes deployments by using files called configs. You store configs in a Git repository.
Some configs are Kubernetes object manifests. Other configs are not object manifests but provide information that Anthos Config Management needs. You can write configs in YAML or JSON. Anthos Config Management watches for updates to these files and applies changes to all relevant clusters automatically.
A configuration-as-code approach lets you manage the configuration of your Anthos clusters by using the same principles that you might already use to manage your applications deployed in Kubernetes.
Anthos Service Mesh: Services management
Anthos Service Mesh is an Istio-compatible framework that lets you connect, monitor, and help secure services running on Anthos clusters. Using Anthos Service Mesh, you can create a network of deployed services such as load balancing, service-to-service authentication, and monitoring without requiring any changes in service code.
Anthos Service Mesh automatically injects a sidecar proxy for each of your application's Pods. A Pod is the basic execution unit of a Kubernetes application. A Pod encapsulates an application's container (or, in some cases, multiple containers). In Anthos Service Mesh, every Pod contains two containers—the application container and an Envoy proxy container (also known as a sidecar proxy). The sidecar proxy intercepts all network traffic to and from the Pods. Anthos Service Mesh also configures an ingress gateway to manage inbound traffic to the mesh. You can use open source Istio APIs to configure policies that are enforced on sidecars and gateways.
Journey to modernization
Google Cloud provides a prescriptive process to move your Java applications from a monolithic state to microservices. You can choose to adopt the following steps and move at a pace that best meets your business requirements and needs:
- Lift and modernize suitable applications from running in VMs to running in containers without rewriting any code.
- Deploy containerized applications to Anthos platform by using modern CI/CD practices. Some applications might not be good candidates for containerization and might remain as VMs.
- Refactor applications to OSS application stacks, modern frameworks, and microservices over time.
The following flowchart illustrates this journey.
Each of these important steps is expained in the next section.
Steps to modernization
The following sections explain each step of the modernization process and how Anthos and Migrate to Containers helps at each stage.
Step 1: Containerizing Java applications
In this modernization step, you containerize suitable Java applications that are running as VMs.
Containerization is a process that packages application code along with all the dependencies and libraries of its operating environment. You can run multiple containers on a single host, each with its own isolated standalone application environments. Containers are lightweight, portable, and efficient alternatives to VMs.
You can containerize a Java application in one of two ways:
- Use Migrate to Containers to lift and modernize the application.
- Use system integrator tools to build containers.
Lift and modernize using Migrate to Containers
You can use Migrate to Containers to migrate applications from VMs directly to containerized artifacts (such as a Dockerfile or Kubernetes resource manifests). You then deploy the containers to Anthos (on GKE and on Anthos clusters on VMware).
Migrating with Migrate to Containers
The process of using Migrate to Containers to migrate applications is as follows:
- Identify candidates for migration. In this step, you assess which
applications are suitable for migration. Two application types are good
candidates for migration:
- Applications whose source code cannot be accessed. Perhaps developers are no longer with a company and the codebase is no longer supported. Instead of managing these applications as VMs, you can use the simplified containerization process in Migrate to Containers to move these applications to Anthos.
- Applications that are maintained but not developed. Some applications might not be actively developed, yet enterprises still need them because of dependencies on other services. Migrate to Containers simplifies the process of modernizing the platform that supports these applications.
- Migrate to Anthos. After you identify suitable candidates for migration, you use Migrate to Containers to convert VMs into containerized artifacts that can be deployed to Anthos by using modern CI/CD practices (see the next section). Migrate to Containers also helps to move data and state for the applications.
Migrate to Containers and challenging migrations
The number of applications that enterprises manage can sometimes be in the thousands. The number of applications to move or the complexities of containerization might hinder enterprises from moving forward on important cloud initiatives. As a result, enterprises can miss business opportunities and the benefits of best-in-class public cloud services. These services might be data and analytics services like BigQuery, artificial intelligence applications such as AutoML, or machine learning (ML) applications such as Google Cloud's pretrained APIs.
Migrate to Containers can help you with the challenges and complexities of your application portfolio in the following ways:
- Handling large-scale application migrations. Using Migrate to Containers, you can modernize and, in parallel, move numerous applications to Anthos without accruing technical debt to your developers and operators.
- Simplifying containerization. Coupled with a large number of applications, containerization can be complex and enterprises may not have the skillset or the amount of resources to support large modernization efforts in a timely fashion. For such cases, Migrate to Containers provides you a simplified and efficient path to Anthos and modernization.
For more information, see Migrate to Containers documentation.
Other tools for containerization
Docker is a widely used platform for building container images. A Dockerfile is a text document that contains all the commands you can call on the command line in order to assemble an image. To create a Docker container, you build your binaries (JAR files) and then package them in a Dockerfile. After you create the Dockerfile, you can use it in a CI/CD pipeline. The following diagram illustrates the workflow that uses a Dockerfile.
Step 2: Deploying applications to Anthos using modern CI/CD
In this modernization step, you deploy containerized Java applications to Anthos by using modern software delivery practices.
Applications require a well-orchestrated, automated, repeatable, and reliable way to be built, tested, and delivered to customers. Because multiple development teams continuously add features, they often build, test, and deploy containerized applications by using CI/CD.
Benefits of modern software delivery practices
Anthos' modern CI/CD or software delivery platform lets you do the following:
- Create and update best practices for provisioning applications.
- Onboard new applications through starter (or boilerplate) projects.
- Develop and iterate applications without interfering with other application development.
- Seamlessly implement and propagate policy across the platform.
- Use GitOps for deployment and for improved release management and change tracking.
Software delivery platform with Anthos
The components in the following diagram form a complete software delivery platform, which is available with the Anthos platform.
Each component provides functionality to the system and applications running on the platform. Several teams (such as development, operations, and security) are typically responsible for maintaining the uptime, configuration, stability, and scale of the platform.
A core component to the software delivery platform is the CI/CD system. When you begin to define the CI/CD process, you need to make sure that each component produces or consumes artifacts that adhere to a standardized interface. When you use a standard interface, it is easier to swap out each component when a better implementation comes to market. When you create a platform for containerized applications, you can choose from three standardized interfaces:
- Git repositories
- Docker images
- Kubernetes manifests
With these interfaces in place, you can create a reusable and flexible CI/CD pipeline with the flows shown in the following diagram.
The process is as follows:
- Developers commit the application code to the application's Git repository.
- The CI system tests the code, creates a Docker image artifact, and stores the image in a registry.
- After the artifact is ready for deployment, a reference to the artifact is added to the application configuration file.
- That application configuration is rendered into a Kubernetes-readable format and stored in a code repository, which deploys it to a pre-production environment.
- After the changes are committed to the code repository, operators review the changes and then merge them into the master branch.
- The application is deployed to production.
- When operators want to make changes across the organization, they commit those changes to their repositories, which triggers an application configuration. When developers deploy the next change, the developers pick up the operators' updates.
- In parallel, security engineers can implement and tweak the policies that define what can be deployed by committing to their own policy repository.
Step 3: Optimizing on-premises VMs for legacy Java applications
In this modernization step, Java applications run as VMs either in on- premises data centers or in Google Cloud, as the following diagram shows.
Some Java applications might not be good candidates for containerization for the following reasons:
- Some of your applications are business critical. If migrating your business-critical applications to containers is too risky, you can still get infrastructure elasticity cost benefits by moving VMs to Google Cloud. In Google Cloud, you can customize the size of the VM to maximize its usage costs.
- Operational teams are unfamiliar with managing a modern platform. Some operations teams might not be comfortable with managing VM environments or don't possess the skills to operate on modern containerized platforms. For example, your team might already be familiar with the current toolchain for managing connectivity and dependencies between legacy applications but needs time to ramp up on operating a containerized platform in production.
- You need to adopt the cloud in stages. For example, you might want to start adopting the cloud but don't want to make too many changes at once. Or, because of risks, you might not want to change your environment (from a data center to the cloud) and platforms (from VM to containers) at the same time.
- You have budget and operational constraints. These might include hardware/infrastructure, licensing, or application architecture requirements.
Options for running VM workloads
You can choose from one or more of the following options to run your VM workloads more efficiently:
- On Google Cloud. You can run VMs on
Google Cloud in two ways:
- As Compute Engine instances. Compute Engine offers configurable VMs running in Google's data centers that have access to high-performance networking infrastructure and block storage. This option relieves enterprises of managing on-premises data centers and servers and paying for virtualization commercial licenses (if applicable).
- As VMware as a Service. The partnership between VMware and Google Cloud delivers an open platform to ensure consistent deployment, operations, and security for cloud applications across multi- and hybrid-cloud environments. This option is applicable for enterprises currently running VMware that rely on VMware-specific functionality. Enterprises are either in a hybrid cloud environment where they want a consistent control plane to manage their VMs (across multiple environments), or they no longer want to manage their own data centers and server infrastructure.
- On-premises data centers. You might run certain
applications as VMs on premises for several reasons:
- Regulatory or compliance considerations
- Performance needs that require them to be closer to their users or other applications
- Current investments in on-premises hardware
Tooling and solutions for migrating VMs
Google Cloud provides various tools and solutions that you can use to migrate your VMs to Google Cloud. With Migrate for Compute Engine, you can validate, run, and migrate applications into Google Cloud within minutes while your data migrates transparently in the background. For resources on how to migrate to Compute Engine, see Migration to Google Cloud: Getting started.
For migrations to VMWare as a Service, Google works with trusted partners to provide professional services that can assist your VMware migrations to Google Cloud.
Step 4: Refactoring applications into microservices
After you modernize the platform, you can focus on modernizing applications that run on the platform. In this stage, you take applications that are running on the Anthos platform and refactor them into microservices.
You might have some applications that still run as monoliths in containers, but that is not a problem. A prerequisite to modernizing applications is migrating your applications to a modern platform (such as Anthos). After the migration, the process of modernizing your applications into microservices can occur over time.
Moving to Anthos lets both developers and operators get familiar with new ways of application and platform management. Developers get used to merging code faster and testing often, while operators get familiar with the modern way of building, testing, and delivering software to their customers.
For the applications that run on the Anthos platform, your lines of business can prioritize which ones to modernize into microservices. Google and our SI partners provide multiple developer and operator tools to help enterprises in this modernization step. The following sections discuss these resources.
Spring Cloud GCP
As part of refactoring, you can port Java applications to modern Java frameworks like Spring Boot. The Spring Boot and Spring Framework provides a comprehensive programming and configuration model for modern Java-based enterprise applications. Spring Cloud provides tools for developers to quickly build some of the common patterns in distributed systems—for example, configuration management, service discovery, circuit breakers, intelligent routing, micro-proxy, control bus, one-time tokens, global locks, leadership election, distributed sessions, and cluster state.
To simplify using Google Cloud from Spring Boot applications, the Spring Cloud GCP project provides several libraries and features that support the following Google Cloud products:
- Pub/Sub: Spring Integration and Spring Stream
- Cloud Spanner, Datastore, and Cloud SQL: Spring Data
- Cloud Logging and Cloud Trace
- Firestore: Spring Data Reactive Repositories
- Cloud Storage: Spring Resource and Spring Integration
- Cloud Vision API: The
- Identity-Aware Proxy (IAP): Spring Security identity extraction from IAP headers
- BigQuery: Spring Integration
Google Cloud provides tools that assist you in creating modern containerized Java applications. Some of these tools include the following:
- Cloud Code. Cloud Code provides IDE support for the full development cycle of Kubernetes applications, from creating a cluster for development and testing to running a finished application in production. Cloud Code provides run-ready samples, out-of-the-box configuration snippets, and a tailored debugging experience to simplify developing with Kubernetes. Cloud Code provides a streamlined Google Kubernetes Engine (GKE) experience that simplifies creating clusters hosted on Google Cloud and better integrates with Google Cloud tools such as Cloud Source Repositories, Cloud Storage, and a variety of Cloud libraries. You can use Cloud Code with either VS Code or IntelliJ.
- Artifact Registry. Artifact Registry provides a central location to store artifacts and build dependencies as part of an integrated Google Cloud experience. Artifact Registry provides a single location for managing packages, libraries, and Docker container images. You can use these artifacts (packages and container images) in a modern CI/CD pipeline, which is described earlier in this document.
Build tools like Jib and Buildpacks. Jib and Buildpacks let you build containers using the Java tools you already know (such as maven or gradle). Without such build tools, you must manually create and test the Dockerfile. This manual approach requires a host with the Docker daemon running for creating and running the containers. This process includes a few more steps and can be repetitive for developers who want to push their code to production as quickly and seamlessly as possible. In a single build step, Jib orchestrates the build of the binary, creates the container image, and pushes the image to a container registry. Jib uses build tools familiar to developers, increasing developer productivity. After you push the Java container to the registry, you can deploy it through a CI/CD pipeline. The following diagram shows this overall flow for Buildpack or Jib.
Replatforming to open source application servers
For some applications, refactoring Java applications also requires replatforming Java application servers. To reduce licensing costs, Java applications running on commercial application server platforms (for example, WebSphere or WebLogic) are replatformed to open source components (for example, JBoss or Tomcat).
Legacy Java application architecture
Legacy Java applications generally use a 3- or 4-tier JEE architecture. JEE architecture supports component-based development of multi-tier enterprise applications. The following diagram shows the tiers typically found in a JEE application system.
The tiers are as follows:
- Presentation tier. In the presentation tier, web components, such as servlets and JavaServer pages (JSP or JSF) or standalone Java applications provide a dynamic interface to the middle tier.
- Application or middle tier. In the application tier, or middle tier, Enterprise Java Beans and web services encapsulate reusable, distributable business logic for the application. These server-tier components are contained on a JEE Application Server, which provides the platform for these components to perform actions and store data.
- Enterprise data tier. In the data tier, the enterprise's data is stored and persisted, typically in a relational database.
These different tiers are typically deployed in virtualized environments and rely on application servers, which can incur heavy licensing costs.
Benefits of moving to open standards
Moving to open standards reduces licensing costs and provides the benefits of cloud-based deployment methodologies and a cloud-based platform.
Tooling and solutions
Google Cloud partners with various system integrators (SIs) that have proven approaches and tools for replatforming JEE applications and adopting OSS technologies.
The process of replatforming starts with assessing your legacy Java applications. Assessment considers numerous factors, including complexity of an application, functionality, usage metrics, and business criticality. This assessment yields a prioritized list of application candidates to be replatformed. SIs provide developer and DevOps tooling that assists enterprises in removing all commercial application server dependencies from the source code. Tests and exit criteria are considered for each application before proceeding to the next stage (deployment). This stage is applicable for applications where the source code is accessible and the open source variant of the platform exists.
Refactoring best practices
The following two Google Cloud articles explain the benefits and a process of how to move from monolithic applications to microservices:
- Migrating a monolithic application to microservices
- Supporting your migration with Istio mesh expansion
Connecting microservices to VMs with Anthos Service Mesh
Enterprises have a variety of applications. Almost all enterprises end up with applications running on one of the following platforms:
- The Anthos platform for running microservices in containers
- A virtualization platform for running VMs
Often, services running in these two platforms depend on each other and must be able to securely communicate with each other. For microservices running on the Anthos platform, Anthos Service Mesh provides a security-enhanced connection to VMs running outside of Anthos in a virtualized environment.
Benefits of Anthos Service Mesh with VMs
- VMs can take advantage of the same Kubernetes-style declarative policy and security management framework as containers and microservices running on Anthos. This approach lets operators ensure there is a security-enhanced (mTLS) authenticated connection between containers running on Anthos and VMs running in another environment.
- No re-coding is required on existing VMs to make them appear as services to the Anthos platform. After the VM appears as a service, Anthos treats it like a service running in GKE.
- Operators get enhanced observability (metrics) for VMs without any instrumentation. The metrics appear as if it were a service running on Anthos.
VMs to containerization
Over time, you can move your existing refactored VMs to containers. This approach lets you move toward modernization at your own pace, prioritizing what applications to modernize.
- Read Google Cloud Enterprise onboarding checklist.
- Explore reference architectures, diagrams, tutorials, and best practices about Google Cloud. Take a look at our Cloud Architecture Center.