Understanding Your Legacy Environment – the Modernization Journey
Before you choose the right option to move your legacy estate to a hyperscale cloud provider such as Azure, you need to understand the current environment of your legacy estate to know the options that might exist. This chapter will focus on the areas you should consider. Also, while many of the concepts that we will discuss can be applied to other hyperscale clouds, this book will focus on Azure. So, let’s start with a list of topics that we will cover in this chapter to help you understand your current legacy estate:
- Current legacy hardware and operating system
- The current state of legacy applications
- What are the goals of moving to a hyperscale cloud such as Microsoft Azure?
- The need to choose a target architecture
- Consider your constraints
- How do you declare success for a legacy modernization to Azure?
Having been involved in many modernizations of legacy environments to Azure, understanding these fundamentals will both increase the likelihood of a successful modernization and provide you with an Azure estate that exceeds the capabilities of your current legacy environment.
Current legacy hardware and operating system
Many people think of mainframes when the term legacy estate is used. However, the term mainframe does not have the same meaning for all people. Additionally, there are non-mainframe systems that can either make up or surround a legacy estate. This section will focus on four types of legacy estates:
- IBM and Unisys mainframes
- IBM midrange
- Enterprise Unix
- Other legacy estates
IBM and Unisys mainframes
IBM mainframes have been around for over 50 years and have the largest share of the mainframe market. The current version is called the z series. Several operating systems can run on z hardware, including z/OS, z/VSE, z/TPF, and z/VM. Currently, IBM mainframes can also run Linux and specialty engines such as the z Integrated Information Processor (zIIP) and Integrated Facility for Linux (IFL). The most common operating environment we see is z/OS, which might also include zIIPs and IFLs in the same environment. This will be the type of IBM mainframe environment we will look at in this book for modernizing to Azure.
If you do have an IBM mainframe estate running z/OS, there are several other factors that you need to take into account before proceeding with an Azure cloud modernization. These include the mainframe size, features in use, and Service Level Agreements (SLAs). All of these factors need to be considered when modernizing to Azure.
The second largest mainframe market share belongs to Unisys. As with IBM mainframes, Unisys mainframes come in multiple versions. These include Libra (MCP) and Dorado (2200). To understand the differences, it is important to look at their history. Unisys is the result of a merger of two companies, Burroughs and Sperry. Libra comes from the Burroughs lineage. Dorado comes from the Sperry lineage. Keep in mind these are separate operating systems and require different modernization strategies.
As with IBM mainframes, you also need to take into account sizing, features, and SLAs.
For this book, we will consider IBM midrange systems to be POWER-based hardware that runs the iSeries OS. The IBM iSeries platform has been in existence for over 30 years and has included systems such as AS/400, System 36, and System 38. Many users of the iSeries platform also run mainframe systems. However, the iSeries is a distinct operating environment versus the IBM z series. As the name implies, midrange systems are typically smaller than mainframes. These systems may run mission-critical applications that require high performance. The iSeries operating system is tightly integrated with the POWER hardware to provide this high level of performance. Unlike the z systems, the iSeries is the only operating system for midrange. There are multiple versions of the iSeries in use today. But these share a common ancestry.
The POWER hardware can also run a Unix variant (AIX). This will be discussed separately in Chapter 3. Sizing, features, and SLAs are also factors for modernizing the iSeries.
While there are several versions of Unix, for this book, we will concentrate on AIX, Solaris, and HP-UX. Unix systems are very different than mainframe and midrange environments. Unix systems were one of the first operating system environments that promised the option of Open Systems. However, as it turns out, the Unix of Open Systems meant the operating system could run on multiple hardware platforms, not that applications developed for one platform could run without modification on another platform. Unix systems are still widely used in several systems. However, each major variant requires a different approach.
IBM AIX systems on POWER hardware are widely used and provide high performance and availability. Solaris is also widely used. Solaris can currently run on x86 but also continues to run on Sparc hardware. HP-UX is still available on HP Epic (Itanium)-based hardware. Enterprise Unix systems were developed over 30 years ago but are more closely related to today’s distributed and cloud systems. Enterprise Unix still has some legacy problems such as proprietary hardware/OS and agility.
Other legacy estates
Just to cover other legacy environments, there are several legacy operating systems and hardware. These include other z operating systems, such as z/TPF and z/VSE, other midrange systems such as Dec VAX, other mainframes such as Bull and NCR, and specialized operating systems such as HPE NonStop. While we will not go into detail about moving these environments to Azure, here are some options you can use for these environments that are similar to the areas we will cover:
- z/TPF: Similar to approaches for Enterprise Unix, but specialized throughput and availability
- z/VSE: Similar to approaches for z/OS
- VAX: Similar approach to Enterprise Unix
- Bull and NCR: Similar to the approach for Unisys
- HPE NonStop: Similar to z/OS, but with special attention to redundancy
These operating systems provide scale-up functionality similar to IBM and Unisys mainframes, and applications on these systems are typically written in legacy languages such as COBOL. This chapter will reference these systems in sections where features provided by them are discussed.
The current state of legacy applications
As with legacy hardware and operating systems, the current condition of applications that use your legacy estate is important to consider when you move to Azure. Here are the topics we will cover related to the current application estate:
- Scope of the legacy application estate
- Languages used in the current estate
- Third-party (COTS) applications
- Utilities (tools) used
- Operating system services
- Application-specific SLAs
Scope of the legacy application estate
While we recommend that you also do a detailed inventory and tools-based assessment of your legacy source code, there are some general rules of thumb you can use to scope out how to both accelerate modernization to Azure and take advantage of Azure services in the process.
For example, the total number of lines of source code is a good indicator of the effort needed to modernize to Azure. Lines of code are not necessarily a measure of complexity, as source code can often be converted using automated tools. However, lines of code will likely indicate the effort needed to test code once converted to Azure.
Another measure of complexity or effort deals with code interdependency. This is important as modules run independently and can usually be converted separately, thus simplifying the testing process. Otherwise, the interdependent code module will likely need to convert at the same time. For performance and testing, we advise using Azure tools such as Azure Monitor and Application Insights to assist with performance testing.
Another thing to consider is the possibility of unused code in your legacy estate. Many of your legacy applications were written across multiple decades. This means that your application may be full of dead code that is no longer used. Rather than converting and testing the dead code, running code analysis tools to identify code that is never called can accelerate modernization.
Identifying the data associated with an application you want to modernize to Azure is very important. For example, if you modernize the application code to Azure without also moving the associated data for that application, you are likely introducing latency that may not be acceptable to access that data.
Finally, identifying if you have all the source code and the current version is extremely important. A lack of source code will limit the modernization options you have.
Languages used in the current estate
Since legacy systems were developed over decades, there may be some obscure development languages that it might be hard to find cloud versions for or are simply no longer supported. More commonly, however, you will find older languages such as Cobol or PL/I that are not supported with common tools and IDEs in Azure without third-party Independent Software Vendor (ISV) compiler software.
In particular, if your goal is to move to Azure-native managed code solutions for your legacy applications, you may find the need to integrate your managed code (for example, Java or C#) with unmanaged code in C/C++ or other managed executables.
Third-party (COTS) applications
Another possibility is the presence of third-party software in the legacy environment. Since most legacy applications not written in Java or C# (or another managed language) are not compatible with Azure, we need to find whether the third-party ISV provides a version that is compatible with Azure. For example, a commercial off-the-shelf (COTS) application that currently runs on AIX may have a version that runs on x86 Linux. In that case, moving the COTS application to Azure is typically not a technical problem. There may be licensing issues that need to be addressed. But it’s not a technical problem. If that is not the case, you will likely need to find an alternative for the COTS application. In some cases, such as POWER platforms, running the COTS application as-is on Azure might be an option. Otherwise, an alternative application that runs in Azure will need to be found.
Utilities (tools) used by applications
Many applications depend on utilities that provide services by the operating system to function. This includes things such as queuing, transactions, data replication, scheduling, monitoring, backup, and printing. For example, many applications use queuing provided by MQSeries. When moving to Azure, you will need to decide if you wish to continue to use MQ, which is available in Azure, or use a native Azure queuing server such as Service Bus.
We recommend mapping all the utilities currently used by your legacy application with utilities available in Azure. In some cases, these may be native Azure services such as Service Bus, Azure Monitor, and Azure Data Factory. In other cases, third-party tools might be required for things such as printing and virtual tape.
Operating system services
A special type of utility deals with operating system services. This is particularly true for IBM mainframes and midrange. This includes features on the mainframe such as CICS, IMS DC, and Coupling Facility. When we look at these features further, CICS and IMS DC are really like application servers on the mainframe. So, on Azure, we need to look at things such as App Services or Tomcat hosted in Azure Kubernetes Service to provide similar functionality.
On the midrange, the operating system provides tight coupling with the database for applications, and integration with scripting using CL. For this type of functionality, we need to extract these functions from the applications and put them in the database, scripting language, or other utility functions on Azure.
The SLAs provided natively by Azure for virtual machines (VMs) and data solutions will likely meet the availability and recovery requirements for most legacy systems. However, there are some specific cases where that may not be the case.
Applications that were developed by legacy programmers often depend on proprietary features of the operating system to achieve high availability and resilience. An example would be COBOL applications run in a CICSPlex and use Db2 that runs in a Parallel Sysplex. In this type of scenario, the applications themselves are unaware of the underlying system software that provides application resilience and limits data loss. Application redundancy and data resilience in cloud systems such as Azure typically rely on scale-out redundancy to meet similar availability. The scale-out approach usually relies on the application to be able to restart. That logic might not be present in the legacy code being converted.
There are mitigating approaches that can be followed, such as using a caching service such as Redis Cache on Azure. However, either the ISV software being used for the application layer, or the application code itself, would need to be Redis Cache-aware.
Mainframe applications were typically developed as monoliths (single system, not distributed). This section covered the various requirements Azure needs to provide to offer the same type of robustness and features.
What are the goals of moving to a hyperscale cloud such as Microsoft Azure?
So, what are the reasons behind deciding on a migration or rewrite of an application or ecosystem of applications to Microsoft Azure? The answer to that question will no doubt be different for everyone. Typically, the reasons can be broken down into three general categories.
- Elastic scalability: Legacy systems were designed to run 24/7 and to support peak volumes, you were forced to design the supporting architecture appropriately. This meant that most architectures were over-provisioned. In Microsoft Azure, you can right-size your architecture and grow it as needed, either vertically or horizontally, due to the elastic nature of the cloud. This elasticity applies to the main elements of any data center – that is, its compute, storage, and networking. You pay for what you need and use and (more importantly) you do not pay for what you do not need. This can allow significant cost savings.
- CapEx versus OpEx: Traditionally, for legacy applications, a large capital expense (CapEx) was necessary to provision a data center. This meant a large outlay of cash for assets that started to immediately depreciate. In a cloud model such as Microsoft Azure, these costs are transformed into operating expense (OpEx). Operating costs are the day-to-day expenses necessary to run a business. Essentially, hyperscalers are similar to utilities, which offer a significant advantage since you do not need to depreciate assets and deal with obsolete hardware.
- Modern developers: COBOL is a procedural language that was created more than 50 years ago. Many mainframe applications were developed in COBOL and also Assembler. Since these languages are so old, there is no provision for things that are inherent in modern languages such as polymorphism and object orientation. Also, aside from a few colleges that teach COBOL, the population of COBOL developers in the world is decreasing. More and more developers are being trained in modern languages such as Java and C#. Moving to Azure allows you to leverage these new developers so that you can maintain these applications.
- Modern DevOps: The process of creating applications has come a long way since the use of tools such as Time Sharing Option (TSO)/Interactive System Productivity Facility (ISPF), which was the solution supplied by IBM for mainframe application development. In today’s cloud-based world, application pipeline management tools and repositories such as Git are the norm. Solutions such as Azure DevOps allow for the streamlined development of modern applications by provisioning developer services that allow teams to work and collaborate on code development and deploy applications.
- Modern architectures: We will explore this in more depth in Chapter 6 and Chapter 7, but many modernization efforts today are being driven simply by the need for your business to be more agile and leverage modern cloud architectures such as microservices. This is especially important in competitive industries such as finance, transportation, and retail. Modern architectures allow businesses to respond more quickly to changing business environments. In government settings, they allow government entities to respond more quickly to situations such as COVID-19 and new regulations.
Obsolete hardware is the major hardware-related factor. In my travels focusing on legacy modernization, I have been surprised by how many companies want to move to Microsoft Azure simply to get off aging hardware. There have been numerous occasions when customers have told me that they had to resort to eBay to buy hardware that was not manufactured and supported anymore. The only option was to modernize or be at the mercy of aging hardware. When you think about it, this was probably to be expected. These were very reliable systems. They just ran the business. Management changed and the business environment changed, but the legacy systems kept running until someone asked if they should be modernized.
So, cost, application development, and hardware are the key drivers for modernizing a legacy application. As you consider where you might be in the drivers listed earlier, keep in mind that there are many paths to modernization. This is the goal and objective of this book – to show you which path might be the best for the current situation you are in.
The need to choose a target architecture
Just as important as understanding the platform that you are moving from, you have to have a clear vision of what your target platform needs to look like. In Azure, this target platform will be quite different from the legacy platform, mainly because it will all be virtual. The need to define a target architecture for your legacy workloads is the first step in laying the foundation of your virtual data center in the cloud. The compute, networking, storage, and other ancillary services need to be thought out and defined prescriptively in Azure if you wish to have a scalable and manageable environment. An example here might explain this concept.
In Azure, one of the fundamental containers for resources is an Azure subscription. One approach that some have used when defining their Azure environment is to create one subscription and then create all the necessary artifacts and assets within that subscription. There are some inherent problems with this approach when it comes to manageability and governance. On the opposite end of the spectrum, there is the approach of overusing subscriptions since they provide such a nice security and billing boundary. The correct approach lies somewhere in the middle. This is where Azure Landing Zones can be very useful.
Azure Landing Zones
We will discuss Azure Landing Zones later in this book, in Chapter 6. For now, it is good to know that an Azure Landing Zone (ALZ) allows the Azure architect to create a prescriptive architecture typically defined in an Azure Resource Manager (ARM) template. This approach allows for a scalable and modular implementation that is highly agile and can be deployed for different purposes. A good example is standing up a replica of production for QA testing or possible training.
There are essentially two types of landing zones:
- Platform Landing Zones, which are typically used to provide centralized services such as networking and identity. These services will be used by various workloads and applications.
- Application Landing Zones, which are typically application-specific and are used, for example, as a way to ensure that group policies are being applied correctly for a particular application group.
For this book, we will focus on Application Landing Zones as our intent will be to migrate legacy applications.
One of the first questions that needs to be answered when you are defining the target environment is, What are my target application containers? Should I use virtual machines, typically called Infrastructure as a Service (IaaS), Kubernetes, or the more cloud-native microservices? There are pros and cons to each.
Infrastructure as a Service (IaaS)
IaaS uses Azure Virtual Machines as the application container. VMs have been leveraged for years both on-premises and in the cloud. Virtual machines are a virtual definition and implementation of a physical machine and as such, they require an OS and application software. This means that they take more time to deploy and manage than, say, something such as Kubernetes. Having said that, virtual machines can be grouped in application clusters within Azure and can horizontally scale. We will dive into this later in Chapter 6.
Here is an example of an architecture for multiple Mainframe workloads migrated to Azure. You can see that the primary site is replicated to a paired region where Azure Site Recovery (ASR) keeps the application tier virtual machines in sync, while Microsoft SQL Server Always On provides fault tolerance for the data tier:
Figure 1.1 – High-level Azure architecture for legacy systems
Azure Kubernetes Service (AKS) and microservices
Microservices decompose the applications running on virtual machines into independent modules that are loosely coupled and distributed. The benefits are applications that are much more scalable and agile but also more complex to manage unless you have a managed service such as Kubernetes. In Azure, this service is called Azure Kubernetes Service (AKS) and provides a way to orchestrate and define relationships between components.
Azure Functions and Service Fabric
There are other deployment vehicles for microservices in Azure, such as Azure Functions and Service Fabric. They offer similar benefits with some variations. We will discuss these later in Chapter 6.
Now that we have looked at the need to define a target architecture, let’s understand the constraints.
Consider your constraints
Most legacy modernization projects for moving to Azure have constraints, meaning there are non-technical constraints, such as time and money, or technical, meaning things such as scalability and performance that have to be addressed. This section will cover these constraints.
Many legacy migrations are bounded by time constraints. With mainframes, this is the process of renewing the mainframe hardware, which typically happens every 3 years. This can help define the time frame necessary for the migration to be completed. It is very important to understand the size of the workloads and the number of lines of code that need to be migrated to meet this time frame. There are various types of time constraints, depending on the industry you are in:
- Hardware renewal constraints: As mentioned earlier, these are for support and maintenance and are typically 3 to 5 years.
- Hardware supportability constraints: For most hardware vendors, they only support previous versions of the hardware back to a certain version. They vary by vendor.
Even though there are large parts of a migration that can be automated, another bounding factor is the number of resources necessary for the migration. This is extremely important when it comes to testing, both smoke testing and user acceptance testing. Human resources such as developers and testers are critical, as are resources such as testing and development environments.
And we cannot forget about funding the migration. There are multiple costs to consider that need to be aligned with the funding to make sure the migration is even worth the effort. Perhaps buying and implementing a COTS or Software as a Service (SaaS) solution would be more efficient:
- The cost of the Azure infrastructure: This cost is relatively easy to calculate. It involves mapping the compute from the legacy system to Azure vCPUs, as well as the storage and networking to the appropriate Azure artifact.
- The third-party software costs: Depending on the migration software vendor, there will be additional software costs for additional components of the solution. A good example is if the legacy solution leverages a scheduler on the legacy platform; a corresponding scheduler will need to be implemented in Azure.
- The migration cost: Even though automation can be used to minimize the number of people necessary to migrate a solution, the actual migration, be it a rehost, refactor, or rewrite, will be a significant part of the cost of the migration.
Now that we’ve looked at constraints, we will look at defining success for a modernization project.
How do you declare success for a legacy modernization to Azure?
In this chapter, we reviewed several different states that might comprise your current legacy environment. We also reviewed the goals you might have for an Azure solution and the constraints you currently face. Now, it’s time to discuss setting up realistic goals, or possibly multiple steps that might be needed to achieve those goals. The idea here is to have early success so that you can build on it. Legacy modernization projects can seem quite daunting, even when there are few or no technical hurdles that need to be overcome. That is why we believe early success makes the daunting task now look achievable.
To help with this, we believe there are several things you should consider.
Identify the first workload to modernize to Azure
This may sound obvious, but there may be several factors you might want to consider, such as the following:
- Will the first application provide a template for replicating similar applications that use Azure features, such as AKS or ASR? In other words, pick an application that has features in common with other applications you want to modernize. Do not choose a one-off.
- Find an application that can be done in a reasonable time frame and achieve a reasonable ROI. These are great measures of success.
- Be careful not to start with the most difficult application move. This is a recipe for failure.
- Make sure business continuity is a key part of the modernization to Azure process.
- Understand the effect latency might have on modernization. Unacceptable latency is another recipe for failure.
- Make sure that the team responsible for the modernization to Azure has the right training to take the application you choose to Azure.
- Make sure you have the proper testing and validation tools and reports to verify success. This could include the use of Azure tools such as Azure Monitor and Application Insights but may also include third-party analysis and benchmark tools.
Determine if modernization can be a multi-step process
Keep in mind that modernization can be a multiple-step process. For example, if you first need to move from on-premises to Azure, moving an application without changing the language might be a good first step. The second step might be to refactor the legacy language to a modern language. The third step might be creating an Azure-native solution.
While it is possible to move directly to an Azure-native solution, doing so will likely require both architecture and source code changes that will take extra time and require more testing. Also, going straight to an Azure-native implementation may be most successful with smaller application modernizations. This makes the process more manageable.
Establish hybrid and integration requirements
Most legacy applications are not standalone and self-contained. There is usually a need to both integrate and interoperate with other legacy applications or applications already on Azure. This means that a hybrid strategy for integration and interoperability is a key feature for success. In looking at the right application to modernize to Azure, there should be the right balance of hybrid or integration needs, along with the ability to segregate functionally so that things such as latency do not become a big issue. Fortunately, Azure provides tools that make creating a hybrid environment practical. They include the following:
- Azure Data Factory: For data ingestion and transformation
- Logic Apps: For low-code data integration
- Power Apps: To extend hybrid functionality with low-code solutions
- Azure Service Bus: For integration with MQSeries or other message environments
- Azure Event Hubs and Event Stream: To enable hybrid event logic
Establish repeatable processes
As a final thought for this chapter, an initial modernization success should also be a recipe for a repeatable process. While not all applications can be modernized to Azure in the same way, there are probably applications that can be categorized as being similar in their approach to Azure. Success in an initial modernization should provide a temple for other applications to follow.
From our experiences, repeatable processes can be achieved in modernization to Azure by first categorizing the application candidates into approaches that are appreciated for each category. Here are some examples:
- If an application currently meets business needs and requires minimal maintenance, then perhaps a rehost of that application or the use of an emulator would be the best option while keeping the same legacy language. This could provide a template for rehosting to Azure for your legacy estate.
- If an application currently meets business requirements but requires a lot of maintenance to the source code, it might be better to refactor (convert it into another language) to allow non-legacy programmers to maintain the application. This does not mean a complete re-architecture of the application, but it will allow you to maintain the application in a modern language. Any example would be refactoring to either Java or C#.
- Finally, if the application needs an overhaul for both business functionality and deployment. This type of application would be best reimagined as an Azure-native architecture.
A single approach may not be appreciated for all applications you want to modernize to Azure. In this case, you may want to create parallel tracks to achieve the optimal paths to Azure.
Now that we’ve looked at how to leverage a successful modernization project to lead to future successful modernizations, we will summarize this chapter.
In this chapter, at a high level, we looked at the overall process of defining, planning, executing, and reusing modernization projects for moving legacy applications to Azure. For the remainder of this book, we will cover additional details regarding each section of this chapter, starting with IBM and Unisys mainframes.