BLOG

Moving Monoliths in with Microservices

Lori MacVittie サムネール
Lori MacVittie
Published May 28, 2019

There's a fanciful belief that you can take a monolith, put it in a container, and voila! Modern architectural benefits of scale and speed.

In fact, a KubeKon 2018 survey suggested that's exactly what's happening for about 55% of respondents who indicated they leverage containers "as VM replacement for existing apps." Other surveys show a significant amount of Java - enterprise-class - applications running in containers. A 2018 Diamanti survey showed that while the majority (54%) were using containers for cloud-native apps, nearly one-third (31%) were using them to modernize legacy applications.

Reasons cited are generally operational; containers are seen as simpler to manage, despite the explosion of moving parts that must be managed. Performance and licensing fees, too, are often factors in the decision to move ahead with containers.

But that move isn't as simple as wrapping up a legacy app and dropping it in a container.

The reality is that monoliths - traditional client-server and web apps - have certain characteristics that make it difficult to lift and shift into a container and reap the operational benefits. Containers and microservices are not mutually inclusive, but both lean toward the 'built to fail' principles upon which availability of modern apps is based. That principle, if you're unfamiliar, is that if one container fails you merely start another to take its place. All containers are cattle and one is as good as the other.

In deliberately modern stateless application architectures, that is true. In traditional stateful application architectures, not so much.

You see, client-server and its successor, the three-tier web app, are generally stateful. They maintain certain information about the interaction between a client and the app in a session. That session might be held in memory on the app or web server, or in a separate database. Regardless of where that data is held, it is what makes the app stateful. That data is relevant and important to the operational of the app. It contains your shopping cart, the last page you visited, and other app-specific information.

Stateful sessions data

You can imagine that if the web/app server where that information is held suddenly disappears, it negatively interrupts a client experience. My cart is gone. I have to navigate back to where I was. I have to start over, basically.

This behavior is diametrically opposed to modern architectural principles that eliminate stateful operation of an application. It is the stateless nature of modern apps and services that make it possible to seamlessly substitute one instance for another when something goes wrong. It is the foundation upon which "built to fail" works. If you introduce state back into that equation, suddenly everything falls apart.

While the app will still work, the user is left in limbo. Their flow is disrupted, their transactions transported into the nether, never to be seen again.

This issue is one that gave rise to the need for application services to respect state. Once a client connected to a particular app/web server, it had to connect to that same app/web server for the life of the session. Cookie persistence and other mechanisms were developed to ensure that requests were routed to the same server every time. To preserve state.

The reality is that unless you're a green field startup, you have both traditional and modern applications running right now. While research varies on the topic, the split of "63% legacy / 37% new apps" remains largely consistent across time. Which means you need to support both legacy and modern architectures at the same time.

Simply moving the monolith into a container isn't going to help if you haven't addressed the divide between stateful and stateless.

ARCHITECURAL TIERING

The best - or at least the easiest - way to manage the migration of monoliths to a containerized environment is to ensure you can still respect state even in the stateless anarchy of a container cluster. That requires some smarts at the edge of the cluster, at the ingress where N-S meets E-W.

traditional v modern ops approach

A two-tiered approach supports both traditional and modern operational approaches as well as the migration of traditional, stateful apps into a containerized environment. By taking advantage of F5 Container Ingress Services (CIS), NetOps can continue to support the needs of stateful applications migrating their way into containerized environments. The connectivity ensures that traditional load balancing methods employing persistence can continue to operate and direct requests to the right container or straight into a traditional environment.

Meanwhile, BIG-IP can simultaneously direct requests for modern apps and APIs to an ingress controller inside the container cluster for distribution across as many stateless containers as is needed.

Transitions Take Time

The reality is that most organizations are supporting as many as five distinctly different application architectures - from monoliths to mobile to microservices. Simultaneously supporting an equal but distinct number of network and operational models is certain to overwhelm ops and negate the benefits of moving to modern architectures and environments. A strategic, two-tiered approach enables organizations to eke out the operational and business benefits of both models while transitioning to a majority containerized environment.

REFACTOR OPTION

One of the things you can do to ease this transition is to refactor legacy apps to take advantage of shared sessions. These sessions are held in a location separate from the web/app server - usually some sort of database - and can be accessed by any web/app server with the proper session id. You'll still need to keep track of the session id, but that can generally be accomplished via a cookie that persists regardless of the web/app server state. If legacy apps don't already use a shared session model, refactoring to do so is a fairly painless process compared to replatforming the entire app.

Because such transitions take time - we're still almost all operating in a multi-cloud model today, after all - it's important to find and take advantage of architectural options that maximize benefits without compromising on core customer needs like availability and security. Using a two-tier architectural approach provides both without constraining containerization efforts.