Twelve Factor App best practices in microservices with MicroProfile and Kubernetes
As a microservices developer, you might be wondering whether there are best practices. Yes, there are: 12 Factor App is a widely adopted methodology for creating microservices. 12 Factor App clarifies the boundary between application and infrastructure, minimises divergence between development and production, and enables your microservices to scale up or down without significant changes to tooling, architecture, or development practices. The 12 Factor App methodology defines the theory but there is no known implementation.
At Devoxx UK earlier this year, I demonstrated how to create two 12 factor microservices (using Eclipse MicroProfile and Kubernetes) and deploy them to Minikube. If you want to watch the whole talk, here it is:
Here is a quick overview of how you can use MicroProfile and Kubernetes to implement the 12 factors when creating microservices:
-
Codebase
You can use GitHub repositories to provide a dedicated codebase per microservice so that each microservice can have its own release schedule.
-
Dependencies
Instead of packaging the third-party libraries inside your microservice, specify your dependencies in your Maven
pom.xml
or Gradlesettings.gradle
file. This enables you to freely move up to newer versions. -
Config
Configuration is one of the most important factors. The golden rule of developing microservices is to write once, configure everywhere. When changing configuration, you don’t want to repackage your microservices. The way to achieve this is to externalise the configuration from the microservice application code. MicroProfile Config enables you to place configuration in properties files that can be easily updated without recompiling your microservices.
-
Backing services
Treat backing services as attached resources. They should be configurable so that you can easily switch the attached resource by just changing the configuration. Again, MicroProfile Config can help here.
-
Build, release, run
Separate the build, release, and run stages. Seriously.
-
Processes
Microservices should be stateless. REST is a well adopted transport protocol, and JAX-RS can be used to achieve a RESTful architecture. Systems that follow the REST paradigm are stateless. In this way, underlying infrastructure can destroy or create new microservices without losing any information.
-
Port binding
Export services using port binding. In the world of microservices, it is common that microservices talk to each other. When deploying them in the cloud, the ports need to change, so it is important to have a way to rebind the port. MicroProfile Config can help this. You can specify the new port in Kubernetes ConfigMap, and MicroProfile Config automatically picks up the value to give the correct info to the deployed microservices. MicroProfile Rest Client can help with creating client code to connect from one microservice to another.
-
Concurrency
The microservices should be able to be scaled up or down, depending on the workload. Kubernetes autoscaler can help with this.
-
Disposability
Microservices should be robust but gracefully shut down when necessary. Microservices should be fault tolerant and able to function under any situation. MicroProfile Fault Tolerance can help out with this. They should also, however, be treated like cattle, not pets: without identity and be replaceable. If a microservice process is not healthy, underlying cloud infrastructure should be able to directly kill it and quickly start a new one.
-
Dev/prod parity
The best practice of operating on microservices is keeping development, staging, and production environments as similar as possible. Docker images are here to ensure that the environments stay the same so that you don’t run into the problem of “it runs on my laptop".
-
Logs
Treat logs as event streams. You should stream out logs in real time so that killing an instance does not cause logs to go missing.
-
Admin processes
Do not put one-off admin process inside your microservices; run them as Kubernetes tasks instead. In this way, your microservices can focus on business logic.
In summary, use MicroProfile and Kubernetes to help you follow the best practices of the 12 Factor App methodology when creating robust, scalable microservices.
For more detail on this, watch my Devoxx UK talk in which I demonstrate how to create two 12 factor microservices and deploy them to Minikube.
Learn more about MicroProfile Rest Client, MicroProfile Fault Tolerance, and MicroProfile Config in the Open Liberty guides.