There are a lot of frameworks in app development, but not all of them are tailored for today’s cloud environment. Many of them lack modularity and flexibility; some don’t even leverage the benefits of using cloud computing. The 12-Factor application principles are designed specifically for modern, containerized cloud environments from the beginning. Each component is tailored to the flexibility of containers and cloud deployment, all while creating a standard for every team member—and third-party developers— to follow.
At the same time, the 12-Factor app creates a more straightforward approach to developing a cloud app with microservices. It takes into account the need for a positive user experience and how virtual environments can be utilized for higher availability.
So, the big question is: Are you 12-Factor app ready?
12-Factor Application Principles of Design
The 12-Factor app methodology has one main objective: to make the created app completely agnostic to cloud environments and dependencies. By achieving this objective, the app can be deployed in different virtual environments without the need for specific drivers or requirements.
The 12-Factors governed by this methodology are basic factors that determine the scalability and flexibility of your app. They are:
- Base Code: By using a uniformed codebase, apps can be deployed in different environments by customizing the configuration files rather than the apps or microservices directly. 12-Factor app config is the only thing you need to customize too; not the actual environment. As the 12-Factor website puts it, “A twelve-factor app is always tracked in a version control system, such as Git, Mercurial, or Subversion. A copy of the revision tracking database is known as a code repository, often shortened to code repo or just repo. A codebase is any single repo (in a centralized revision control system like Subversion), or any set of repos who share a root commit (in a decentralized revision control system like Git).”
- Dependencies: Package managers are the better, more efficient way to go when it comes to managing dependencies. Instead of adding dependencies to the codebase directly, you will have an easier time reproducing deployment across environments with a package manager. Moreover, “A twelve-factor app never relies on the implicit existence of system-wide packages. It declares all dependencies, completely and exactly, via a dependency declaration manifest.”
- Config: Config is treated as an Environment Variable, keeping the codebase free of environment-specific parameters. As mentioned in the first factor, configuration made independent is how you keep the app flexible.
- Backing Services: Ensuring compatibility with backing services is also an important step since it allows you to switch service providers or services without having to make changes to your code. You can keep microservices running in more environments with this approach.
- Build, Run, Release: The 12-Factor methodology separates Build, Run, and Release phases firmly. Code moves from one phase to another as they are reviewed and tested, which means the deployed codes are always up to the job they are meant to do.
- Stateless Processes: The days of adding state to your services are officially gone now that the 12-Factor app methodology supports stateless services all the way.
- Port Binding: This component is easy to deploy since it basically means making services available through port binding. The result is an app – with microservices as components – that is independent.
- Concurrency: To help make scaling up manageable, microservices are made as small as possible. Microservices can also be scaled up as units or as an entire app thanks to their stateless nature (Factor 6).
- Disposability: Yes, every process in the app is disposable. The approach makes handling failures and tracking inefficiencies easier.
- Dev-Prod Parity: Matching environments is the key to making your CI/CD cycles more effective.
- Logs: No good framework is complete without sufficient logging for debugging and general health checks. “A twelve-factor app never concerns itself with routing or storage of its output stream. It should not attempt to write to or manage logfiles. Instead, each running process writes its event stream, unbuffered, to stdout. During local development, the developer will view this stream in the foreground of their terminal to observe the app’s behavior. In staging or production deploys, each process’ stream will be captured by the execution environment, collated together with all other streams from the app, and routed to one or more final destinations for viewing and long-term archival. These archival destinations are not visible to or configurable by the app, and instead, are completely managed by the execution environment. Open-source log routers (such as Logplex and Fluentd) are available for this purpose.”
- Admin Processes: To complete the set, there is a need for management tasks to run as one-time processes rather than continuous cycles. Process formation is the array of processes that handle an app’s regular business (such as web requests, etc.,) when it runs. Alternatively, developers will often want to do one-off administrative or maintenance tasks for the app. Run these one-off admin processes in an identical environment as the regular long-running processes of the app. Run them against a release, using the same codebase and config as any process run against that release. Admin code must ship with application code to avoid synchronization issues. Such one-off processes can include:
- “Running database migrations (e.g. manage.py migrate in Django, rake db: migrate in Rails).
- Running a console (also known as a REPL shell) to run arbitrary code or inspect the app’s models against the live database. Most languages provide a REPL by running the interpreter without any arguments (e.g., python or perl) or in some cases have a separate command (e.g., irb for Ruby, rails console for Rails).
- Running one-time scripts committed into the app’s repo (e.g., php scripts/fix_bad_records.php).”
12-Factor Application Principles in Kubernetes
Many of the 12-Factor application principles are among the things that make Kubernetes so popular. Modularity, disposability, and concurrency are some of the strong suits of deploying apps and microservices using Kubernetes.
If you take a look at some 12-Factor app example deployments, you will also find that they work really well with Kubernetes pods and config files. Pods utilize port binding to remain visible, use config and requirements that are defined for each of them, and are incredibly scalable.
In fact, tools like the Horizontal Pod Autoscaler (HPA) make scaling Kubernetes pods easier. Lifecycle controllers that are native to Kubernetes, including DaemonSets and ReplicationControllers, allows for concurrent pods to make high availability possible.
States in a Stateless Environment
The only real challenge of adopting the 12-Factor application principles is whenever your Kubernetes application needs to use states (or you have to develop a stateful application). States are crucial in maintaining processes and enabling efficient resource sharing. It may seem like a complete dead-end at first, but there are ways to get around the states in Kubernetes when implementing 12-Factor.
Persistent datastore attached to the Config of your Kubernetes environment is an elegant solution to the issue. It allows you to have scalable pods without sacrificing data storage and the benefits of service states.
The 12-Factor approach is a framework that can be implemented in virtually any development situation. More importantly, it is a framework that works better with Kubernetes than many believe. If you are looking for a standard to adopt for your app development projects, becoming 12-Factor app-ready is the way to go.
Caylent provides a critical DevOps-as-a-Service function to high growth companies looking for expert support with Kubernetes, cloud security, cloud infrastructure, and CI/CD pipelines. Our managed and consulting services are a more cost-effective option than hiring in-house, and we scale as your team and company grow. Check out some of the use cases, learn how we work with clients, and read more about our DevOps-as-a-Service offering.