⎈ Blue-Green Deployment on Amazon EKS Using CI/CD Pipeline 🟦🟩


Introduction:
In modern software development, keeping applications available while deploying updates is essential. Blue-Green Deployment is a reliable strategy that ensures seamless updates with zero downtime. By running two identical environments—Blue (current live) and Green (new version)—it allows traffic to switch smoothly between them, minimizing risks and ensuring continuous service during deployments.
What is Blue-Green Deployment?
Blue-Green Deployment is a strategy to minimize downtime and risks during software updates by maintaining two identical environments:
🔵 Blue Environment: Live environment currently serving user traffic.
🟢 Green Environment: Testing new release, isolated from live user traffic.
How Blue-Green Deployment Works:
🖥️Two Identical Environments (Blue and Green): You maintain two identical environments—Blue (current live) and Green (new version). Initially, all user traffic is directed to the Blue environment.
🚀Deploy to Green: When a new version or update is ready, it is deployed to the Green environment, while the Blue environment remains live, ensuring no downtime for users.
🔍Testing in Green: The Green environment undergoes rigorous testing, including smoke tests, UAT, and load tests, to ensure the new version is functioning as expected. During this time, users continue using the Blue environment without interruption.
🔄Switch Traffic to Green: Once testing is successful, traffic is gradually shifted from the Blue environment to the Green environment. Users begin interacting with the updated version seamlessly.
📺Monitoring: After the traffic shift, the Green environment is closely monitored to ensure stability and detect any issues that may arise post-deployment. This helps catch and address potential problems early.
⚠️Rollback if Needed: If any issues are detected during or after the Green deployment, traffic can be quickly reverted to the Blue environment. This makes rollback fast and minimizes risks.
🛠️Blue Becomes Idle: Once the Green environment is confirmed stable, the Blue environment becomes idle and can be prepared for the next update cycle.
🌟 Why Use a Blue-Green Environment?
🕒Zero Downtime Deployments: No disruption for users during updates. They can continue using the system while the new release is being deployed and tested.
⚠️ Risk Mitigation: If any issues arise with the new release, you can instantly switch back to the previous environment (Blue) without affecting users.
🔄 Safe Rollbacks: Rollbacks are simple and fast by directing traffic back to the original environment (Blue), avoiding complexity.
🔍 Real-World Testing: Test the new version thoroughly (e.g., smoke tests, load tests) in realistic conditions before it goes live.
📅 Flexible Deployments: Teams can deploy new features or updates whenever needed, without rushing.
💡 Resource Efficiency: Switch between environments seamlessly without the need to rebuild or reconfigure systems.
📝 Project Overview:
Blue-Green Deployment on Amazon EKS with CI/CD Pipeline Using Jenkins and Terraform
This project implements a Blue-Green Deployment strategy for a Kubernetes-based application hosted on Amazon EKS, with the infrastructure fully managed using Terraform. The Blue-Green Deployment approach ensures seamless updates with zero downtime by routing traffic between two environments—Blue (current live) and Green (new version)—through a LoadBalancer service once the new version passes all health checks.
🔑Key Components:
Terraform: Infrastructure management and provisioning.
Jenkins: Automating the CI/CD pipeline.
SonarQube: Continuous code quality and security analysis.
Nexus: Artifact management and version control.
Kubernetes RBAC: Secure cluster and resource access management.
🔄Seamless Application Updates:
Jenkins orchestrates the Blue-Green deployment process.
The new version (Green) is deployed alongside the live version (Blue) and tested thoroughly.
If Green passes health checks, Jenkins orchestrates the traffic shift, directing all user requests to Green with zero downtime.
🌍Real-Time Traffic Flow in Blue-Green Deployment:
External DNS Name:
Users access the application through the external DNS name.Load Balancer (LB):
The request first hits the Load Balancer.Configuration Check:
The LB checks the configuration (Blue or Green) to determine where to route the traffic.Blue:
If the configuration is set to Blue, it forwards the traffic to the Blue deployment.Green:
If the configuration is set to Green, it routes traffic to the Green deployment.Kubernetes Service (Cluster IP):
The traffic is directed to a Kubernetes service with a Cluster IP.Traffic Routing: 🔑The Kubernetes Service
routes traffic to the appropriate pods(Blue or Green)based on labels.
⚖️Load Balancer Service:
Instead of utilizing an ingress controller, the Kubernetes LoadBalancer service is employed to handle traffic routing between Blue and Green environments.
This ensures smooth transitions and uninterrupted traffic flow during deployments.
🎛️Traffic Shifting with LoadBalancer:
Amazon's Elastic Load Balancer (ELB) dynamically routes incoming traffic between the Blue and Green environments.
Once the Green environment passes its health checks, traffic is switched to Green.
If any issues arise, the pipeline quickly rolls back to the Blue environment, ensuring no disruptions to users.
🔙Rollback Mechanism:
In case of deployment issues or failed health checks during the Green deployment, the system provides an immediate rollback to the Blue environment.
This ensures that production remains unaffected.
🕛Continuous Integration & Deployment:
The entire CI/CD process is automated through Jenkins, covering:
Building the application,
Running quality and security checks with SonarQube and Trivy,
Storing the build artifacts in Nexus,
Deploying them onto the Kubernetes clusters in EKS.
Jenkins also handles post-deployment verifications to ensure successful updates.
Conclusion:
High availability, zero downtime, and fast rollbacks are ensured by the Blue-Green deployment setup.
Jenkins, Terraform, SonarQube, and Nexus provide a streamlined, automated, and secure deployment pipeline.
The architecture is scalable, making it ideal for production environments where user experience and service continuity are essential.

