A production-grade Kubernetes setup for deploying a Spring Boot + MySQL application, leveraging:
- 🐳 Dockerized Spring Boot App
- 🐬 MySQL (as StatefulSet)
- 🔐 AWS Secrets Manager + External Secrets Operator
- ⚙️ Helm for templating
- 🧩 Kustomize for GitOps and environment-specific configurations
| Feature | Description |
|---|---|
| ✅ Spring Boot (Java 17) | RESTful API + Flyway DB migrations |
| ✅ MySQL StatefulSet | Durable DB with persistent volumes |
| ✅ AWS Secrets Manager | Centralized secret storage |
| ✅ External Secrets Operator | Auto-sync secrets from AWS to Kubernetes |
| ✅ Helm Chart | Templated Kubernetes manifests |
| ✅ Kustomize Overlays | Environment-specific config |
This setup includes both Helm and Kustomize to maximize flexibility across environments, pipelines, and tooling.
| Feature | Helm | Kustomize |
|---|---|---|
| Templating | ✅ Powerful templating engine | ❌ Static YAML only |
| Environment Overlays | ✅ Native support via overlays | |
| Secrets Integration | ✅ Through values + templates | ✅ With overlays + ESO |
| GitOps Integration | ✅ First-class support | |
| Packaging & Reuse | ✅ Versioned Helm charts | ❌ No built-in packaging |
| Learning Curve | Moderate (templating logic) | Low (pure YAML + patches) |
- Helm is used for reusable, versioned application charts.
- Kustomize is used for managing deployments to environments like
dev,staging, andprod. - Secrets are securely injected using AWS Secrets Manager + External Secrets Operator.
k8s/
├── base/ # Common base manifests
│ ├── deployment.yaml
│ ├── mysql-service.yaml
│ ├── mysql-statefulset.yaml
│ ├── service.yaml
│ └── kustomization.yaml
├── overlays/ # Env-specific config (Kustomize)
│ ├── dev/
│ │ ├── configmap.yaml
│ │ ├── kustomization.yaml
│ │ ├── mysql-external-secret.yaml
│ │ ├── namespace.yaml
│ │ └── secret-store.yaml
│ └── staging/
│ └── prod/
├── helm/ # Helm chart for full app
│ ├── Chart.yaml
│ ├── values.yaml
│ └── templates/
│ ├── deployment.yaml
│ ├── mysql-statefulset.yaml
│ └── springboot-service.yaml
└── values/ # Helm values per env
├── dev-values.yaml
├── staging-values.yaml
└── prod-values.yaml
---
# --------------------
# README Snippet
# --------------------
# ⚠️ Pre-requisite: Manually create the AWS credentials secret in your cluster
#
# This secret is required by the SecretStore defined in this chart. It must be created **outside Helm**:
#
# ```bash
# kubectl create secret generic aws-credentials \
# --from-literal=access-key-id=<AWS_ACCESS_KEY_ID> \
# --from-literal=secret-access-key=<AWS_SECRET_ACCESS_KEY>
# ```
#
# Replace `<AWS_ACCESS_KEY_ID>` and `<AWS_SECRET_ACCESS_KEY>` with your real values.
#
# Never commit your AWS credentials to Git or store them in `values.yaml`.
#
---
## ⚙️ CI/CD Pipeline (`.github/workflows/crewmeister-ci.yaml`)
| Stage | What it does |
|--------------|--------------------------------------------------------|
| `build` | Builds the app using Maven |
| `code-quality` | Runs tests and quality checks |
| `docker` | Builds multi-arch image and pushes to Docker Hub |
| `updatek8s` | Authenticates to AWS (OIDC), updates kubeconfig, and deploys Helm chart to EKS |
---
## 🔐 AWS + Terraform Setup
Before running the pipeline, ensure:
- You have a working **Terraform backend** in S3 + DynamoDB
- Your secrets are in **AWS Secrets Manager**
- External Secrets Operator is installed in the cluster
- You created the required OIDC IAM Role for GitHub → AWS access
# Create AWS Secret for DB password
aws secretsmanager create-secret \
--name devops-challenge-secret \
--secret-string '{"mysql-root-password":"dev"}'Apply Dev environment:
kubectl apply -k k8s/overlays/devDelete resources:
kubectl delete -k k8s/overlays/devInstall the Helm chart:
helm install my-app ./k8s/helm -f ./k8s/values/dev-values.yamlUpgrade:
helm upgrade my-app ./k8s/helm -f ./k8s/values/dev-values.yamlUninstall:
helm uninstall my-appkubectl port-forward svc/my-app-service -n dev 8080:80Access the app at: http://localhost:8080
- Keep AWS credentials secure. Use GitHub OIDC for temporary credentials.
- Secrets should be pulled via External Secrets, not stored in
values.yaml. - Use Helm for reusable packaging, and Kustomize for env-specific overrides.