VEELIX is a start-up building a web platform through which universities, schools, and private teachers can create teaching materials and administer their students. Students can communicate with each other, work on their exercise sheets and take exams.
The start-up did not have any IT infrastructure and internal processes for the developers to work efficiently. Naturally, the software developers wanted to start right away with coding. They chose a microservice approach, which created an even higher demand of good DevOps structures. The main problem was, therefore, to bring the microservices of both backend and frontend together and to work on them in a group of around 10-15 developers.
- Orchestrate containers with Kubernetes
- Aligning production and development environments with Helm/Helmfile
- Using Tilt for local development
The first step was to introduce Kubernetes for both local development (through Kind clusters) and the production system.
The code was centralized into a mono repository, as this was the easiest to manage. Within this repo, the different microservices were separated. The corresponding Helm charts, Dockerfiles and application configuration were also part of the repository.
The next challenge that Syself addressed was how to efficiently manage multiple microservices. Helm was chosen for its abilities of templating and packaging Kubernetes objects. As most of these microservices did not have special requirements (Kubernetes deployment, service, routing with Istio, scaling, and security), we used our Monochart. With its help, redundant Helm code was avoided.
Because of interdependencies of these microservices, Syself introduced Helmfile which allows managing multiple Helm charts efficiently, e.g. by applying them in a certain order. Helmfile started first the databases and then the microservices that used these databases. Then the database migrations ran and seeding jobs were started.
Using this setup, it was easy to configure new environments with just a few lines of code. All of these environments, both for local environment and production system, were aligned. Only very few parameters needed to be changed. For example, the domains or lighter databases for development with heavier production databases.
Thanks to Helmfile, the developers did not need any expertise in DevOps to change a few parameters. They were able to get different database seeding and verbosity levels or to additionally start debugging tools. The developers were empowered to take over some DevOps tasks to optimally configure their microservices.
Even though Helm and Helmfile provided very good opportunities to define different environments, they alone were not enough for developers to work efficiently. Therefore, a Tilt setup imitated a production environment on the local machine of the developers. All while keeping the speed of development similar to the one of developing stand-alone code.
In a central settings file, the developers defined exactly how their environment should look like. For example, which microservices they wanted to deploy and whether the images were supposed to be pre-built from a remote source or built locally (to be able to update it). Pre-built images were, of course, faster, so the developers typically used only few microservices with local builds.
This Tilt setup allowed developers to work in a Kubernetes environment with hot reloads in less than a second (e.g. for Golang apps with caching).
The Kind cluster and the applications managed by Helm and Helmfile running in different testing environments (incl. database seeding) also served as the basis for end-to-end tests in a CI system.
After finishing the project, VEELIX’s team was able to work efficiently together. Due to some issues with less powerful laptops, the memory consumption of the Tilt setup was dramatically reduced.
Unlike most developers were used to from earlier projects, no external APIs were used for testing. This allowed workflows like the following:
A frontend developer realizes that the backend microservice does not fully behave as expected. The owner of this backend service fixes the issue quickly and pushes the commit. The frontend developer switches the build type of the respective microservice to a local build and is able to test the fix immediately - without waiting for the CI/CD pipeline to create a new remote dev cluster with the fix.