1️⃣ Set Up EKS Cluster Using Terraform
In this project, we will utilize Terraform to create an Amazon Elastic Kubernetes Service (EKS) cluster on AWS. Terraform, as our infrastructure-as-code (IaC) tool, will automate the setup of the entire EKS cluster, including worker nodes, networking, and other essential AWS resources.
Benefits of Using Terraform:
Version Control: Track infrastructure changes over time, making it easier to manage and revert when necessary.
Easy Modifications: Easily update or upgrade the cluster by modifying the code.
Scalability: Simplify cluster scaling based on the application's evolving needs.
Consistency: Ensure consistent setup and configuration across multiple environments.
Using Terraform simplifies cluster management, reduces manual errors, and improves the overall efficiency of managing our Kubernetes infrastructure on AWS.
2️⃣ Set up Jenkins, SonarQube, and Nexus
Jenkins: A CI/CD tool responsible for managing build, test, and deployment pipelines. Jenkins will either be installed on an EC2 instance or within a Kubernetes pod inside the EKS cluster, depending on the architecture.
SonarQube: A code quality and security analysis tool that integrates with Jenkins. It scans code for bugs, vulnerabilities, and code smells, ensuring that only high-quality code is deployed.
Nexus: A repository manager that acts as a central hub for storing and managing artifacts like Docker images and Maven dependencies. Jenkins will leverage Nexus to ensure smooth artifact management.
Together, Jenkins will be configured to work with SonarQube and Nexus, ensuring that code quality and artifact management are seamlessly integrated into the pipeline.
3️⃣ Set up RBAC for Kubernetes
Role-Based Access Control (RBAC) will be configured within the Kubernetes cluster to secure access and manage permissions. We will define roles, role bindings, and service accounts to control user and system interactions with the Kubernetes API and resources. This ensures secure access for:
Jenkins
Developers
Other integrated services
Proper RBAC configuration is crucial to maintaining a secure, compliant Kubernetes environment.
4️⃣ Create a Pipeline Job in Jenkins for Blue-Green Deployment:
Once the environment is ready, we will create a Jenkins pipeline that automates the Blue-Green deployment strategy:
Git CheckOut: Pulls the latest code from the GitHub repository (branch: main).
Compile: Compiles the project using Maven.
Tests: Runs tests, with the
-DskipTests=trueflag to skip actual test execution.Trivy fs Scan: Scans the file system using Trivy for vulnerabilities, outputting results in an HTML file.
SonarQube Analysis: Analyzes code quality using SonarQube.
Quality Gate Check: Waits for SonarQube quality gate results, ensuring code meets defined standards.
Build: Packages the application using Maven, skipping tests.
Publish Artifact to Nexus: Uploads the generated artifact (application package) to a Nexus repository.
Docker Build & Tag Image: Builds a Docker image for the application and tags it with the selected Docker tag (blue or green).
Trivy Image Scan: Scans the Docker image for vulnerabilities and outputs the results.
Docker Push Image: Pushes the built Docker image to a Docker registry.
Deploy MySQL Deployment and Service: Deploys MySQL to Kubernetes using a predefined deployment file.
Deploy SVC-APP: Deploys the service for the application (bankapp-service) if it doesn't already exist.
🛠️ Tools Involved:
Terraform: For provisioning EKS Cluster.
Jenkins: For automating the CI/CD pipeline.
SonarQube: For static code analysis and code quality checks.
Nexus: For artifact storage and management.
Trivy: For scanning vulnerabilities in files and Docker images.
Docker: To containerize applications.
AWS EKS: The managed Kubernetes service on AWS, which hosts the Kubernetes cluster.
Kubernetes (AWS EKS): For managing containerized workloads.
🎯 Prerequisites:
Basic Understanding of CI/CD: Familiarity with Continuous Integration and Continuous Deployment.
AWS Account: Access to create and manage EC2 instances and EKS.
Git Knowledge: Experience using Git and GitHub.
Linux Commands: Basic experience with terminal commands and SSH access.
Jenkins, Docker, and Kubernetes knowledge: Understanding of basic setup and usage.
🛠️ Setup EKS Cluster Using Terraform
Deploy an Amazon EKS cluster on an Ubuntu 24.04 LTS VM using Terraform.
Task 1: Setting Up Your Environment
Step 1: Launch an EC2 Ubuntu Instance
Log in to the AWS Management Console.
Navigate to the EC2 Dashboard to launch a new instance.
Launch a new instance:
AMI: Ubuntu 24.04 LTS
Instance Type: c5.large (optimal for compute-intensive workloads).
Region: North Virginia (us-east-1)
Tags: Name it EKS-Cluster.
Key Pair: Create EKS-keypair.
Security Groups:
Open Port 22 (SSH)
Open Port 80 (HTTP)
Configure Storage: Set root volume to 20 GiB.
Launch the instance.
Connect to the EC2 Instance using MobaXterm or PuTTY:
Username: ubuntu
Private key: EKS-keypair
Step 2: Install Updates and Required Packages, AWS CLI & Configure
- Connect to your EC2 Instance via SSH. Once connected, set the hostname of the instance:


Once you connect to the terminal of EC2, you will look like this

Set the hostname of the instance
sudo hostnamectl set-hostname EKS-cluster
bash

- Update the package lists & install the required packages (wget and unzip):
sudo apt update
sudo apt install wget unzip -y
- Install AWS CLI
# Download the AWS CLI installer
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
# Install unzip if it's not already installed
sudo apt install -y unzip
# Unzip the downloaded AWS CLI package
unzip awscliv2.zip
# Run the AWS CLI installer
sudo ./aws/install
This step installs the AWS CLI, allowing your VM to interact with AWS services.


- Configure AWS CLI:
# Configure AWS CLI with your credentials
aws configure
Theaws configure command sets up your access and secret keys to authenticate with AWS.
Step 3: Install Terraform
sudo snap install terraform --classic

This installs Terraform using the Snap package manager, simplifying the installation process by managing dependencies.
Clone Your Project's GitHub Repo
Clone the git repository for the EKS cluster code:
https://github.com/Sandhyagito/Blue-Green-Deployment-Project
git clone https://github.com/Sandhyagito/Blue-Green-Deployment-Project.git

Provision Infrastructure using Terraform
Navigate to the /cluster folder:
cd Blue-Green-Deployment-Project/Cluster

Key Terraform Files:
main.tf: Configuration for setting up your EKS cluster, VPC, subnets, and other resources.
variables.tf: Declares variables for your Terraform code, such as region and instance types.
output.tf: Specifies desired output values, like the cluster's endpoint or VPC ID.
Run the following Terraform commands to provision your EKS Cluster:
terraform init
Initializes the Terraform working directory and downloads necessary provider plugins.

terraform plan
Generates an execution plan showing the changes Terraform will make to your infrastructure, allowing you to review them before proceeding.


terraform apply --auto-approve
Provisions resources and updates your infrastructure to match the desired state specified in your configuration files.


✅ Verify Resource Creation
Confirm all resources have been created:
Terraform state list

Lists all resources currently managed by Terraform in your state file.
Verify and Visualize Resource Creation:
Once the terraform apply command is executed successfully, you can see the EKS cluster worker nodes created on the EC2 dashboard.

EKS Cluster

A node group and 3 worker nodes:


VPC, Subnets, Route Table, Internet gateway, and Security groups

igw-08b14631211088f90 / bluegreen-project-igw


Cluster Security Group: sg-0b882d19ae3090a03 - bluegreen-project-cluster-sg
This security group (aws_security_group.bluegreen_project_cluster_sg) is associated with the EKS control plane. It's used for communication between the control plane and the worker nodes. This ensures your control plane can communicate securely with your nodes.

sg-0c4a3b7b4cceff61f - bluegreen-project-node-sg
Node Security Group: This security group (aws_security_group.bluegreen_project_node_sg) is attached to the worker nodes. It manages traffic to and from the nodes. By defining this in Terraform, you control which ports and protocols can be used by the nodes.

sg-0aac2bd7baabddc5a - eks-cluster-sg-bluegreen-project-cluster
EKS Control Plane Security Group: The EKS control plane security group, managed by AWS, is used internally by EKS to facilitate communication between the control plane components.

Cluster Role (aws_iam_role.bluegreen_project_cluster_role):
- This role is assumed by the EKS control plane to manage the cluster.
Node Group Role (aws_iam_role.bluegreen_project_node_group_role):
- This role is assumed by the worker nodes to interact with AWS services.

🔧 Install kubectl
sudo snap install kubectl --classic
We install kubectl on both the EKS server and Jenkins server to ensure seamless interaction and management of the Kubernetes cluster.
- Install Kubectl on EKS Server: This server will have Terraform and
eksctlinstalled, making it your primary hub for managing EKS infrastructure. Addingkubectllets you directly manage and troubleshoot your Kubernetes cluster in the same environment.

