Share:

S

Shuja Akbar

in

devops

November 01 2025

GitOps Solution

#gitops

#devops

#microservices

#architecture

Introduction:

Today we will be developing modern GitOps Solution for managing infrastructure and application deployments. We will be deploying full stack microservices application using GitOps principles with ArgoCD, Helm, Kubernetes and Github Actions.

We will be using two github repositories for this solution

Core Microservices:

Here is the breakdown of all microservices Tech Stack and roles.

ServiceRoleTech
service-appReact frontend to visualize logsReact.js
service-apiExposes REST API to fetch logsFlask (Python)
service-dataPersists and retrieves logs from DBFlask + PostgreSQL
postgresCentralized log storagePostgreSQL

Architecture Overview:

This is how our final GitOps solution will looks like.

nextjs-simple-blog-template

Tech Stack:

  • ArgoCD
  • Helm
  • Kubernetes

Pre-requists: Code Editor, Docker, Minikube

Continous Integration:

Inside AppsLog repository, I have created git action workflow for CI. Using this workflow every code push creates a new release with version tags like v1.1.0 and Inside release pipeline we are creating docker images with newest version tags and pushing those images to Dockerhub. We are also updating version tags inside AppsLog-GitOps repository values.yaml file.

This is how our final git actions CI workflow looks like:

name: Release Pipeline
on:
push:
branches:
- main
jobs:
semantic-release:
name: Release Pipeline
runs-on: ubuntu-latest
concurrency: release
permissions:
id-token: write
contents: write
steps:
- name: Checkout Repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Python Semantic Release
id: release
uses: python-semantic-release/python-semantic-release@master
with:
github_token: ${{ secrets.GIT_ACTIONS_SECRET }}
# --- Build and Push Docker Image ---
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and Push Docker Image
uses: docker/build-push-action@v6
with:
context: ./service-api
file: ./service-api/Dockerfile
push: true
tags: |
${{ secrets.DOCKERHUB_USERNAME }}/service-api:latest
${{ secrets.DOCKERHUB_USERNAME }}/service-api:v${{ steps.release.outputs.version }}
- name: Build and Push Docker Image
uses: docker/build-push-action@v6
with:
context: ./service-data
file: ./service-data/Dockerfile
push: true
tags: |
${{ secrets.DOCKERHUB_USERNAME }}/service-data:latest
${{ secrets.DOCKERHUB_USERNAME }}/service-data:v${{ steps.release.outputs.version }}
- name: Build and Push Docker Image
uses: docker/build-push-action@v6
with:
context: ./service-app
file: ./service-app/Dockerfile
push: true
tags: |
${{ secrets.DOCKERHUB_USERNAME }}/service-app:latest
${{ secrets.DOCKERHUB_USERNAME }}/service-app:v${{ steps.release.outputs.version }}
provenance: false
build-args: |
APP_ENV=production
REACT_APP_API_URL="service-api:5000"
REACT_APP_API_URL_DATA="service-data:5000"
- name: Logout from Docker Hub
run: docker logout
- name: Checkout gitops repo
uses: actions/checkout@v4
with:
repository: shujaakbar2020/AppsLog-GitOps
token: ${{ secrets.GIT_ACTIONS_SECRET }}} # token with write permission
path: gitops-repo
fetch-depth: 0
- name: Update image tag in gitops repo (values.yaml)
run: |
git config --global user.email "shujaakbar2020@gmail.com"
git config --global user.name "Shuja Akbar"
cd /home/runner/work/AppsLog/AppsLog/gitops-repo
git checkout main
git remote show origin
git remote set-url origin https://${{ secrets.GIT_ACTIONS_USER }}:${{ secrets.GIT_ACTIONS_SECRET }}@github.com/shujaakbar2020/AppsLog-GitOps.git
FILE=values.yaml
yq eval ".service-app.image.tag = "v${{ steps.release.outputs.version }}"" -i "$FILE"
yq eval ".service-api.image.tag = "v${{ steps.release.outputs.version }}"" -i "$FILE"
yq eval ".service-data.image.tag = "v${{ steps.release.outputs.version }}"" -i "$FILE"
git add "$FILE"
git commit -m "chore: update image tag to ${{ steps.release.outputs.version }}"
git log
git push origin main

Releases:

Every time above git actions pipeline runs successfuly, it creates a new release for any feature, fix or any chore update. We mark every release with git tags.

  • Git tags:
  • nextjs-simple-blog-template
  • DockerHub tags:
  • nextjs-simple-blog-template

Update GitOps repository:

We also update the AppsLog-GitOps repository values.yaml file with updated docker image tags

service-api:
image:
repository: saakbar/service-app
pullPolicy: IfNotPresent
tag: "v1.0.1"
service-data:
image:
repository: saakbar/service-app
pullPolicy: IfNotPresent
tag: "v1.0.1"

Continous Deployment:

We will be using ArgoCD for CD. ArgoCD runs inside the Kubernetes cluster and continuously monitors the connected Git repository. We will be deploying helm charts for our microservices. We have created these helm charts inside our AppsLog-GitOps repository.

nextjs-simple-blog-template

These are list of resources created by our helm charts.

nextjs-simple-blog-template

Conclusion:

This project demonstrates a production-grade GitOps workflow using:

  • GitHub Actions -- CI
  • Docker -- Containerization
  • Helm -- Packaging
  • Kubernetes -- Orchestration
  • ArgoCD-- GitOps Engine

Git is now the control plane.

📂 You can explore the full implementation here:

Microservices: github.com/shujaakbar2020/AppsLog

GitOps Config: github.com/shujaakbar2020/AppsLog-GitOps

Built with ❤️ by Shuja Akbar | DevOps Engineer | Open Source Enthusiast. You can reach me here any time. I will also be sharing more DevOps related problems, keep visiting me.

Copyright © 2025 DevOps Guru

Privacy PolicyTerms and Conditions