2026 · Case study

AWS Retail Store — EKS Production Deployment

The flagship. Multi-language microservices on EKS with Helm umbrella charts, IRSA, HPA, StatefulSets, and full Prometheus/Grafana observability — driven by a single Jenkins shared library.

01

Overview

Everything I learned building RoboShop on VMs, rebuilt properly on Kubernetes. A 5-service polyglot retail app (UI, Catalog, Cart, Orders, Checkout) plus MySQL, Postgres, RabbitMQ, Redis, and DynamoDB — all deployed to Amazon EKS with zero static credentials, dynamic storage, autoscaling, and dashboards that ship with the workload.

02

Problem

Most students who 'know Kubernetes' have run kubectl apply on a tutorial manifest. The goal here was the opposite: prove I can operate a real cluster — OIDC-backed identity, StatefulSet storage, health-probe-driven rollouts, and a CI/CD system that scales across every service in every language from one shared codebase.

03

Architecture

Interactive architecture — click a component
pipeline · GitHub

Source of truth — push to main triggers Jenkins via webhook.

04

CI/CD Flow

  1. 01Jenkins shared library exposes three reusable Groovy functions: detectVersion(), dockerBuildPush(), deployK8s().
  2. 02detectVersion() reads pom.xml for Java, main.go for Go, package.json for Node — one pipeline definition works across every service.
  3. 03dockerBuildPush() builds and pushes SHA-tagged images to DockerHub; deployK8s() runs helm upgrade with env-specific values.
  4. 04When the deployment process changes, it changes in one place — not five Jenkinsfiles.
05

Infrastructure

  • Umbrella Helm chart with 10 subcharts: cart, catalog, checkout, orders, ui, mysql, postgresql, rabbitmq, redis, dynamodb.
  • Env values: dev uses local DynamoDB + static creds; prod uses AWS DynamoDB + IRSA. Zero secret sprawl.
  • IRSA fully implemented: OIDC provider on EKS, trust policy scoped to a single ServiceAccount, IAM policy scoped to a specific DynamoDB table ARN. Verified via env | grep AWS inside the pod.
  • StatefulSets with volumeClaimTemplates + EBS CSI (gp3, WaitForFirstConsumer) for MySQL and PostgreSQL — each replica gets its own volume.
  • HPA on all 5 application services at 70% CPU. Startup + liveness + readiness probes on every workload.
06

Technologies Used

AWS EKSHelm (umbrella + subcharts)IRSA + OIDCEBS CSI / gp3StatefulSets + HPAJenkins Shared LibraryPrometheus kube-prometheus-stackGrafanaDockerTerraform
07

Challenges

Challenge
Deploys took 12 minutes because pods restarted before dependencies were ready.
Resolution
Added startup probes tuned per service; Kubernetes stopped killing pods mid-DB-connect. Deploy time dropped to ~1.5 minutes. The lesson: startup probes, not liveness, were the missing piece.
Challenge
How do you actually prove IRSA is working end-to-end?
Resolution
Exec into the pod and check AWS_ROLE_ARN and AWS_WEB_IDENTITY_TOKEN_FILE in the environment. If they are set and the token exists, the OIDC chain resolved. That's the ground truth — not the trust policy JSON.
Challenge
One Jenkinsfile per service does not scale.
Resolution
Wrote a shared library with language-aware version detection. Every service's Jenkinsfile is now three lines: @Library, detectVersion(), deploy pipeline. Adding a new service is a Jenkinsfile stub, not a Jenkinsfile.
08

Lessons Learned

  • IRSA is a habit, not a feature. Once the OIDC → trust policy → SA annotation chain is muscle memory, static AWS keys become unthinkable.
  • Observability is a deploy-time concern. ServiceMonitors and dashboards ship inside the Helm chart, not as a follow-up ticket.
  • Shared libraries pay off the moment you have a second service. Write the abstraction before you write the second Jenkinsfile.
Source code
Full repository on GitHub
Open repo ↗