Even if you mistakenly installed kubectl outside of the /Blue-Green-Deployment-Project/Cluster directory, it still works because kubectl is installed system-wide. Regardless of which directory I run commands from, the system recognizes the installation and kubectl work as expected.
- Install kubectl on Jenkins instance: Jenkins handles your CI/CD pipelines. By installing
kubectl, Jenkins can directly interact with the EKS cluster to deploy and manage Kubernetes resources as part of your automated workflows.

⚙️ Install eksctl (Optional but Recommended)
eksctl is a simple CLI tool for creating and managing EKS clusters.
Download and extract eksctl
curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
Move the eksctl binary to /usr/local/bin for global access
sudo mv /tmp/eksctl /usr/local/bin
Verify eksctl installation
eksctl version

Note: While eksctl simplifies EKS cluster management, it’s not mandatory in this setup as Terraform handles all infrastructure provisioning. However, eksctl can provide additional flexibility for managing your cluster.
🔑 Connecting to the EKS Cluster with Kubeconfig
Updating your kubeconfig is key to interacting with your EKS cluster using kubectl.
aws eks update-kubeconfig --region <your-region> --name <your-cluster-name>

when you run the command, it connects to the EKS service, fetches the required API endpoint and tokens, and updates the kubeconfig file. This allows you to manage your EKS cluster using kubectl from your EC2 instance.
🔧 Setup Required Servers (Jenkins, SonarQube, Nexus)
We are going to launch 3 EC2 instances for Jenkins, Nexus, and SonarQube.
Virtual Machine Configuration
Instance Type:
t2.mediumvCPUs: 2
Memory: 4 GB
Network Performance: Moderate
Amazon Machine Image (AMI): Ubuntu Server 24.04 LTS
Security Groups: Using existing security groups with open ports:
- 80 (HTTP), 443 (HTTPS), 22 (SSH), 1000-11000 (Custom range), 500-1000 (Custom range)
Storage Configuration: Allocated 20 GB per instance


⚙️ Configure Jenkins Instance
SSH into the Jenkins instance
Update & Install Java for Jenkins
# update the packages
sudo apt update
# Install OpenJDK 17 JRE Headless
sudo apt install openjdk-17-jre-headless -y

- Install Jenkins:
# Download Jenkins GPG key and save it
sudo wget -O /usr/share/keyrings/jenkins-keyring.asc https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
# Add Jenkins repository to the sources list
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
# Update the package list again to include Jenkins repository
sudo apt-get update
# Install Jenkins
sudo apt-get install jenkins -y
# Start Jenkins
sudo systemctl start jenkins
# Enable Jenkins to start on boot
sudo systemctl enable jenkins

🐳 Installing Docker for Jenkins
To enable Docker in Jenkins, follow these steps:
- Add Docker's GPG key and repository:
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
- Install Docker with latest version, run:
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

After installing Jenkins and Docker, you need to make sure Jenkins can access Docker. Here's how to do it:
- Add Jenkins to the Docker Group:
sudo usermod -aG docker jenkins
- Apply group changes:
Either run ** newgrp docker ** to update the group for your session.
# Or reboot the instance:
sudo reboot
# Or restart the Jenkins service:
sudo systemctl restart jenkins
This ensures Jenkins can interact with Docker to run builds and manage containers.

🔑 Accessing Jenkins
After installation, access Jenkins via http://<your-jenkins-public-ip>:8080 and retrieve the initial password using:
sudo cat /var/lib/jenkins/secrets/InitialAdminPassword

When this is done correctly, we can now access the Jenkins page.
In my case, it is http://3.109.32.41:8080/

🔌 Installing Required Jenkins Plugins
Navigate to Plugins:
Manage Jenkins > Manage PluginsInstall Plugins:
Click on the Available tab.
Search and select the following plugins:
SonarQube Scanner
Config File Provider
Maven Integration
Pipeline Maven Integration
Pipeline: Stage View
Docker Pipeline
Kubernetes
Kubernetes Client API
Kubernetes Credentials
Kubernetes CLI
- Install:
Click Install without restart and wait for the plugins to install

🔨 Configure Maven and SonarQube Scanner
Global Tool Configuration:
Maven: Add
maven3SonarQube Scanner: Add
sonar-scanner
Now, Jenkins is fully configured to use Maven3 for builds and SonarQube for code analysis!
☑️ Why We Configure Maven and SonarQube on Jenkins
🎯 Purpose: Defines where Jenkins can find these tools for executing pipeline jobs.
📌 Versioning: Ensures Jenkins uses the correct version during builds for compatibility and reliable execution.
🌟 Benefits of Configuring Maven and SonarQube in Jenkins
🚀 Maven:
Automated Build Process: Configuring Maven enables Jenkins to automate compiling, testing, and packaging of applications.
Seamless Dependency Management: Maven simplifies handling dependencies, ensuring consistent and repeatable builds.
🛡️ SonarQube Scanner:
Automated Code Quality & Security Checks: SonarQube Scanner integration helps Jenkins analyze your code, identifying issues early.
Improved Code Quality: Running static code analysis within Jenkins enhances overall software quality and security.
🔄 This configuration streamlines your CI/CD pipeline, improving efficiency, and maintaining high standards of code quality.


Before setting up the pipeline, we need to integrate the necessary credentials.
🛠️ Trivy Installation
To install Trivy, use the following steps:
sudo apt-get install 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 trivy

🛢️ Configure Nexus Server (Docker-based)
- Install Docker on Nexus Instance
SSH into your Nexus instance and run the following:
sudo apt update
sudo apt install docker.io
sudo usermod -aG docker ubuntu
newgrp docker

- Run Nexus Container
docker run -d -p 8081:8081 sonatype/nexus3
3. Verify Nexus Container
docker ps

