Running applications as containers is the new default for cloud-native developed software and solutions. Many books, articles, and blog posts describe how to realize benefits by using a containers-based platform. But what about your legacy applications? What are you going to do with them? Can they benefit from a run-as-containers approach?
For many companies, a large part of the IT budget is used for maintaining and managing the technical debt of the legacy application portfolio. Therefore, can containerization be part of the evergreening process? Since only 20% of enterprise workloads moved to the cloud, the remaining 80% is not taking full advantage of the cloud-scale potential. Can containerization be a new cost-effective path to cloud for legacy apps? Because of their size and complexity, modernizing monolithic applications and databases is difficult in practice. Can a gradual adoption of cloud-native architectures be an approach to make our monoliths more agile and future ready?
This article addresses the question of how benefits can be realized by moving legacy applications to containers and to the cloud. I elaborate on the concept that containerization is not a binary thing, such as to be on containers or not to be. It is much more like a matter of scale to what extent the container concepts can be adopted and at what granularity.
For cloud-native scenarios, the use of containers is default and does not come with too much overhead cost because containers are part of the architecture from the start. In contrast, containerization of legacy apps always requires some form of transformation and corresponding investments. So, a cost-versus-benefit discussion needs to take place. I go into a business case model that helps you make these investment decisions by answering the question of when containerization of legacy apps makes sense and to what extent.
Containerization in the context of legacy app modernization
Containers and container orchestration tools, such as Kubernetes, are emerging trends well under way to become game changers in the software engineering and IT industry. The way that the containers concept provides an abstraction layer to infrastructure is unprecedented for software developers.
But before an app can be deployed in containers, you need to start thinking about when an app is suitable for containerization. Therefore, let’s first think about the term containerization because it can entail different things for different scenarios.
For cloud-native scenarios, containerization is the process of packaging compiled software code, libraries, configuration, and compute, network, and storage definitions into a set of containers and container management (Kubernetes) definitions. These containers are deployed on a runtime engine, such as Docker Engine or CRI-O. Scalability, high availability, and cluster management are arranged by the container orchestration tool.
In a legacy apps context, the meaning of the word containerization needs to be augmented to include all that is necessary to make an existing app ready to adopt the run-as-a-container concept. That is, to an extent that is well balanced with technical feasibility and expected business benefits.
By looking at containerization in this way, the next logical step is to introduce a scale to which a legacy app can adopt the run-as-a-container concept. This scale ranges from a simple containerization that does not change anything about the legacy app to more complex containerizations where apps are refactored or even recoded. So, containerization of legacy apps is a spectrum of simple, medium, and complex techniques that can be applied where appropriate from technical and business perspectives.
For example, imagine a spectrum from left to right representing simple to complex containerizations. At the leftmost side of this spectrum, you might package an application as-is to one or a couple of containers, store container images to a container registry, and run the app as one or a set of containers on a platform, such as Docker Engine or CRI-O.
Shifting to the right along the containerization spectrum, you might introduce container orchestration tools to start-stop-restart containers based on external events.
Further right along the spectrum, you can deploy parts of the legacy app that are suitable to run independently from the user or business logic state (stateless), such as the front end of a web application, as separate containers. These containers can be automatically controlled by Kubernetes to adhere to declared availability or scalability constraints.
Shifting a bit further to the right of the spectrum, you might partly refactor your legacy app by identifying the parts that are suitable to run as independent, yet coarse-grained, macroservices as part of the legacy app cluster.
Even further to the right along the spectrum, you can find techniques to refactor your application in such a way that microservices-level modules can be deployed and run independently, and you can fully use containers and Kubernetes as if your app was designed for them from the beginning. This is the rightmost and closest to cloud-native side of the spectrum, if you will.
Moving from left to right along this spectrum, the higher extent to which your app uses the containerized platform increases the number of benefits that it receives. As a result, you gain more cost-effectiveness and business agility. At the same time, the investments you must make to transform your legacy app goes up. More risks are introduced to these types of projects as the technical complexity increases to refactor or recode the app.
As with all migration approaches, choosing the right legacy containerization technique within this spectrum is a matter of striking the right balance between investment, business outcome, cost-effectiveness gain, technical feasibility, and risk appetite.
Emerging container technologies open paths to cloud
If and to what extent a legacy app can be containerized depends on its technology stack. In general, older technologies, such as older software development frameworks, make it harder to move an app to a container. Container technologies are becoming available that open up more possibilities to move an application to a container and then to a cloud.
Specific, light container versions of middleware. A key principle of a container-based architecture is lightweight components that can be restarted quickly. The aim is to keep the containers as lightweight as possible. For example, by using as little disk volume as possible for the installation files within the container. In most cases, the operating system files do not have to be part of the container since containers reuse the operating system files from the hosting platform. In addition, I see a trend where lightweight versions of middleware become available. For example, a light version of a web application server that includes just the components and files that are needed to facilitate the functions that the app in the container requires. This results in middleware software that contributes to a lower footprint and shorter restart times of containers.
Stateful support by Kubernetes for parts that manage a database. A container-based architecture works well for stateless designed applications. After all, resiliency and scalability are implemented by restarts of failed containers or initiate identical containers in parallel to perform the application functions at a higher load. This works best when no state must be managed in the application logic. However, most legacy applications require state management and data persistency. Kubernetes can coordinate states and data persistency by providing a mechanism to track storage volumes and maintain hostnames after a restart of the container by using the StatefulSet resource. This allows containerization of the parts of the legacy app that manages states such as databases.
Windows Server Containers. The advantage of Windows Server Containers is that it allows for containerization of .NET applications, which makes the scope for containerization much larger. Older versions of .NET apps are supported and you can eliminate conflicts between different versions of Internet Information Services (IIS) or .NET apps as they can co-exist too. Another interesting containerization case is to isolate an older Windows operating system version in a Windows Server 2016 container as a quick evergreen win.
Brief discussion of how to containerize legacy apps
The purpose of this article is to explain the what and why of legacy application containerization to help you evaluate if containerization is a beneficial approach for your situation. In future articles, I will describe the how of legacy app containerization, which is only a limited part of this article, as described below.
In my view, successful containerization programs require five critical components:
Asses your application portfolio to select the right containerization candidates. A cloud affinity assessment of your applications is necessary to identify the right candidates within your application portfolio that are suitable for an initial form of containerization. You will receive good results when the relevant parameters of your application are analyzed during this first pass affinity analysis. The parameters should include use frequency of the app, business criticality, programming languages used, operating system, hardware requirements, database technology, and infrastructure usage, to name a few important ones. The IBM Cloud Advisory Tool is an example of a tool that can support your initial cloud affinity assessment. After a first pass filtering is done, you need to perform a more detailed analysis per application to understand the technology dependencies. This analysis uses the code or deployment archives, such as web archives (WARs) and enterprise application archives (EARs), as input to determine which programming languages and frameworks are used. This analysis should also aim to identify the parts that might be able to run independently as a container, either as macroservices or even microservices. The Red Hat Application Migration Toolkit is an example of a tool that supports this detailed phase.
Select the right migration approach. Most legacy apps can move to containers without much initial adaptation. By following a containerization method on the left, less complex side of the containerization spectrum, you can manually build up a container image by defining a Dockerfile that includes all of the installations and configurations that are needed to run as a container natively on a server. A more supported way is using the Image2Docker tool, which takes virtual machine (VM) level images as input to create a Docker container image. Other tooling comes into play when the legacy app needs to be refactored or recoded. The most complex part of containerization is the movement of the container into a new cloud environment, where integration with the auxiliary system needs to take place, such as security authentication systems. Another thing to pay attention to is defining how the containerized application fits in the directory server domain. Reconnecting the containerized app to the required databases might require design, depending on your migration strategy for the databases, especially when the databases remain on premises. For such scenarios, your network design needs to be carried out to facilitate the exchange between the containerized app on the cloud and the on-premises database environment. The latter is also important for the connected applications that remain on premises.
Define and govern a fit-for-purpose target architecture to host your containerized apps. Many enterprises are on a path to incorporate containers and Kubernetes in their IT landscape. There are three important considerations here. First, building a containers and Kubernetes platform by yourself is complex. It requires making many interlinked architectural decisions, especially around network and security. Since most enterprises adopt two or more hyperscaler cloud platforms, deploying a containers and Kubernetes layer increases complexity with respect to the different flavors of services that hyperscalers offer. Therefore, I recommend an open architecture approach to create an overall control plane across the clouds. Such open architectures can be realized by Red Hat OpenShift, which is available on all major hyperscalers. Second, containers and Kubernetes services on hyperscalers come with different service levels. You must consider what level of services (no service level, service objective, or service level agreements) fits your IT enterprise strategy best. In many cases, enterprises adopt a fully managed containers and Kubernetes service to free up resources to focus on applications and business processes. Third, building a containers and Kubernetes platform is a journey. Using a grow-as-you-go model for the services you need to run your initial workloads as containers is the best approach to balance your investments with outcomes. For example, you might start with Windows Server Containers just to host your Windows and .NET workloads.
Reuse and govern recipes, patterns, and standards. Through my work with clients across industries, I learned that capturing successful patterns and recipes for solution development and application modernization is key to repeatable success and to scale within the working domain and beyond. Repeatable patterns and recipes should be captured to assess, migrate, and run applications as containers, providing a detailed description of what works and what doesn’t work in the context of the specific enterprise IT landscape. A well-governed and maintained containerization playbook is a good way to capture these recipes and standards.
Develop a business case to progress your containerization program. A consistent business case development approach is important to fuel your containerization program. I talk about the business case elements further down in this article. Continuous business case development aligns investment with outcome and changes over time when more container technology becomes available and matures. For example, an enterprise can focus on quick wins first to move Linux-based web applications to containers, which benefit from higher infrastructure utilization and lower application management costs.
Technical benefits of containerizing legacy apps
There is a fundamental difference between the results after containerization of a legacy application versus the results after virtualization. Virtualization focuses on how infrastructure can be defined and shared to host applications. Virtualization manages the dependencies with the infrastructure resources that provide a layer to run applications. In contrast, containers focus on the app requirements that need to be fulfilled by infrastructure. Containers and Kubernetes support a declarative approach to managing these non-functional requirements. Imagine a traditional technology stack with hardware, an operating system, and a hosted application. Virtualization looks from the app down to the infrastructure, while containers and Kubernetes look up to the application.
In the following sections, I discuss some specific technical advantages that containers and Kubernetes create for legacy applications. The advantages divide into three groups: improved service operations, hybrid cloud adoption, and application modernization acceleration.
Improved service operations
Faster handling of containers through lower footprint. As I mentioned previously, the total disk volume that a container needs to run an application is lower than that of VMs. As a result, containers are more lightweight to operate. For example, the start-up time for containers can be within seconds, which allows for high-speed service recovery by just restarting a fresh container.
Readiness for Kubernetes container orchestration. After a legacy application is containerized, it can use container orchestration capabilities, such as those from the de facto leader, Kubernetes. You can achieve better resiliency and scalability for your app by just defining requirements and constraints that the application should adhere to. Kubernetes takes care of the container management to guarantee that your app runs according to these requirements. This increases the programmability of how and under what constraints your app should run. It changes the way service operations work from performing the tasks and processes to run the application to an approach where you just define the outcome of the service (declarative).
Better service automation. Kubernetes container orchestration is implemented by YAML configuration files that define the outcome of the application service in terms of where it should be deployed, where it should be replicated in cases of higher load or fail-over, or how to manage persistency. In this way, deployment, scalability, resiliency, and monitoring are fully automated by the Kubernetes platform. The higher scale of automation contributes to cost takeout of service management.
Easier flow of changes to production and continuous delivery. The declarative approach to deployment that I previously mentioned recognizes an automatic code-to-deployment process. This allows for an easier flow of changes to production and contributes to continuous delivery of application features to your business.
Increased resiliency leads to self-healing systems. The automatic fail-over of restarting new container instances when there is a problem can increase the overall resiliency of your application landscape. It also leads to a self-healing system approach with fewer manual interactions. This results in a higher uptime of your applications with less effort.
Faster problem detection through log collection and tracing. Although Kubernetes takes over many of the service management responsibilities, it is still important to analyze any failures that occur in your container landscape. Due to the Kubernetes cluster approach of a control plane that oversees worker nodes, you can identify problems with log collection and analysis at a fine-grained level. Open source capabilities such as the ELK stack are now the de facto standard to build a log data processing pipeline to an analytics engine that feeds graphical dashboards.
Hybrid cloud adoption
Software-defined deployment. Kubernetes and containers allow for a dense deployment of your application with a relatively loose coupling to your infrastructure. You can keep application and user domains separate with namespaces while you control your compute resource allocation, network, storage, and access control. This define-once-run-everywhere concept facilitates application deployment at a global scale and in a controlled and consistent fashion.
Higher portability of applications. The standardized foundational layer of container engines and Kubernetes makes it possible for you to deploy apps on different environments, even on different clouds, on premises, and at the edge. This accommodates loose coupling with cloud technology providers and increases your negotiation power for resource contracting.
Lower footprint on infrastructure resources. The container’s low footprint and fast deployment mechanism allows for smarter deployment on infrastructure, which leads to lower resource usage. In addition to lower storage use of the application installation files, you can share compute resources among a set of applications or across non-production and productions environments.
Application modernization acceleration
Legacy technology isolation. Modernizing your application landscape consolidates the number of technologies you must manage. However, it is hard to evergreen your landscape due to dependencies between your application code, and technology libraries and frameworks. Containers provide a way for you to isolate older technologies that are prerequisites for your application code without interfering with other application stacks.
No recoding at all. You can gain initial quick wins just by applying the simplest containerization technique possible without any recoding or refactoring of your legacy application. This low investment approach is a new path to the cloud and opens up the possibility to move more workloads to the cloud. Especially in cases where a VM lift and shift is complex due to dependencies on your underlying infrastructure.
Business case development for legacy transformation with containerization
Many organizations face the challenge of moving their legacy application estate to the cloud. With only 20% of enterprise workloads moved to cloud, enterprises are not taking full advantage of cloud-scale resources and elasticity, cloud-scale security, and automation potential. The technical advantages that are provided by containerization techniques create a new path to cloud for more workloads. This pays off in two areas: cost efficiency and business agility.
Infrastructure cost takeout. A software-defined deployment of applications to infrastructure and an adoption of open architecture with higher portability of workloads makes it easier to select the most economic infrastructure. You can deploy apps to several cloud technology providers or to on-premises servers if you need to adhere to global or local data requirements and constraints, for example. In addition, infrastructure sharing, or doing more with the same capacity, is a feasible scenario with containerized apps.
Service management cost takeout. Deploying applications as containers can be highly automated and lower the cost of service management. Besides, the self-healing mechanisms of Kubernetes clusters also contribute to lower operations risk and higher application landscape resiliency.
Acceleration of business value. Many organizations still face a long lead time for bringing new ideas into production. The containers and Kubernetes approach shortens that path. First, the development of a highly componentized deployment with containers allows you to change a limited scope of your application and deploy it to a limited scope of your production environment. In other words, the impact of a change is smaller in terms of cost, effort, and risk. Second, the automated deployment and continuous delivery allows you to promote smaller changes to production in a controlled way and at a much higher frequency, sometimes weekly or daily if necessary.
Security standardization and improvement. Container definitions and images are highly reusable. This allows you to standardize your stack and improve the governance of which technology is permitted and which is not. This higher control of applied technologies, and architectural and security patterns contributes to a higher integrity of the overall stack you use to host applications.
Summary and next steps
Containerization is an emerging modernization technique to move legacy applications to the cloud. A spectrum of containerization approaches allows you to select the right technique that balances your investments with business benefits. Successful legacy containerization programs include application candidate assessment, a factory approach to migration, a fit-for-purpose target architecture, best practices management, and continuous business case development.
A logical next step for you is to run a containerization pilot for some of your legacy applications to get an understanding of the cost takeout potential and business benefits. It will also provide you with insights on how your target architecture should look like to host a first wave of apps on containers.