GitOps Observability — Visualizing the journey of a container
By: Samiya Akhtar
Tags: Kubernetes, Azure, Continuous Delivery, DevOps, Gitops

Trivia app

I have a very simple Trivia web application that I would like to host on Kubernetes using the GitOps pattern. It contains a simple React frontend and a Nodejs backend that queries existing APIs on the internet for fresh trivia questions.

Even in a simple application such as this one, there’s two microservices since we have a separate dockerfile for the frontend and backend. This would mean that I need to setup CI pipelines for these individually, and one common CD pipeline should be sufficient to deploy the changes to the cluster.

I’m following the 5 minutes GitOps pipeline with Bedrock guide which creates a skeleton for all my pipelines and a starter HLD. My current CI setup looks like this:

High Level Definition (HLD)

Kubernetes manifest files define the final configuration of the deployment on the cluster. Being extremely error prone, helm charts are a great tool for templating Kubernetes resource definitions. In any application, there are multiple microservices (n) and that leads to (n) helm chart configurations. Bedrock uses the concept of a High Level Definition (HLD) that allows you to define the components of your application at a higher level.

For example, in my Trivia application I need to include the frontend and backend microservices. But at an even higher level, I want to include Traefik in the cluster. I’m looking at having my high level definition at the root folder look something like below:



type: component

subcomponents:

- name: hello-world-full-stack

type: component

method: local

path: ./hello-world-full-stack

- name: traefik2

source:

method: git

path: definitions/traefik2 name: default-componenttype: componentsubcomponents:- name: hello-world-full-stacktype: componentmethod: localpath: ./hello-world-full-stack- name: traefik2source: https://github.com/microsoft/fabrikate-definitions.git method: gitpath: definitions/traefik2

And the definition at the nested level to be:

name: hello-world-full-stack

type: component

subcomponents:

- name: backend

type: component

method: local

path: ./backend

- name: frontend

type: component

method: local

path: ./frontend

Who doesn’t love recursion!

Fabrikate is the tool behind HLD that simplifies the GitOps workflow: it takes this high level description of the deployment, a target environment configuration (eg. QA or PROD) and renders the Kubernetes resource manifests for that deployment by utilizing templating tools such as Helm. As you may have already guessed, it runs as part of the CI/CD pipeline that connects the HLD repository to the final manifest configuration repository!

Deployment Rings

I want to setup two environments, let’s say dev and prod for my application. But I want to run them on the same cluster to cut cost! I also want to be able to test my new features for the Trivia app in their own separate environments before I merge into dev or prod. Several customers have expressed interest in being able to test their features within an existing cluster before they make merge it into their next release.

This scenario calls for the concept of Deployment Rings — an encapsulation of a DevOps strategy to group your users into cohorts based on the features of your application you wish to expose to them, similar to A/B or canary testing but in a more formalized manner. Rings allow multiple environments to live in a single cluster with the help of a service mesh, by setting a header on their ingress routes. Each developer in the team would be able to test their features in their own rings before merging it into the formal production branch.

In the figure above, a single cluster has multiple deployment rings, and each of these rings is running off a branch in the source repository. For example, the production ring is deployed against the master branch and the dev ring is deployed against the develop branch. When a developer is testing their features before merging into develop , they're able to deploy a ring into the cluster, let's say feature_ring_1 and get feedback from their team before merging it into develop . Once the feature gets into develop , they can go through the testing process, and make it to staging , and then finally into master for production.

Connecting all the pieces together

Using Bedrock CLI, I created a High Level Definition for my Trivia app and hooked up the CI/CD pipelines for the repositories together.