A sysadmin's guide to containerizing applications
For years, I floundered around with moving my own blog, ticket system, and wiki into containers. Literally, ticket #627: Migrate Crunchtools to Containers has been open in Request Tracker since March 11th, 2017. It's embarrassing to admit, given how deeply I've been involved with containers at Red Hat.
Since the early days of Docker in Red Hat Enterprise Linux 7 (circa 2014), to building OpenShift 3 on Kubernetes instead of Gears; from launching CRI-O as Technology Preview in OpenShift 3.7 to launching the Container Tools module with Podman, Buildah, Skopeo in RHEL 8; from the acquisition of CoreOS including Quay.io (one of my favorite services), to launching Red Hat Universal Base Image; I have been deeply using, testing, and even driving the roadmap for container technologies at Red Hat. Yet, it's taken me until 2020 to finish ticket #627.
Sure, I've built tons of demos, done tons of experiments, and thought for hours and hours about how to migrate things. I've had hundreds or thousands of migration conversations with customers and community members, but I just couldn't find time to convert my personal Linux services. So don't feel bad if you are still staring, longingly, from afar, at other people's fancy containerized services, as I've only recently gotten over the hump myself.
I've finally done it, and I want to share my technical solution and break down my conscious design decisions. I hope it will help you move your own services into containers. The goal is to give you some solid, concise, and technical guidance. Here are the three services we are going to take a hard look at in this article:
|WordPress||Blog||Apache, PHP, FastCGI Process Manager (FPM), MariaDB, WordPress|
|MediaWiki||Wiki||Apache, PHP, FastCGI Process Manager (FPM), MariaDB, Cron, MediaWiki|
|Request Tracker||Ticket System||Apache, FastCGI, Perl, MariaDB, Postfix, Cron, Request Tracker|
These are very common Linux services, and they seem so deceptively simple at first glance. But the truth is, they're really not. You need senior Linux skills to containerize them well. These are only samples, but deep inspection of these containerized services should provide a foothold for your own work.
If you search with Google, you will find pages and pages of blogs, white papers, and articles. A quick look at five or ten of the results will lead you to the same three main options:
To be clear, these are the same three options that people have had for many years. As an aside, before mainframes, there was no portability. You had to rewrite your application from scratch for every different computer (A Brief History in Code Portability). Since the advent of operating systems and standardized programming languages, some permutation of the same three options has existed. Here are some examples:
- Mainframe to Unix – mostly rewrite
- Unix to Linux – lift and shift, refactor, rewrite
- Bare metal to virtual machines – mostly lift and shift
- Virtual machines to cloud – mostly refactor, rewrite
- Windows to Linux – lift and shift, refactor, rewrite
- Linux processes to containerized Linux processes – lift and shift, refactor, rewrite
In fact, if you search for migrating to containers, the second article you'll find is one I wrote, delving into these three options and some techniques on how to analyze architecture, security, and performance: (Best practices for migrating to containerized applications – 11 pages). Also, here's a presentation I did covering the same topic: Containers for Grownups" Migrating Traditional and Existing Applications: Video and Slides.
For simplicity, I will briefly touch on the most essential parts of the above white paper and presentation. The vast majority of the software we use today was designed and written before Linux containers, so even when you write (or rewrite) software from scratch, you need the same skills. These skills will come naturally for Linux Systems Administrators and Architects. Now, let's dig into what I did specifically for my own services.
For my blogs, wiki, and ticketing system, rewriting and refactoring were completely out of the question. Now, you may be asking yourself, why don't you just move to Jira for ticketing, wordpress.com for your blogs, and some free service for your wiki? Well, I can't move for the same reasons most large enterprises businesses can't move. There is way too much data embedded in my services—from learning Jiu-Jitsu to home projects to changing the differential in my 2005 Crossfire SRT 6. Everything I have done over the last 10+ years is embedded in these Linux services. They are essentially an extension of my brain. There are nearly 1000 tickets in Request Tracker, 800 pages in my wiki, and over 200 articles on my two blogs. In fact, much like a large enterprise, I purposefully chose MediaWiki because I know that it will exist for as long as Wikipedia exists and will likely outlive me. I literally plan on writing my last MediaWiki entry a few days before I kick-off, so I just need MediaWiki to be around for another 20 or 30 years. Given my business needs, I chose lift and shift, with a little, teeny, tiny bit of refactoring mixed in.
Now, let's move on to the level of effort. Here are some guidelines on how difficult different services are to move:
|Code||Completely Isolated (single process)||Somewhat Isolated (multiple processes||Self Modifying (e.g. Actor Model)|
|Configuration||One File||Several Files||Anywhere in Filesystem|
|Data||Saved in Single Place||Several Files in Several Places||Anywhere in Filesystem|
|Secrets||Static Files||Network||Dynamic Generation of Certificates|
|Network||HTTP, HTTPS||TCP, UDP||IPSEC, Highly Isolated|
|Installation||Packages, Source||Installer and Understood Configuration||Installers (install.sh)|
|Licensing||Open Source||Proprietary||Restrictive and Proprietary|
|Recoverability||Easy to Restart||Fails Sometimes||Fails Often|
Once you have decided between lift and shift, refactor, or rewrite, you need to gauge the level of effort because even new applications (including micro-services) rely on programming languages and Linux daemons written before containers existed. Luckily, most Unix and Linux services are designed in a modular way that makes them conducive to separating code, configuration, and data. This is an absolute necessity when you move any software into containers. Furthermore, you need to think about installation (and updates in the case of WordPress), secrets, and recoverability. For a slightly deeper dive on the above table, see: Architecting Containers Part 4: Workload Characteristics and Candidates for Containerization
Separating services into code, configuration, and data requires a strong set of Linux skills. With a few hours of investment learning the key concepts in containers, a strong Linux Sysadmin or Architect can productively start to move services into containers. For a deeper dive into the skills necessary for a Linux admin to learn Linux containers, see: Lab: Linux Container Internals 2.0.
In our next article, we'll dig into WordPress and the steps you need to take to move your existing WordPress blog into a container.
This series is based on "A Hacker's Guide to Moving Linux Services into Containers" on CrunchTools.com and is republished with permission.