A production-ready Spring Boot banking application deployed on Amazon EKS with a complete DevSecOps CI/CD pipeline featuring Jenkins, ArgoCD, SonarQube, OWASP dependency scanning, Trivy container scanning, and comprehensive monitoring with Prometheus and Grafana.
This project demonstrates an enterprise-grade DevSecOps implementation for a Spring Boot banking application with:
- Application: Spring Boot 3.3.3 banking application with MySQL database
- Container Orchestration: Amazon EKS (Elastic Kubernetes Service)
- CI/CD Pipeline: Jenkins with 12-stage automated pipeline
- GitOps: ArgoCD for automated Kubernetes deployments with auto-sync and self-heal
- Code Quality: SonarQube for static code analysis
- Security Scanning:
- OWASP Dependency Check for vulnerability scanning
- Trivy for container image scanning
- Infrastructure as Code: Terraform for AWS infrastructure provisioning
- Package Management: Helm charts for Kubernetes deployments
- Monitoring: Prometheus + Grafana for comprehensive observability
- Auto-Scaling: Horizontal Pod Autoscaler (HPA) for dynamic scaling
| Category | Technology |
|---|---|
| Application | Spring Boot 3.3.3, Java 17, Maven |
| Database | MySQL 8.0 |
| Container | Docker |
| Container Registry | DockerHub |
| Orchestration | Kubernetes (Amazon EKS) |
| CI/CD | Jenkins |
| GitOps | ArgoCD |
| Code Quality | SonarQube |
| Security Scanning | OWASP Dependency-Check, Trivy |
| Package Management | Helm 3 |
| Monitoring | Prometheus, Grafana |
| Infrastructure | Terraform, AWS (EKS, EC2, EBS) |
| Metrics | Kubernetes Metrics Server, HPA |
- Region: us-west-1 (N. California)
- EKS Cluster: bankapp-cluster-v2
- Node Group: 2 x t2.medium instances
- EC2 Master: Jenkins server (t2.large)
- EBS CSI Driver: For persistent storage
- VPC: Default VPC configuration
- LoadBalancers:
- ArgoCD UI
- Grafana Dashboard
- BankApp Service
- Namespace: bankapp-namespace
- Deployments:
- BankApp (2 replicas with auto-scaling)
- MySQL (1 replica with persistent storage)
- Services:
- BankApp: LoadBalancer (external access)
- MySQL: ClusterIP (internal only)
- ConfigMaps: Application configuration
- Secrets: Database credentials
- PersistentVolumeClaim: 10Gi EBS volume for MySQL
- HPA: Auto-scaling from 2 to 5 replicas (40% CPU threshold)
- Ingress: NGINX ingress for routing (optional)
- Prometheus: Metrics collection and storage
- Grafana: Visualization and dashboards
- Node Exporter: System metrics
- Kube State Metrics: Kubernetes object metrics
- Git Checkout: Clone repository from GitHub
- Compile: Maven clean compile
- Test: Run unit tests
- Build Application: Maven package (creates JAR)
- SonarQube Analysis: Code quality and security analysis
- Quality Gate: Validate code quality standards
- OWASP Dependency Check: Scan dependencies for vulnerabilities
- Build Docker Image: Multi-stage Docker build
- Trivy Image Scan: Container security vulnerability scanning
- Push to DockerHub: Push image with version tag and latest
- Update Kubernetes Manifest: Update deployment YAML with new image tag
- Commit & Push Changes: Push updated manifest to trigger GitOps
- Automated versioning using Jenkins build number
- Code quality analysis with SonarQube
- Security scanning with OWASP Dependency-Check
- Container vulnerability scanning with Trivy
- Docker multi-stage builds for optimized image size
- Automated manifest updates for GitOps workflow
- Automatic cleanup and docker logout
- Quality gate validation
- Comprehensive error handling
- AWS CLI (configured with appropriate credentials)
- kubectl (v1.28+)
- eksctl (v0.167+)
- Terraform (v1.0+)
- Docker (v20.10+)
- Helm (v3.0+)
- Git
- EKS cluster creation and management
- EC2 instance management
- EBS volume creation
- IAM role and policy management
- VPC networking
- LoadBalancer creation
- AWS Account with appropriate permissions
- DockerHub account (for pushing images)
- GitHub account (for repository)
cd terraform
terraform init
terraform plan
terraform apply -auto-approvessh -i your-key.pem ubuntu@<EC2_PUBLIC_IP># AWS CLI
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
# kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
# eksctl
curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
sudo mv /tmp/eksctl /usr/local/bin
# Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# Docker
sudo apt update
sudo apt install -y docker.io
sudo systemctl start docker
sudo systemctl enable docker
# Trivy
sudo apt-get install -y wget apt-transport-https gnupg lsb-release
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
echo "deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | sudo tee -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install -y trivy
# Maven
sudo apt-get install -y maveneksctl create cluster \
--name bankapp-cluster-v2 \
--region us-west-1 \
--nodegroup-name bankapp-nodes \
--node-type t2.medium \
--nodes 2 \
--nodes-min 2 \
--nodes-max 3 \
--managedWait approximately 15-20 minutes for cluster creation.
eksctl utils associate-iam-oidc-provider \
--region=us-west-1 \
--cluster=bankapp-cluster-v2 \
--approveeksctl create iamserviceaccount \
--name ebs-csi-controller-sa \
--namespace kube-system \
--cluster bankapp-cluster-v2 \
--region us-west-1 \
--attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \
--approve \
--role-only \
--role-name AmazonEKS_EBS_CSI_DriverRole
eksctl create addon \
--name aws-ebs-csi-driver \
--cluster bankapp-cluster-v2 \
--region us-west-1 \
--service-account-role-arn arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):role/AmazonEKS_EBS_CSI_DriverRole \
--forcekubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# Wait for ArgoCD pods to be ready
kubectl wait --for=condition=ready pod -l app.kubernetes.io/name=argocd-server -n argocd --timeout=300s
# Expose ArgoCD server
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
# Get ArgoCD admin password
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -dkubectl apply -f - <<EOF
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: bankapp
namespace: argocd
spec:
project: default
source:
repoURL: 'https://github.com/ArsalanAnwer0/Springboot-BankingApp.git'
targetRevision: main
path: kubernetes
destination:
server: 'https://kubernetes.default.svc'
namespace: bankapp-namespace
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
EOF# Install Java
sudo apt update
sudo apt install -y fontconfig openjdk-17-jre openjdk-17-jdk
# Install Jenkins
sudo wget -O /usr/share/keyrings/jenkins-keyring.asc \
https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
echo "deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc]" \
https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
/etc/apt/sources.list.d/jenkins.list > /dev/null
sudo apt-get update
sudo apt-get install -y jenkins
# Start Jenkins
sudo systemctl start jenkins
sudo systemctl enable jenkins
# Get initial admin password
sudo cat /var/lib/jenkins/secrets/initialAdminPasswordAccess Jenkins at http://<EC2_PUBLIC_IP>:8080
- Maven Integration
- Docker Pipeline
- Docker
- Git
- SonarQube Scanner
- OWASP Dependency-Check
-
JDK (Manage Jenkins → Tools → JDK installations):
- Name: JDK17
- JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64
- Uncheck "Install automatically"
-
Maven (Manage Jenkins → Tools → Maven installations):
- Name: Maven
- MAVEN_HOME: /usr/share/maven
- Uncheck "Install automatically"
-
Dependency-Check (Manage Jenkins → Tools → Dependency-Check installations):
- Name: DP-Check
- Check "Install automatically"
- Install from github.com
sudo usermod -aG docker jenkins
sudo systemctl restart jenkins# Run SonarQube in Docker
docker run -d --name sonarqube \
-p 9000:9000 \
sonarqube:latest
# Wait for SonarQube to start
sleep 60Access SonarQube at http://<EC2_PUBLIC_IP>:9000
- Default credentials: admin / admin
- Change password on first login
-
Install SonarQube Scanner Plugin in Jenkins
-
Configure SonarQube Server (Manage Jenkins → System → SonarQube servers):
- Name: sonarqube-server
- Server URL: http://<EC2_PRIVATE_IP>:9000
- Server authentication token: (Generate in SonarQube → My Account → Security → Tokens)
-
Add SonarQube Token to Jenkins Credentials:
- Kind: Secret text
- Secret:
- ID: sonarqube
-
Configure SonarQube Scanner (Manage Jenkins → Tools):
- Name: SonarQube Scanner
- Install automatically from Maven Central
-
GitHub (ID: github):
- Kind: Username with password
- Username: Your GitHub username
- Password: GitHub Personal Access Token
- ID: github
-
DockerHub (ID: dockerhub):
- Kind: Username with password
- Username: Your DockerHub username
- Password: DockerHub password/token
- ID: dockerhub
- Open Jenkins → New Item
- Enter name: bankapp-pipeline
- Select "Pipeline"
- Under "Pipeline" section:
- Definition: "Pipeline script from SCM"
- SCM: Git
- Repository URL: https://github.com/YOUR_USERNAME/Springboot-BankingApp.git
- Credentials: Select your GitHub credentials
- Branch: */main
- Script Path: Jenkinsfile
- Click "Save"
# Add Prometheus Helm repo
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
# Create monitoring namespace
kubectl create namespace monitoring
# Install Prometheus + Grafana stack
helm install prometheus prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--set prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues=false
# Expose Grafana via LoadBalancer
kubectl patch svc prometheus-grafana -n monitoring -p '{"spec":{"type":"LoadBalancer"}}'
# Get Grafana admin password
kubectl get secret prometheus-grafana -n monitoring -o jsonpath="{.data.admin-password}" | base64 -dAccess Grafana at the LoadBalancer URL with username admin.
To enable Quality Gate feedback in Jenkins:
- Go to SonarQube → Administration → Configuration → Webhooks
- Click "Create"
- Name: Jenkins
- URL: http://<EC2_PRIVATE_IP>:8080/sonarqube-webhook/
- Click "Create"
# Change service type to LoadBalancer
kubectl patch svc bankapp-service -n bankapp-namespace -p '{"spec":{"type":"LoadBalancer"}}'
# Get application URL
kubectl get svc bankapp-service -n bankapp-namespace- SonarQube Analysis: Static code analysis for bugs, vulnerabilities, and code smells
- Quality Gates: Enforced quality standards before deployment
- OWASP Dependency Check: Scans all dependencies for known vulnerabilities
- Checks against National Vulnerability Database (NVD)
- Reports Critical, High, Medium, and Low severity issues
- Trivy Scanning: Comprehensive container vulnerability scanning
- Severity Filtering: Focuses on HIGH and CRITICAL vulnerabilities
- Automated Scanning: Every build is scanned before deployment
- Multi-stage Builds: Reduces attack surface by excluding build dependencies
- Secrets Management: Database credentials stored in Kubernetes Secrets
- Resource Limits: CPU and memory limits defined for all containers
- Health Checks: Readiness and liveness probes configured
- Network Policies: ClusterIP services for internal communication
- RBAC: Role-Based Access Control for service accounts
- Cluster Metrics: CPU, memory, disk, network usage
- Node Metrics: Individual node performance
- Pod Metrics: Application-specific metrics
- Custom Metrics: Application performance indicators
Pre-configured dashboards available:
- Kubernetes / Compute Resources / Cluster: Overall cluster health
- Kubernetes / Compute Resources / Namespace (Pods): Pod-level metrics
- Kubernetes / Compute Resources / Pod: Individual pod performance
- Node Exporter / Nodes: System-level metrics
minReplicas: 2
maxReplicas: 5
targetCPUUtilizationPercentage: 40HPA automatically scales the application between 2-5 replicas based on CPU utilization.
- Developer pushes code to GitHub
- Jenkins pipeline automatically triggers
- Pipeline executes all stages (build, test, scan, build image)
- Pipeline updates Kubernetes manifest with new image tag
- Pipeline commits and pushes updated manifest to GitHub
- ArgoCD detects the change (within 3 minutes)
- ArgoCD automatically syncs and deploys to EKS
- Kubernetes performs rolling update
- Old pods are gracefully terminated
- New pods become ready and start serving traffic
- Auto-Sync: Automatically deploys changes from Git
- Self-Heal: Automatically fixes drift from desired state
- Rollback: Easy rollback to previous versions
- Health Status: Real-time application health monitoring
- Sync Waves: Ordered resource deployment
.
├── kubernetes/ # Kubernetes manifests
│ ├── bankapp-deployment.yml # BankApp deployment
│ ├── bankapp-service.yml # BankApp service
│ ├── bankapp-hpa.yml # Horizontal Pod Autoscaler
│ ├── bankapp-ingress.yml # Ingress configuration
│ ├── bankapp-namespace.yml # Namespace definition
│ ├── configmap.yml # Application configuration
│ ├── mysql-secret.yml # MySQL credentials
│ ├── mysql-deployment.yml # MySQL deployment
│ ├── mysql-service.yml # MySQL service
│ └── persistent-volume-claim.yml # MySQL PVC
├── helm/ # Helm charts
│ └── bankapp/ # BankApp Helm chart
│ ├── Chart.yaml # Chart metadata
│ ├── values.yaml # Default values
│ └── templates/ # Kubernetes templates
├── terraform/ # Terraform IaC
│ ├── main.tf # EC2 instance configuration
│ └── variables.tf # Variable definitions
├── src/ # Spring Boot application
│ ├── main/java/ # Application code
│ └── main/resources/ # Application resources
├── Dockerfile # Multi-stage Docker build
├── Jenkinsfile # Jenkins pipeline definition
├── pom.xml # Maven project configuration
└── README.md # This file
# Verify Jenkins user is in docker group
groups jenkins
# If not, add jenkins to docker group
sudo usermod -aG docker jenkins
sudo systemctl restart jenkins# Check application status
kubectl get application bankapp -n argocd
# Force sync
kubectl patch app bankapp -n argocd --type merge -p '{"operation":{"initiatedBy":{"username":"admin"},"sync":{"revision":"HEAD"}}}'
# Refresh application
kubectl -n argocd patch app bankapp --type merge -p '{"spec":{"source":{"targetRevision":"main"}}}'# Check SonarQube is running
docker ps | grep sonarqube
# View SonarQube logs
docker logs sonarqube
# Restart SonarQube
docker restart sonarqube# Check pod status
kubectl get pods -n bankapp-namespace
# View pod logs
kubectl logs <pod-name> -n bankapp-namespace
# Describe pod for events
kubectl describe pod <pod-name> -n bankapp-namespace
# Check PVC status
kubectl get pvc -n bankapp-namespace# Verify MySQL is running
kubectl get pods -l app=mysql -n bankapp-namespace
# Check MySQL logs
kubectl logs -l app=mysql -n bankapp-namespace
# Test connectivity from app pod
kubectl exec -it <bankapp-pod> -n bankapp-namespace -- nc -zv mysql-svc 3306# Check Grafana service
kubectl get svc prometheus-grafana -n monitoring
# Get LoadBalancer URL
kubectl get svc prometheus-grafana -n monitoring -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'
# Check Grafana pods
kubectl get pods -l app.kubernetes.io/name=grafana -n monitoringAfter setup, you can access:
- Jenkins: http://<EC2_PUBLIC_IP>:8080
- SonarQube: http://<EC2_PUBLIC_IP>:9000
- ArgoCD: http://<ARGOCD_LOADBALANCER>
- Grafana: http://<GRAFANA_LOADBALANCER>
- BankApp: http://<BANKAPP_LOADBALANCER>:8080
This is a demonstration project for educational purposes. The credentials and secrets included are for development and testing only. For production deployments:
- Use AWS Secrets Manager or HashiCorp Vault for secret management
- Never commit credentials or private keys to version control
- Implement proper RBAC and network policies
- Enable pod security policies and admission controllers
- Use private container registries
- Enable audit logging
- Implement SSL/TLS for all services
- Use managed databases (RDS) instead of self-hosted MySQL
- Enable encryption at rest and in transit
- Implement proper backup and disaster recovery
- Complete DevSecOps pipeline with 12 automated stages
- GitOps deployment with ArgoCD auto-sync and self-heal
- Code quality analysis with SonarQube
- Security scanning with OWASP and Trivy
- Infrastructure as Code with Terraform
- Container orchestration with Kubernetes on AWS EKS
- Comprehensive monitoring with Prometheus and Grafana
- Auto-scaling with Horizontal Pod Autoscaler
- Helm charts for package management
- Production-ready architecture with high availability
This project is for educational and demonstration purposes.
Arsalan Anwer
- GitHub: @ArsalanAnwer0
- LinkedIn: Arsalan Anwer
- Spring Boot Team for the excellent framework
- Kubernetes community for comprehensive documentation
- Jenkins community for CI/CD best practices
- ArgoCD team for GitOps implementation
- SonarQube for code quality tools
- OWASP for security scanning tools
