In the current tech landscape, handling infrastructure efficiently is crucial to keep up and meet our clients’ needs. At Devolution, we’ve set out on a mission to simplify and optimize infrastructure management based on Kubernetes by creating a unique solution as a Platform as a Service (PaaS) that can be applied across all of our clients. And our go-to tool for achieving that is Helmfile.
Helmfile is a tool used in the context of Kubernetes and Helm. We use it to create declarative deployments and implement templating - these features make it easier to set up distinct environments with less code, which we'll delve into later on.
Helmfile works with Helm but adds an extra layer of abstraction and management on top. It uses Helm commands under the hood to perform operations like installing, upgrading, or deleting releases. It helps us to deploy multiple Helm releases together using a single command. We have arranged our deployments in such a way that we can deploy a whole environment (with all supporting services like ingress controller/external-dns, etc.) in a matter of days.
Here’s an overview of Helmfile’s key features:
1. Declarative Configuration
2. Templating and Inheritance
3. Dependency Management
4. State Management
5. Rollback and Rollforward
6. Integration with Helm
7. Synchronization and Validation
Over the past years, we’ve worked with a lot of clients so we had an opportunity to encounter a number of different Kubernetes and non-Kubernetes setups, sometimes we did a refactor of existing infrastructure, and sometimes developed everything from scratch.
What is common for all clients (and software development in general) is the need for separate environments (e.g. dev, staging, UAT, production, etc.) - meaning that there will be a lot of deployment files, which are usually >90% the same across environments. The organization of those files proved to be a real challenge in order to keep everything logically organized, easy to understand, and maintainable.
We've identified two primary setups that we encounter frequently:
- One Cluster = One Environment: Here, each Kubernetes cluster corresponds to a single environment. It's a straightforward approach, but we've observed that over time requirements usually change, necessitating a shift from this model to the next one (also there is the cost perspective)
- One Cluster = Multiple Environments: In this alternative setup, a single Kubernetes cluster serves multiple environments. This approach offers more flexibility and cost reduction.
However, the fluid nature of client requirements often leads to transitions between these two setups. As a consequence, this leads to headaches related to file organization (namely the structure of values files located in `values/` directory - used by helmfile in order to load service configs).
During the years working with our clients, we settled on a structure that offers the most flexibility while being simple to understand: Kubernetes infrastructure is divided into clusters, and clusters are divided into environments - meaning that you can have as many environments per cluster as needed, or you can have only one.
The structure of `values/` directory looks like this (in this example the customer uses AWS EKS):
└── values
├── <customer>-production-eks # Cluster name
│ └── production # Environment name
│ ├── app # Client app (business logic)
│ └── infra # Supporting services (ingress, DNS, monitoring, etc.)
└── <customer>-staging-eks
├── staging
│ ├── app
│ └── infra
└── uat
├── app
└── infra
This structure allows logical separation between files that developers frequently change (app) and other services usually managed by the Infrastructure team (infra). Once you’ve quickly created a mental map of how everything is organized, it is easy to navigate any of the projects our team manages since we always use the same structure, and any major refactoring of core components is propagated as soon as possible to all of our clients.
In the next blog post, we will share more details on how we’re structuring environments directory, how we organize infra services, and how we decide which infra services or applications should be installed in each environment. Also, we will demonstrate how to define different versions of Helm releases for each environment and how we use templating in Helmfile in order to do that.
Say hi to hello@devolut.io if you want to find out more about how we work!