Note: Nexus may take a while to start. Access it via:
🌐 http://<nexus-ec2-public-ip>:8081
(e.g., http://13.127.147.165:8081)

when you try to sign in, you will be asked to enter your username and password.

4. Retrieve Admin Password
To log in, retrieve the password stored inside the Nexus container:
The username is admin, and the password is stored in a file located at /nexus-data/admin.password inside the container. To get the password, access the container's main shell and read the admin.password file.
docker exec -it <container-id> /bin/bash
cd sonatype-work/nexus3
cat admin.password

💡 Tip: The password will look like this: a70e162e-38bd-4b01-b718-da8-da831651843f. Copy and use it to log in as admin.
After logging in, you’ll be prompted to change the admin password and disable anonymous access.



You can now see that you are logged in as admin.

🎛️ Configure SonarQube Server (Docker-based)
- Install Docker on SonarQube Instance
SSH into your SonarQube instance and run:
sudo apt update
sudo apt install docker.io
sudo usermod -aG docker $USER
newgrp docker
- Run SonarQube Container
docker run -d -p 9000:9000 sonarqube:lts-community
### Verify sonarqube container
docker ps
3. Verify SonarQube Container
docker ps

Access SonarQube via:
🌐 http://<sonar-ec2-public-ip>:9000
(e.g., http://13.235.95.27:9000)

4. Sign In to SonarQube
Username:
adminPassword:
admin
Generate a token:
Administration > Security > Users > Generate Token > Copy Token

🔐 Adding Credentials in Jenkins
1. GitHub Credentials
Go to Jenkins > Manage Jenkins > Manage Credentials > System > Global Credentials > Add credentials
Username with password
Enter GitHub username and token
Provide ID and description
Click OK
2. DockerHub Credentials
- Same as above, but use DockerHub username and password instead.
3. SonarQube Credentials
Add Secret Text and paste the SonarQube token generated earlier.
Provide ID and description.
Click OK

Steps to Add SonarQube Server in Jenkins
🖥️ Dashboard:
- Go to Jenkins Dashboard.
⚙️ Manage Jenkins:
- Click on Manage Jenkins.
⚙️ System:
- Select Configure System.
🔌 SonarQube Servers:
- Scroll to the SonarQube servers section.
➕ Add SonarQube:
- Click Add SonarQube under SonarQube installations.
📝 Enter Details:
- Provide Name, Server URL, and Token (Select the token from credentials).
💾 Save:
- Click Save.
✅ Done!
🤔Why Add SonarQube Configuration in Jenkins (System Section)?
🔗 Integration with SonarQube:
Name: Identifies the SonarQube server.
Server URL: Connects Jenkins to your SonarQube instance.
Token: Provides Jenkins with secure access to SonarQube.
Consistency: Ensures all jobs use the same server and credentials.
Ease of Use: Automatically uses the configured settings during builds.
This setup simplifies and secures SonarQube integration with Jenkins! 🌟

Setting Up Jenkins and Kubernetes for Continuous Integration
🚀 Kubernetes RBAC Configuration for Jenkins Service Account
RBAC (Role-Based Access Control) in Kubernetes is a security system that controls which users or service accounts can perform specific actions in the cluster. It ensures that only authorized accounts have the necessary permissions, reducing the risk of unauthorized access or changes.
RBAC is crucial in environments where multiple services or users interact with the cluster, especially when using automation tools like Jenkins. It allows you to control who can do what in a secure and structured way, helping manage resources like pods, services, and volumes while maintaining security.
🛠️Create a Service Account, Assign Roles, Generate Token, and Create Secret
In this setup, we’re creating a service account for Jenkins, assigning it specific roles to control what it can do in a given namespace and cluster-wide. By creating a role binding and cluster role binding, we ensure Jenkins has the right permissions to manage resources, such as pods and persistent volumes, securely. Finally, we generate a token for the Jenkins service account to authenticate and use these permissions during its operations.
To view YAML files, Click here.
📝 Summary of the Files:
Service Account: Creates a Jenkins service account in the
webappsnamespace.Role: Defines a role named
app-rolethat allows Jenkins to perform actions on resources like pods, deployments, and services in thewebappsnamespace.RoleBinding: Binds the
app-roleto thejenkinsservice account, giving it the necessary permissions in thewebappsnamespace.ClusterRole: Creates a cluster-wide role named
jenkins-cluster-rolethat allows Jenkins to manage persistent volumes.ClusterRoleBinding: Binds the
jenkins-cluster-roleto thejenkinsservice account, granting it cluster-wide permissions.Token Generation: Generates an authentication token for the
jenkinsservice account.
⚙️ Steps for Configuring RBAC and Secrets in the EKS Cluster:
To access the EKS cluster using the Jenkins pipeline, we need Jenkins to have access to EKS. For that, we will be creating the Service Account in the webapps namespace, which Jenkins will use to access the EKS resources.
- Creating namespace
webappsin EKS:
kubectl create ns webapps
- Create a Jenkins service account in the
webappsnamespace. Create a fileservice-account.ymlwith content as:
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins
namespace: webapps with content as:
- Apply the YAML definition
kubectl apply -f service-account.yml

- Create and apply a role:
- Now we will be creating a role and attaching it to the Jenkins service account by creating a file
role.ymlwith content as:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: app-role
namespace: webapps
rules:
- apiGroups:
- ""
- apps
- autoscaling
- batch
- extensions
- policy
- rbac.authorization.k8s.io
resources:
- pods
- secrets
- componentstatuses
- configmaps
- daemonsets
- deployments
- events
- endpoints
- horizontalpodautoscalers
- ingress
- jobs
- limitranges
- namespaces
- nodes
- pods
- persistentvolumes
- persistentvolumeclaims
- resourcequotas
- replicasets
- replicationcontrollers
- serviceaccounts
- services
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- Apply the YAML definition
kubectl apply -f role.yml

- Create and apply a role binding:
- The next step is to bind the created role
app-roleto thejenkinsservice account, giving it the necessary permissions in thewebappsnamespace. Create a file namedrolebind.ymlwith the following content:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: app-rolebinding
namespace: webapps
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: app-role
subjects:
- namespace: webapps
kind: ServiceAccount
name: jenkins

- Apply the YAML definition
kubectl apply -f rolebind.yml
- Create and apply a secret:
- Next, create a secret token for the Jenkins service account. Create a file
secret.ymlwith the content:
apiVersion: v1
kind: Secret
type: kubernetes.io/service-account-token
metadata:
name: mysecretname
annotations:
kubernetes.io/service-account.name: jenkins
- Apply the YAML definition:
kubectl apply -f secret.yml -n webapps

Secret mysecretname created in the webapps namespace.
🔍 Putting it all together:

Verify the Secret
We will be using this secret for Jenkins to EKS communication. To get the token, run the command:
kubectl describe secret mysecretname -n webapps

A long JWT token is used to authenticate the service account. This token is used by the jenkins service account for API access within the webapps namespace.
To store the token as a secret text in Jenkins, follow these steps:
Copy Token: Run
kubectl describe secret mysecretname -n webappsand copy the token.Log in to Jenkins: Go to
http://<jenkins_public_ip>:8080and log in.Add Secret Text:
Navigate to Manage Jenkins > Manage Credentials.
Select (global) and click Add Credentials.
In the Kind dropdown, choose Secret text and paste the token.
Add an ID and Description, then Save.

📒Steps to Add Global Maven Settings in Jenkins
⚙️ Manage Jenkins:
- Go to Manage Jenkins.
📁 Manage Files:
- Click on Manage Files.
➕ Add New Config:
- Select Add a new config.

🔧 Global Maven Settings XML:
- Choose Global Maven settings XML.
✏️ Replace ID:
- Change the ID to
maven-settingsand click Next.

🔍 Scroll to Content:
Line 124: Remove
-->Line 118: Press Enter and add
-->
📦 Get Repository URL:
For Java-based applications, you need two repos: maven-releases and maven-snapshots.
- Click browse and click
maven-releasesand copy the last part of the URL (i.e.,maven-releases).
📝 Update Jenkins Managed Files:
Replace maven-releases in the ID: Set username to admin (the username of Nexus) and password to the new password you updated earlier.
<server>
<id>maven-releases</id>
<username>admin</username>
<password>nexus@123</password>
</server>
📝 Add Snapshot Configuration
Copy the entire code (lines 120 to 124) for
maven-releases.Press Enter and paste it to create the configuration for
maven-snapshots.Replace the ID with
maven-snapshots, keeping the username and password the same:
<server>
<id>maven-snapshots</id>
<username>admin</username>
<password>nexus@123</password>
</server>
Now both the maven releases & maven-snapshots will look like this:

✅ Submit
Click Submit: Once done, you will see "MyGlobalSettings.”

This will set up your global Maven settings in Jenkins for both release and snapshot repositories!
🔄 Update pom.xml
Now return to your Nexus interface: Click on Browse and copy the URL for maven-releases.


Copy this URL: Go to your project's GitHub repository. Open the pom.xml file and replace the maven-releases URL with the one you copied from Nexus maven-releases.
Once done: Go back to your Nexus interface and copy the URL for maven-snapshots.

Then, replace the maven-snapshots URL in your pom.xml with the one you copied from Nexus maven-snapshots. once done, commit your changes.

🌐 Steps to Create a Webhook in SonarQube and Add Jenkins URL
Log in to SonarQube
🔐 Open your SonarQube instance and log in.Navigate to Webhooks
⚙️ Go to Administration > Configuration > Webhooks.Click Create to Add a New Webhook
➕ Add a webhook.Add Jenkins URL
📝 Name: Give a name to your webhook (e.g., "Jenkins Webhook").
🌐 URL: Enter your Jenkins URL in this format:
http://<jenkins_public_ip>:8080/sonarqube-webhook/
- Save
💾 Click Save to create the webhook.
👉 Now, SonarQube will send analysis results to Jenkins automatically!



📝Before you create a pipeline in Jenkins, ensure all the required credentials have been added.

🚀 Steps to Create a Pipeline in Jenkins (Name: Blue-Green)
Navigate to New Pipeline
🛠️ From the Jenkins dashboard, click New Item.Create Pipeline
✏️ Enter the Name: Blue-Green.
📂 Select Pipeline: Choose Pipeline as the project type.
✅ Click OK.
Configure Pipeline
⚙️ Scroll to the Pipeline section and define your pipeline script or choose Pipeline script from SCM.Save
💾 Once configured, click Save to create the pipeline.
🎉 Your Blue-Green pipeline is now ready!
Let’s see what we define in our pipeline script.
📜Pipeline Definition
Agent
any: The pipeline can run on any available Jenkins agent.Tools:
- ⚙️
maven 'maven3': Specifies the Maven version used for the build.
- ⚙️
🌍Parameters:
DEPLOY_ENV: Choose between the blue or green environment for deployment.DOCKER_TAG: Specifies which Docker image (blue or green) to deploy.SWITCH_TRAFFIC: A boolean parameter to control whether to switch traffic between the environments.
🌍Environment Variables:
IMAGE_NAME: Docker image name.TAG: The Docker tag is determined by theDOCKER_TAGparameter.SCANNER_HOME: Path to SonarQube scanner.KUBE_NAMESPACE: Kubernetes namespace for the application.
Stages:
Git Checkout: Clones the repository from GitHub.
SonarQube Analysis: Runs a static analysis using SonarQube to check code quality.
Trivy FS Scan: Scans the filesystem for vulnerabilities.
Docker Build: Builds the Docker image with the specified tag.
Trivy Image Scan: Scans the Docker image for vulnerabilities.
Docker Push Image: Pushes the image to a Docker registry.
Deploy MySQL: Deploys MySQL to the Kubernetes cluster.
Deploy Service: Creates the application service if it doesn’t exist.
Deploy to Kubernetes: Deploys the application based on the selected environment (blue or green).
Switch Traffic: Updates the service to route traffic to the selected environment.
Verify Deployment: Checks the status of the pods and service to verify the deployment.
📋 Pipeline Stages Overview
📥Stage 1: Git Checkout
This stage pulls the latest code from the GitHub repository into the Jenkins workspace.
Purpose: Ensures that Jenkins is working with the most up-to-date version of the code.
Why it matters: Jenkins needs access to the latest code for testing, building, and deployment
stages {
stage('Git CheckOut') {
steps {
git branch: 'main', credentialsId: 'Git-Credential', url: 'https://github.com/Sandhyagito/Blue-Green-Deployment-Project.git'
}
}
}
🔧Stage 2: Compile
Compiles the source code using Maven.
Purpose: Converts source code into executable code (binaries) to ensure there are no compilation errors.
Why it matters: Compilation verifies that the code is syntactically correct and can be executed.✔️
stage('Compile') {
steps {
sh "mvn compile"
}
}
🧪Stage 3: Tests
Executes unit tests on the compiled code.
Purpose: Validates the functionality of the code by running automated tests.
Why it matters: Testing ensures that the code works as expected before proceeding further.
🔍 Security and Quality Checks
🛡️Stage 4: Trivy fs Scan
Scans the entire project directory for vulnerabilities using Trivy.
Purpose: Detects known security vulnerabilities in the project files and libraries.
Why it matters: Ensures that no known security flaws are present before deployment.
Identifies vulnerabilities early to ensure compliance with security standards.
stage('Trivy fs Scan') {
steps {
sh "trivy fs --format table -o fs.html ."
}
}
⏳Stage 5: SonarQube Analysis
Performs static code analysis using SonarQube.
Purpose: Analyze the code for bugs, vulnerabilities, code smells, and technical debt.
Why it matters: Ensures code quality and security compliance, highlighting areas for improvement.
stage('SonarQube Analysis') {
steps {
withSonarQubeEnv('sonarqube') {
sh "$SCANNER_HOME/bin/sonar-scanner -Dsonar.projectKey=Multitier -Dsonar.projectName=Multitier -Dsonar.java.binaries=target"
}
}
}
🚧Stage 6: Quality Gate Check
Check the SonarQube Quality Gate status.
Purpose: Verify if the code meets the quality standards defined in SonarQube.
Why it matters: This acts as a gatekeeper. Ensures that only high-quality code passes. If the code fails to meet the quality threshold, the pipeline stops, preventing flawed or insecure code from progressing further in the deployment process.
stage('Quality Gate Check') {
steps {
timeout(time: 1, unit: 'HOURS') {
waitForQualityGate abortPipeline: false
In this case, The pipeline continues even if the quality gate fails because abortPipeline: false.
🏗️ Build and Deploy
Overview: This stage usually involves compiling and packaging the application.
📦Stage 7: Build
Packages the application into a deployable artifact (JAR file) using Maven
Purpose: Bundles the compiled code into an artifact (JAR,
in case of a Java project using Maven) that can be deployed or used to build a Docker image.Why it matters: The JAR file is necessary for creating Docker images or deploying to other environments.
stage('Build') {
steps {
sh "mvn package -DskipTests=true"
}
}
📥Stage 8: Publish Artifact to Nexus
Deploys the packaged artifact to Nexus for version control.
Purpose: Stores the build artifact in a centralized repository (Nexus) for traceability.
Why it matters: Nexus serves as a reliable storage for versioned artifacts, facilitating easy rollback or redeployment.
tage('Publish Artifact to Nexus') {
steps {
withMaven(globalMavenSettingsConfig: 'maven-settings', jdk: '', maven: 'maven3', mavenSettingsConfig: '', traceability: true) {
sh "mvn deploy -DskipTests=true"
}
}
}
🚀Deploy Stage: This stage prepares, scans, and pushes the Docker image, followed by Kubernetes deployment.
🐳 Stage 9: Docker Build & Tag Image
Builds and tags the Docker image for the application.
Purpose: Converts the packaged artifact (JAR) into a Docker image.
Why it matters: The Docker image will be used to deploy the application in containers.
stage('Docker Build & Tag Image') {
steps {
script{
withDockerRegistry(credentialsId: 'Docker-Credential') {
sh "docker build -t ${IMAGE_NAME}:${TAG} ."
}
}
}
}
🔍Stage 10: Trivy Image Scan
Scans the Docker image for vulnerabilities.
Purpose: Ensures that the Docker image is free of security vulnerabilities.
Why it matters: Security compliance is critical before deploying containerized applications.
stage('Trivy Image Scan') {
steps {
sh "trivy image --format table -o fs.html ${IMAGE_NAME}:${TAG}"
}
}
⤴️Stage 11: Docker Push Image
Pushes the Docker image to Docker Hub or another registry.
Purpose: Stores the Docker image in a remote registry (Docker Hub) so it can be pulled for deployment.
Why it matters: Ensures that the image is accessible to the Kubernetes cluster for deployment.
stage('Docker Push Image') {
steps {
script {
withDockerRegistry(credentialsId: 'Docker-Credential') {
sh "docker push ${IMAGE_NAME}:${TAG}"
}
}
}
}
⚙️ Kubernetes Deployment Stage
Now that the Docker image is ready, it’s time to deploy to Kubernetes:
📂Stage 12: Deploy MySQL Deployment and Service
Deploys the MySQL service to Kubernetes.
Purpose: Ensures the MySQL database is running and ready to be used by the application.
Why it matters: Ensures that the MySQL service is available in the Kubernetes cluster before deploying the application.
stage('Deploy MySQL Deployment and Service') { steps { script { withKubeConfig(caCertificate: '', clusterName: 'bluegreen-project-cluster', contextName: '', credentialsId: 'k8s-service-account-token', namespace: 'webapps', restrictKubeConfigAccess: false, serverUrl: 'https://1C227108150786A9F6E06701A06123FE.gr7.ap-south-1.eks.amazonaws.com') { sh "kubectl apply -f mysql-ds.yml -n ${KUBE_NAMESPACE}" // Ensure you have the MySQL deployment YAML ready } } } }
🚀Stage 13: Deploy SVC-APP
Deploys the application service to Kubernetes.
Purpose: Exposes the application to external traffic by creating a Kubernetes service.
Why it matters: The application needs a service to route external requests into the Kubernetes cluster.
stage('Deploy SVC-APP') {
steps {
script {
withKubeConfig(caCertificate: '', clusterName: 'bluegreen-project-cluster', contextName: '', credentialsId: 'k8s-service-account-token', namespace: 'webapps', restrictKubeConfigAccess: false, serverUrl: 'https://1C227108150786A9F6E06701A06123FE.gr7.ap-south-1.eks.amazonaws.com') {
sh """ if ! kubectl get svc bankapp-service -n ${KUBE_NAMESPACE}; then
kubectl apply -f bankapp-service.yml -n ${KUBE_NAMESPACE}
fi
"""
}
}
}
}
🌐Stage 14: Deploy to Kubernetes
Deploys the application to the blue or green environment.
Purpose: This stage deploys the application to the Kubernetes cluster.
It applies a Kubernetes deployment file (blue or green), based on the DEPLOY_ENV parameter (blue or green environment).
Flow:
Environment Check: Depending on the
DEPLOY_ENVparameter, either theapp-deployment-blue.ymlorapp-deployment-green.ymlfile is selected.Deploy: The selected YAML file is applied to the Kubernetes cluster using
kubectl apply. This deploys the application to the specified environment (blue or green).
Why it matters: It controls the deployment process by choosing the correct environment for the application, ensuring a smooth deployment to Kubernetes.
stage('Deploy to Kubernetes') {
steps {
script {
def deploymentFile = ""
if (params.DEPLOY_ENV == 'blue') {
deploymentFile = 'app-deployment-blue.yml'
} else {
deploymentFile = 'app-deployment-green.yml'
}
withKubeConfig(caCertificate: '', clusterName: 'bluegreen-project-cluster', contextName: '', credentialsId: 'k8s-service-account-token', namespace: 'webapps', restrictKubeConfigAccess: false, serverUrl: 'https://1C227108150786A9F6E06701A06123FE.gr7.ap-south-1.eks.amazonaws.com') {
sh "kubectl apply -f ${deploymentFile} -n ${KUBE_NAMESPACE}"
}
}
}
}
♻️Stage 15: Switch Traffic Between Blue & Green Environments
Switches traffic to the newly deployed environment.
Purpose: This stage switches user traffic to the newly deployed version of the application (either blue or green) based on the DEPLOY_ENV parameter.
Flow:
Condition Check: The stage only runs if the
SWITCH_TRAFFICparameter is set totrueTraffic Switching:
Determine Environment:
Uses the DEPLOY_ENV parameter to identify whether to switch to the blue or green environment.Patch Service:
Updates the Kubernetes service to redirect traffic to the selected environment using the kubectl patch command.Confirmation Message:
Outputs a message confirming that traffic has been switched to the chosen environment.
Why it matters: Switching traffic is essential for a blue-green deployment strategy, allowing seamless transitions between different versions of the application without downtime.
stage('Switch Traffic Between Blue & Green Environment') {
when {
expression { return params.SWITCH_TRAFFIC }
}
steps {
script {
def newEnv = params.DEPLOY_ENV
// Always switch traffic based on DEPLOY_ENV
withKubeConfig(caCertificate: '', clusterName: 'bluegreen-project-cluster', contextName: '', credentialsId: 'k8s-service-account-token', namespace: 'webapps', restrictKubeConfigAccess: false, serverUrl: 'https://1C227108150786A9F6E06701A06123FE.gr7.ap-south-1.eks.amazonaws.com') {
sh '''
kubectl patch service bankapp-service -p "{\\"spec\\": {\\"selector\\": {\\"app\\": \\"bankapp\\", \\"version\\": \\"''' + newEnv + '''\\"}}}" -n ${KUBE_NAMESPACE}
'''
}
echo "Traffic has been switched to the ${newEnv} environment."
}
}
}
🛠️ Verification Stage
Once the deployment is complete, it’s essential to verify everything is working as expected.
- ✔️ Stage 16: Verify Deployment: Checking that all services, deployments, and pods are up and running correctly in the Kubernetes cluster, ensuring the application is functioning as intended
stage('Verify Deployment') {
steps {
script {
def verifyEnv = params.DEPLOY_ENV
withKubeConfig(caCertificate: '', clusterName: 'bluegreen-project-cluster', contextName: '', credentialsId: 'k8s-service-account-token', namespace: 'webapps', restrictKubeConfigAccess: false, serverUrl: 'https://1C227108150786A9F6E06701A06123FE.gr7.ap-south-1.eks.amazonaws.com') {
sh """
kubectl get pods -l version=${verifyEnv} -n ${KUBE_NAMESPACE}
kubectl get svc bankapp-service -n ${KUBE_NAMESPACE}
"""
}
}
}
📸Outputs:
When you run the pipeline for the first time, you will witness Build now

When you run for the second time, you witness the Build with parameters option

✅Jenkins Build successful:



Verification of Deployment in the 'webapps' Namespace
kubectl get all -n webapps

Breakdown of the Output:
Pods:
pod/bankapp-blue-f549f7b45-k5pts: This pod is Running with1/1ready, indicating that the application is up and functioning properly.pod/mysql-f5c84b88-nnsgl: This MySQL pod is also Running with1/1ready, which means the database is operational as well.
Services:
service/bankapp-service: This LoadBalancer service is correctly exposing thebankappon port 80, with an external IP assigned. This means your application should be accessible from outside the cluster.service/mysql-service: This ClusterIP service is functioning for internal communication within the cluster, which is expected for a database service.
Deployments:
deployment.apps/bankapp-blue: It shows that1/1is ready and available, meaning the deployment is healthy.deployment.apps/mysql: Also healthy with1/1ready.
ReplicaSets:
The old ReplicaSet
bankapp-blue-6855f6f4f7has scaled down to0pods, which is good as it indicates the old version of the deployment is no longer active.The new ReplicaSet
bankapp-blue-f549f7b45has1pod and is active.
Reason for scaling down of Old Pods: The old ReplicaSet bankapp-blue-6855f6f4f7 scaled down to 0 pods because the previous image encountered an ErrImagePull issue, preventing it from running successfully. Once the new image was pushed and the deployment updated, the old ReplicaSet was no longer needed, leading to its scaling down.

↩️Cause of ImagePullBackOff»»
The ImagePullBackOff error for my bankapp-blue pod indicates that Kubernetes is unable to pull the Docker image. This issue is likely due to:
- Incorrect Docker Image Reference: The image name in my deployment YAML may not match the repository name
sandhyadev836/bankappin Docker Hub.
I need to ensure that the correct image name is specified in my Kubernetes deployment file, such as sandhyadev836/bankapp:blue.
Health Check: If you have health checks configured, ensure that they are passing. This can be checked by describing the pod:
📊Describing Pod Details for 'bankapp-blue' in the 'webapps' Namespace
kubectl describe pod bankapp-blue-f549f7b45-k5pts -n webapps

Resource Requests and Limits, Env Variables & Pod conditions

Volume info, QoS & Events

🌏Accessing the Application via LoadBalancer External IP
Access the Application: You can test the application by accessing the LoadBalancer's external IP from your browser.
http://a21230295946f400095cdf05c752dd26-530663340.ap-south-1.elb.amazonaws.com/login

📦Artifact Storage in Nexus:

Application Startup:



SonarQube Analysis

🔍 SonarQube Analysis Observations
Bugs (5): The codebase has identified a total of 5 bugs, which need immediate attention to ensure the application functions as expected.
Reliability (C): The reliability rating of C suggests moderate reliability; addressing the identified bugs is essential for improving this metric.
Vulnerabilities (0): There are currently 0 vulnerabilities, indicating a secure codebase, which is a positive aspect.
Security Hotspots (8): There are 8 security hotspots that require manual review to prevent potential vulnerabilities, emphasizing the need for thorough security assessments.
Test Coverage (0.0%): The 0.0% test coverage on 166 lines underscores the necessity for comprehensive testing in future iterations.
Unit Tests (14.4%): Currently, only 14.4% of unit tests are covered, highlighting room for improvement in testing practices.
Technical Debt (1h 37min): The analysis indicates 1 hour and 37 minutes of technical debt, which should be addressed to enhance the maintainability of the code.
Code Smells (8): There are 8 code smells detected, which, while not critical, should be resolved to improve overall code quality.
Maintainability (A): The high maintainability rating of A suggests that the code is well-structured and easy to maintain, facilitating future updates and modifications.
Duplications (2): The analysis identifies 2 duplicated blocks within 1.3k lines of code, indicating areas that may benefit from refactoring to improve code quality.
Issues identified in Sonarqube analysis:

SonarQube Analysis Summary
Bugs: 5 identified
* Code Smells: 8 total, including 4 critical issues:
* "account" - Use a constant instead of duplicating the literal (Critical)
* "dashboard" - Use a constant instead of duplicating the literal (Critical)
* "error" - Use a constant instead of duplicating the literal (Critical)
* "redirect:/dashboard" - Use a constant instead of duplicating the literal (Critical)
### Key Observations
* Reliability (C): The presence of 5 bugs and multiple critical code smells indicates a moderate need for improvement.
* Maintainability (A): Despite code smells, the maintainability remains high, suggesting the codebase is still easy to modify with low technical debt..

SonarQube Measures Overview
Risk Level: 0.0%
Reliability Rating: C (yellow)
Security Rating: A (green)
New Code: Analyzed since October 14, 2024
Overall Risk: Low, but attention is needed to improve reliability (C rating) and review security hotspots. Maintainability is strong with an A rating.


Pipeline Errors and Resolutions
Build #1: Authentication Failed in Docker Hub
Issue: Docker authentication failed.
Resolution: Created a new password multiple times and updated it in Jenkins credentials but auth failed. Eventually, switched to using a token instead of the password and it worked.
Solution: Use the Token for Docker login instead of a password.



Build #2: Login Succeeded, but Pipeline Still Failed:


The pipeline successfully authenticated with Docker Hub, but encountered an issue during the push:
Issue:
The pipeline is failing with the error:
denied: requested access to the resource is denied
This occurred because the IMAGE_NAME in the Jenkinsfile was set incorrectly to sandhya/bankapp, which does not match your Docker Hub username sandhyadev836.
Solution:
Update the IMAGE_NAME in your Jenkinsfile to reflect your correct Docker Hub username:
environment {
IMAGE_NAME = 'sandhyadev836/bankapp'
}
With this correction, Docker Hub will automatically create the bankapp repository under your sandhyadev836 account when you push the image, eliminating the access denial issue.
# 3 Build: Successful but ImagePullBackOff



Issue:
The pod for bankapp-blue is failing to start due to the following error messages:
Failed to pull image: The system cannot pull the image from Docker Hub.
Authorization failed: Indicates either the repository does not exist or requires authentication.
Solution:
Check Repository Name: Ensure the repository name in your Kubernetes deployment YAML is correctly specified as
sandhyadev836/bankapp:blue, notsandhya/bankapp:blue.Verify Image Existence: Ensure the image
sandhyadev836/bankapp:blueexists on Docker Hub and is publicly accessible.
After these adjustments, redeploy your application to resolve the ErrImagePull and ImagePullBackOff errors.

Reminder: Ensure the repository is set to public to avoid further issues.
Monitor the application
1. Set Up a New EC2 Instance
Instance Type:
t2.largewith 25GB storage.This instance will host Prometheus, Grafana, and Blackbox Exporter.
2. Install AWS CLI and Configure
Install AWS CLI to interact with your AWS resources:
sudo apt-get update
sudo snap install aws-cli --classic
Configure AWS CLI with your credentials:
aws configure
3. Install kubectl for EKS Cluster Interaction
Install kubectl to manage your Kubernetes EKS cluster:
sudo snap install kubectl --classic
Make sure kubectl is configured to point to your EKS cluster:
aws eks update-kubeconfig --region <your-region> --name <your-cluster-name>
Example:
aws eks update-kubeconfig --region ap-south-1 --name bluegreen-project-cluster

4. Set Up Blackbox Exporter
Blackbox Exporter probes endpoints and checks their availability.
- Download and Extract Blackbox Exporter:
wget https://github.com/prometheus/blackbox_exporter/releases/download/v0.21.0/blackbox_exporter-0.21.0.linux-amd64.tar.gz
tar xvfz blackbox_exporter-0.21.0.linux-amd64.tar.gz
cd blackbox_exporter-0.21.0.linux-amd64
./blackbox_exporter
Configure Blackbox Exporter:
Create the
blackbox.ymlconfiguration file:
vi blackbox.yml
Paste the following configuration:
In my case, I updated the following configuration in the existing blackbox.yml file.
modules:
http_2xx:
prober: http
timeout: 5s
http:
method: GET
valid_http_versions: [ "1.1" ] # Adjusted this to valid version
Why we include http_2xx and custom_http_check in blackbox.yml:
Purpose: To create custom HTTP probes to monitor the health and performance of HTTP endpoints.
Function: They define specific HTTP requests and expected responses. This ensures that the endpoints return the correct HTTP status codes and versions.
Explanation:
http_2xx: Checks for a successful HTTP GET response (status code 200) and verifies it uses HTTP version 1.1.custom_http_check: Similar tohttp_2xx, but can be customized further based on specific needs.
Including these probes helps detect issues early, ensuring your applications remain reliable and performant.
Here is my complete blackbox.yml file:-
modules:
http_2xx:
prober: http
timeout: 5s
http:
method: GET
valid_http_versions: [ "1.1" ] # Adjusted this to valid version
http_post_2xx:
prober: http
http:
method: POST
tcp_connect:
prober: tcp
pop3s_banner:
prober: tcp
tcp:
query_response:
- expect: "^+OK"
tls: true
tls_config:
insecure_skip_verify: false
grpc:
prober: grpc
grpc:
tls: true
preferred_ip_protocol: "ip4"
grpc_plain:
prober: grpc
grpc:
tls: false
service: "service1"
ssh_banner:
prober: tcp
tcp:
query_response:
- expect: "^SSH-2.0-"
- send: "SSH-2.0-blackbox-ssh-check"
irc_banner:
prober: tcp
tcp:
query_response:
- send: "NICK prober"
- send: "USER prober prober prober :prober"
- expect: "PING :([^ ]+)"
send: "PONG ${1}"
- expect: "^:[^ ]+ 001"
icmp:
prober: icmp
custom_http_check:
prober: http
timeout: 5s
http:
method: GET
valid_http_versions: [ "1.1" ] # Adjusted this to valid version
5. Set Up Prometheus
- Install Prometheus:
sudo apt install prometheus -y

- Create Prometheus Configuration:
Create a prometheus.yaml file:
Place the prometheus.yaml file in the directory where you have installed Prometheus, which in my case is:
/blackbox_exporter-0.21.0.linux-amd64
cd /blackbox_exporter-0.21.0.linux-amd64
vi prometheus.yaml
Paste the following configuration:
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'blackbox'
metrics_path: /probe
params:
module: [http_2xx]
static_configs:
- targets:
- http://prometheus.io
- https://prometheus.io
- <your-blog-app-url> # Replace with your app URL
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: <blackbox_exporter_ip>:9115 # Blackbox Exporter address
This configuration tells Prometheus how to scrape metrics from itself and the Blackbox Exporter, including the target URLs to probe.
Make sure to change the blackbox exporter address and blog app url linkto that which points to your VM IP. and change the blog app url link
- Start Prometheus:
Since the executable is located at /usr/bin/prometheus, you can start it directly from there with your configuration file:
/usr/bin/prometheus --config.file=/path/to/prometheus.yaml
For ex:
/usr/bin/prometheus --config.file=/home/ubuntu/blackbox_exporter-0.21.0.linux-amd64/prometheus.yaml
This command starts the Prometheus server with the specified configuration file.
This ensures Prometheus knows where to find its settings for scraping metrics and other configurations. It’s like telling Prometheus: "Here’s your manual, go do your job."
Access Prometheus at: http://<prometheus-ip>:9090

6. Set Up Grafana
- Install Grafana:
# Update package list and install necessary dependencies
sudo apt-get update
sudo apt-get install -y software-properties-common curl
# Add Grafana GPG key
curl https://packages.grafana.com/gpg.key | sudo apt-key add -
# Add Grafana APT repository
sudo add-apt-repository "deb https://packages.grafana.com/oss/deb stable main"
# Update package list again and install Grafana
sudo apt-get update
sudo apt-get install -y grafana
- Start Grafana Service:
Grafana will be used for visualizing metrics collected by Prometheus.
# reload the systemd daemon to pick up the changes.
sudo systemctl daemon-reload
# Start Grafana service
sudo systemctl start grafana-server
# Enable Grafana to start on boot
sudo systemctl enable grafana-server
# Print the status of Grafana service
sudo systemctl status grafana-server
Grafana will now be running at: http://<your-ec2-ip>:3000
7. Start Blackbox Exporter as a Service
To ensure that Blackbox Exporter runs on boot, create a systemd service:
- Create Service File:
sudo vi /etc/systemd/system/blackbox_exporter.service
Add the following content:
[Unit]
Description=Blackbox Exporter
After=network.target
[Service]
User=ubuntu
ExecStart=/path/to/blackbox_exporter --config.file=/path/to/blackbox.yml
Restart=always
[Install]
WantedBy=multi-user.target
- Reload Systemd and Start the Service:
sudo systemctl daemon-reload
sudo systemctl start blackbox_exporter
sudo systemctl enable blackbox_exporter
- Verify Blackbox Exporter:
Access the status page at http://<your-ec2-ip>:9115.

8. Configure Grafana
- Access Grafana:
Navigate to http://<your-ec2-ip>:3000 and log in with the default credentials (admin/admin).
- Add Prometheus as a Data Source:
Go to Configuration > Data Sources.
Click Add data source and select Prometheus.
Set the URL to
http://<your-ec2-ip>:9090and click Save & Test.
- Import Dashboard:
Click on Import Dashboard (left pane).
Enter the dashboard ID:
7587and click Load.Select Prometheus as the data source and click Import.



9. Verify Installations
Run these commands to check that all services are running:
# Blackbox Exporter
curl http://localhost:9115
curl http://localhost:9115/metrics
# Prometheus
curl http://localhost:9090/metrics
# Grafana
sudo systemctl status grafana-server

Summary of the Blue-Green Deployment Architecture
This project implements a Blue-Green Deployment strategy using a CI/CD pipeline orchestrated by Jenkins, integrated with various DevOps tools to ensure smooth and seamless application delivery and infrastructure management.
Continuous Integration & Delivery Pipeline:
Developer commits changes to GitHub, triggering the Jenkins pipeline.
Jenkins handles the build, testing, security scanning, and deployment tasks, utilizing Maven, SonarQube (for code quality analysis), and Trivy (for vulnerability scanning).
Nexus is used for artifact management, storing built images for versioning.
Containerization & Deployment:
After the build, the application is containerized using Docker and pushed to DockerHub.
The application is then deployed onto Amazon EKS (Elastic Kubernetes Service) clusters using Terraform for infrastructure provisioning.
Blue-Green Deployment Strategy:
A LoadBalancer Service is used to route traffic between the Blue and Green environments.
The Blue environment serves as the current live version, while the Green environment is used to deploy and test the new version in parallel.
The LoadBalancer service creates an external IP (or DNS) and routes traffic based on the deployment strategy. Once the Green environment passes all tests, traffic is seamlessly switched to the new version, ensuring zero downtime.
Infrastructure Automation:
- Terraform automates the provisioning of infrastructure, creating the necessary Kubernetes clusters, services, and deployments within the AWS EKS environment.
This architecture enables reliable, scalable, and secure application deployment with minimal downtime, making use of a modern DevOps toolchain for efficient management and orchestration of application releases.
This project taught me so much about real-world deployments and how to keep users happy by avoiding downtime. It was a powerful learning experience, and now I get to see how these strategies are used by major platforms every day! 💪



