You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
End-to-end DevOps pipeline for a Java WAR application — from a GitHub push to a running container on AWS EKS — with code quality gates, image security scanning, zero-downtime rolling deployments, and Helm-managed releases.
graph TD
A[Developer pushes code] --> B[GitHub Repository]
B -->|Webhook trigger| C[Jenkins on EC2]
C --> D[Checkout]
D --> E[Build — verify WAR]
E --> F[SonarQube Analysis]
F --> G{Quality Gate}
G -->|Fail| Z[Pipeline Aborts ❌]
G -->|Pass| H[Docker Build]
H --> I[Trivy Security Scan]
I --> J[Docker Push to DockerHub]
J --> K[Deploy to AWS EKS]
K --> L[Helm Upgrade --atomic]
L --> M[Validate Deployment]
M --> N[Application Live ✅]
style Z fill:#cc0000,color:#fff
style N fill:#007700,color:#fff
style G fill:#ff8800,color:#fff
Loading
AWS Infrastructure
graph LR
subgraph AWS["AWS ap-south-1"]
subgraph VPC["VPC 10.0.0.0/16"]
subgraph AZ1["ap-south-1a"]
S1[Public Subnet\n10.0.1.0/24]
end
subgraph AZ2["ap-south-1b"]
S2[Public Subnet\n10.0.2.0/24]
end
end
subgraph EKS["EKS Cluster — java-eks-cluster"]
NG[Node Group t3.medium]
NG --> P1[Pod: java-app]
NG --> P2[Pod: java-app]
end
LB[LoadBalancer] --> NG
EC2[Jenkins EC2] --> EKS
end
User --> LB
DH[DockerHub] --> NG
S1 --> EKS
S2 --> EKS
# Create the S3 bucket for Terraform state (one-time — do this first)
aws s3 mb s3://vitthal-terraform-state-java-eks --region ap-south-1
aws s3api put-bucket-versioning \
--bucket vitthal-terraform-state-java-eks \
--versioning-configuration Status=Enabled
cd terraform/
cp terraform.tfvars.example terraform.tfvars
terraform init # downloads providers and modules, configures S3 backend
terraform plan # review what will be created
terraform apply # creates VPC + EKS (~15 minutes)# Configure kubectl to point to the new cluster$(terraform output -raw configure_kubectl)
kubectl get nodes
Also configure: Manage Jenkins → System → SonarQube servers — name SonarQube, add server URL.
4 — Create the Pipeline
New Item → Pipeline → Pipeline script from SCM → Git → this repo URL → Branch: */main → Script Path: Jenkinsfile → Save → Build Now
5 — Verify the Deployment
kubectl get pods -n java-app -o wide
kubectl get svc -n java-app
helm status java-app -n java-app
# Open the EXTERNAL-IP from the LoadBalancer service in a browser
6 — Destroy When Done (avoid AWS costs)
cd terraform/
terraform destroy
Architecture Diagrams
CI/CD Pipeline
AWS Infrastructure
Screenshots
Capture these after running the pipeline and add to docs/screenshots/ — they are the highest-value portfolio evidence.
#
Screenshot
What It Proves
1
Jenkins pipeline — all 10 stages green
Pipeline runs end-to-end
2
Trivy scan output in Jenkins console log
Security scanning is active
3
SonarQube dashboard — quality gate PASSED
Code quality enforcement works
4
DockerHub — multiple versioned tags (1, 2, 3...)
Pipeline ran repeatedly; image tagging works
5
kubectl get pods -n java-app — 2/2 Running
EKS deployment succeeded
6
helm status java-app — STATUS: deployed
Helm release is healthy
7
terraform apply terminal output
Real infrastructure was provisioned
8
Application in browser at LoadBalancer URL
End-to-end: the thing actually works
Troubleshooting
Problem
Cause
Fix
ImagePullBackOff
Image name in manifest doesn't match pushed image
Verify DOCKER_IMAGE in Jenkinsfile matches image.repository in values.yaml
Pods stuck in Pending
Node has insufficient CPU/memory
kubectl describe pod <name> -n java-app — check Events
Quality Gate always times out
Jenkins can't reach SonarQube
Check SonarQube server URL in Jenkins System config
Helm upgrade fails, auto-rollback
Pods crashlooping on new image
kubectl logs -l app=java-app -n java-app
kubectl fails in pipeline
kubeconfig missing on Jenkins node
Ensure aws eks update-kubeconfig runs before every kubectl command
Error acquiring state lock
Previous apply crashed mid-run
terraform force-unlock <LOCK_ID>
Trivy: many CVEs on base image
Upstream Tomcat image has unpatched CVEs
Pin to a newer patch version in Dockerfile
Learning Outcomes
Provisioning AWS infrastructure (VPC + EKS) with Terraform remote state and DynamoDB locking
Writing Jenkins declarative pipelines with proper credential handling, timeouts, and cleanup
Using SonarQube as a mandatory gate — waitForQualityGate makes it fail the build, not just report
Building Docker images with non-root users, pinned base images, and Docker HEALTHCHECK
Running Trivy image scans inside a Jenkins pipeline
Zero-downtime Kubernetes rolling updates with maxSurge and maxUnavailable configured
Liveness vs readiness probes — understanding the operational difference
Helm --atomic flag for automatic rollback when a deployment fails
Future Improvements
Improvement
Why Not Now
ArgoCD GitOps
Adds a full GitOps layer — good next project, not needed here
Prometheus + Grafana
Valuable in production; out of scope for this CI/CD demonstration
GitHub Actions as secondary CI
Worth learning after this pipeline is stable
Multi-environment Helm values
Good next step — add values-dev.yaml and values-prod.yaml
Built by Vitthal Misal — B.Tech CS 2025 | Cloud & DevOps
About
End-to-end CI/CD pipeline: Java WAR → Jenkins → SonarQube → Trivy → Docker → AWS EKS via Terraform and Helm