How I Built a Scalable GitOps Platform from Scratch with ArgoCD, Helm, and ApplicationSet

In this blog, Iβll walk you through how I built a fully automated, multi-tenant GitOps platform from scratch using:
π ArgoCD (for GitOps deployment)
π¦ Helm (for templated applications)
π ApplicationSet (for dynamic app generation)
π Kubernetes (EKS-ready)
π‘ This platform is built on top of the Google Cloud microservices-demo β a real-world e-commerce application with 10+ microservices. All manifests, charts, and automation are available in my GitHub repo:
π― Goals of This Project
Learn how GitOps can work in a multi-team, multi-environment setup
Reduce duplication across Helm charts using shared templates
Scale microservice deployments using ApplicationSet
Handle secrets securely with SealedSecrets
π§± Folder Structure at a Glance
enterprise-multitenant-gitops/
βββ apps/ # Shared Helm chart templates
β βββ microservices-demo/charts/
βββ tenants/ # Environment-specific Helm values
β βββ microservices-team/overlays/dev/values-*.yaml
βββ clusters/dev/ # ArgoCD entrypoint
β βββ applicationset.yaml
βββ common/ # Kustomize overlays (RBAC, NS, etc.)
βββ secrets/ # Sealed secrets for each environment
π Step 1: Bootstrap ArgoCD into the Cluster
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
Then expose ArgoCD UI:
kubectl port-forward svc/argocd-server -n argocd 8080:443
Open http://localhost:8080 and log in.
πΈ ArgoCD Dashboard:
π§© Step 2: Build One Helm Chart for All Services
Instead of managing 10 separate Helm charts, I used one shared chart with templates like:
apps/microservices-demo/charts/
βββ deployment.yaml
βββ service.yaml
βββ hpa.yaml
βββ ingress.yaml
βββ values.yaml
And each microservice like adservice
, frontend
, or checkoutservice
just overrides values via:
tenants/microservices-team/overlays/dev/values-adservice.yaml
π¦ Step 3: ApplicationSet β GitOps Automation at Scale
Hereβs the magic. I created one ApplicationSet YAML like this:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: microservices-team-dev
spec:
generators:
- git:
repoURL: https://github.com/prathyushreddy123/enterprise-multitenant-gitops
revision: HEAD
files:
- path: tenants/microservices-team/overlays/dev/values-*.yaml
template:
metadata:
name: '{{path.basenameNormalized}}-dev'
spec:
source:
path: apps/microservices-demo/charts
helm:
valueFiles:
- '{{path}}'
destination:
namespace: microservices-team-dev
syncPolicy:
automated:
prune: true
selfHeal: true
π Now any time I add a file like values-productcatalogservice.yaml
, ArgoCD auto-generates a new app π
πΈ Dynamic Apps Created in ArgoCD:
π Step 4: Secure Secrets with SealedSecrets
kubectl create secret generic app-secret --from-literal=DB_PASSWORD=securepass123 -n microservices-team-dev
kubeseal --controller-namespace=argocd -o yaml < secret.yaml > sealed-secret.yaml
Place sealed secret under:
secrets/sealed/dev-app-secret.yaml
Commit β Sync β Applied securely π
π§ͺ Step 5: Deploy Everything
kubectl apply -f clusters/dev/applicationset.yaml -n argocd
Watch the apps appear:
kubectl get applications -n argocd
Or view in UI π―
β¨ What I Learned
Helm reuse is game-changing when dealing with 10+ microservices
ApplicationSet keeps your GitOps repo DRY, flexible, and scalable
Secrets can be handled securely even in a GitOps flow
ArgoCDβs UI + automation is a powerful combo
Feel free to βοΈ the GitHub repo or follow me for updates:
π https://github.com/prathyushreddy123/enterprise-multitenant-gitops
Let me know what you think β and if you'd like help building your own GitOps setup!
Subscribe to my newsletter
Read articles from Prathyush Dommata directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Prathyush Dommata
Prathyush Dommata
With 10 years of experience as a DevOps, SRE, and Cloud Engineer, Iβve worked across various tech stacks, always eager to explore new tools and best practices. Iβm particularly interested in AI and MLOps, and I enjoy diving deep into projects to gain hands-on experience. I believe the best way to learn is by building from scratch, and through this blog, I aim to share insights, challenges, and lessons from my journey. Whether it's automation, cloud infrastructure, or AI-driven workflows, Iβm always curious to explore whatβs next.