Learn 12 Factor Apps Before Kubernetes

Have you ever worked at a company where you struggled with containerized apps but couldn’t quite express why?
My initial experiences with containers were at a company implementing them in every wrong way imaginable. For example, they ran databases inside a container with no external volumes. You read that right: They wrote the database storage to an aufs file system, which is not designed for long-term storage and is also very slow. When I mentioned this was a terrible idea because we could lose all the data, the answer was, “We are doing snapshots, so we are fine.”
The first apps they put into containers were not much better:
- They didn’t use environment variables for configuration; instead, they hardcoded configuration and mounted config files.
- The app died immediately when the database was unavailable; it didn’t wait or retry until it became available.
- There was terrible log messaging or logs that went to files, not stdout logging.
- They ran admin processes such as database migrations with a different app.
- Apps were needlessly stateful.
I solved most of these issues with entry-point scripts, as mentioned by Kelsey Hightower. But that’s a hacky solution to make up for terrible design. I remember coyly asking the developers to redesign their apps to address all these issues, with only my opinion to back me up. So I went online to do some research and found 12 Factor apps, which not only expanded and validated my points, but also gave me an excellent framework to back up my arguments.
Why Learn 12-Factor Apps
The 12-factor app methodology is a set of best practices for building containerized applications. Heroku introduced these practices in 2011, and they have since been widely adopted by software development teams worldwide.
The 12 factors provide a framework for building scalable, portable, maintainable and resilient applications. But perhaps the most important benefit is that they create apps that are easy for operators because they are designed to work seamlessly with any container orchestrator.
Kubernetes (K8s) works best with 12-factor apps because they are the best design practices for containerized applications. K8s, being a container orchestrator, is designed with the assumption that your applications are 12-factor apps.
Venturing into container orchestration without knowing how to engineer container apps will make operating them significantly more tedious to manage and less scalable. Sure, you can make monoliths and poorly designed apps run in Kubernetes. For example, you can mount volumes, run statefulSets and even do vertical autoscaling. But ultimately, you will have to contend with high operational costs:
Factor | Operational cost from not implementing |
Codebase | Apps with shared code base are harder to update and maintain. |
Dependencies | Time is spent finding and installing dependencies that should be clearly defined and packaged with the container. |
Config | Time and engineering is spent creating entry-point scripts and/or custom images from source code to change the hard-coded configuration. |
Backing Services | There are costly and time-consuming migrations and/or significant downtime when changing backing services. |
Build, release, run | App code and server running being treated as one leads to snowflake servers, painful maintenance and costly upgrades. |
Processes | Apps cannot horizontally scale when the state is shared. They also cannot be seamlessly replaced when upgrading them. |
Port binding | This means maintaining a web server container like Tomcat, causing significant configuration overhead and inflated app runtime. |
Concurrency | Apps not designed with concurrency in mind might use an excessive amount of resources, making a poor choice for scaling. |
Disposability | This results in data loss and performance issues due to a lack of graceful shutdown implementations and to not handling requests so they can deal with crashes. |
Dev/prod parity | It is impossible to predict how an app will behave in production. Downtime increases and impairs deployment velocity. |
Logs | It is tedious to send logs to a log warehouse. Container orchestrators expect logs to use stdout. |
Admin Processes | Time is wasted procuring a process that’s not part of the app or even doing it manually. |
Platform Engineering and 12-Factor Apps
Platform engineering helps deliver excellent self-service and great developer experience with an internal developer platform (IDP). And an IDP significantly reduces cognitive load for developers by providing golden paths and multiple abstractions based on user roles.
iIn platform engineering, 12-factor apps are important because developers self-serve their applications and infrastructure needs with an IDP. Internal developer platforms generally leverage container orchestration and shift the operation of services to developers, meaning that operational excellence is paramount to mitigate all the issues described above.
A platform orchestrator like Humanitec sits at the center of your IDP, making it easy to deploy workloads and all their resources to all environments with a simple workload specification.
Humanitec uses K8s to deploy workloads, therefore, designing 12-factor apps is crucial to maintain high operational performance. When using an IDP, developers self-serve their infrastructure and configuration needs, including deploying and operating applications. If they use non–12-factor apps, they will experience all the pain points described above.
For example, let’s say you have an application that uses a database. Suppose you’re not using a 12-factor app. In that case, you may need to mount configuration on disk, and whatever tooling you use to automate this process is likely designed to work with configuration as variables. If you have multiple environments, you will compound the problem.
Overall, 12-factor apps make deploying, managing and scaling applications easier. They also make it easier to collaborate with other developers.
Conclusion
The 12-factor apps framework provides best practices for building containerized applications that are scalable, portable, maintainable and resilient. They are essential for maintaining high operational excellence when deploying and operating applications in the cloud.
Platform engineering helps developers consume their own infrastructure and easily operate their own services, but the services must be designed with these tools in mind. We encourage all developers to adopt the 12-factor methodology to make their life easier operating them.
Have your 12-factor apps ready? Standardize and deploy them with Humanitec today.