Automated CI/CD Pipeline for a Multi-Microservice Kubernetes Deployment
Built an end-to-end Jenkins CI/CD pipeline for a 6-service MERN-stack application (backend, frontend, auth-service, notification-service, stats-service, status-service) running on a self-hosted K3s cluster — turning a previously manual deployment into a fully automated push-to-deploy workflow.
What it does: a push to GitHub triggers Jenkins via webhook, which determines which services actually changed, builds and pushes only those as Docker images (native ARM64 builds via Buildx, hosted on Docker Hub), and rolls them out to the live cluster with health-checked deployments — without rebuilding or restarting unrelated services.
The interesting engineering problem: the hard part wasn't the happy path — it was reliably knowing what needed rebuilding. Diffing git history broke the moment a build failed partway through, since Jenkins' own "last successful build" bookkeeping doesn't distinguish between "actually deployed" and "reported success while silently missing a step." The pipeline was redesigned to read its own deployment state directly off the Kubernetes cluster, via a custom annotation written only after a verified successful rollout, rather than trusting its own history — making the system self-healing against partial failures, closer to how GitOps tools like ArgoCD reason about state. Along the way: Jenkins' Groovy sandbox restrictions, Docker-socket permission boundaries between host and containerized CI runners, and a corrupted-binary/wrong-architecture issue in the build toolchain, each traced to its root cause rather than papered over.
View on GitHub ↗