Skip to main content

Command Palette

Search for a command to run...

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

Updated
42 min read
⎈ Blue-Green Deployment on Amazon EKS Using CI/CD Pipeline 🟦🟩
S
My name is Sandhya. I come from a non-tech background with six years of experience before taking a two-year career break to learn cloud computing. Today I work as an AWS Cloud Infrastructure Support Engineer — my first year in tech. Now I have a new goal: transition into AI and MLOps engineering. And it all starts with Python. This blog is my public learning diary. I will document every step — the wins, the errors, the confusion, and the breakthroughs. If you are also starting from scratch, I hope this helps you feel less alone.

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:

  1. 🖥️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.

  2. 🚀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.

  3. 🔍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.

  4. 🔄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.

  5. 📺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.

  6. ⚠️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.

  7. 🛠️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=true flag 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

  1. Log in to the AWS Management Console.

  2. Navigate to the EC2 Dashboard to launch a new instance.

  3. 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.

  4. 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

  1. 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

  1. Update the package lists & install the required packages (wget and unzip):
sudo apt update
sudo apt install wget unzip -y
  1. 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.

  1. 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 eksctl installed, making it your primary hub for managing EKS infrastructure. Adding kubectl lets 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.medium

    • vCPUs: 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

  1. SSH into the Jenkins instance

  2. Update & Install Java for Jenkins

 # update the packages
sudo apt update
# Install OpenJDK 17 JRE Headless
sudo apt install openjdk-17-jre-headless  -y

  1. 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:

  1. 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
  1. 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:

  1. Add Jenkins to the Docker Group:
sudo usermod -aG docker jenkins
  1. 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

  1. Navigate to Plugins: Manage Jenkins > Manage Plugins

  2. Install 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

  1. Install:
    Click Install without restart and wait for the plugins to install

🔨 Configure Maven and SonarQube Scanner

  1. Global Tool Configuration:

    • Maven: Add maven3

    • SonarQube 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)

  1. 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

  1. 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)

  1. 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
  1. 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: admin

  • Password: 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:

  1. Go to Jenkins Dashboard.

⚙️ Manage Jenkins:

  1. Click on Manage Jenkins.

⚙️ System:

  1. Select Configure System.

🔌 SonarQube Servers:

  1. Scroll to the SonarQube servers section.

➕ Add SonarQube:

  1. Click Add SonarQube under SonarQube installations.

📝 Enter Details:

  1. Provide Name, Server URL, and Token (Select the token from credentials).

💾 Save:

  1. 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 webapps namespace.

  • Role: Defines a role named app-role that allows Jenkins to perform actions on resources like pods, deployments, and services in the webapps namespace.

  • RoleBinding: Binds the app-role to the jenkins service account, giving it the necessary permissions in the webapps namespace.

  • ClusterRole: Creates a cluster-wide role named jenkins-cluster-role that allows Jenkins to manage persistent volumes.

  • ClusterRoleBinding: Binds the jenkins-cluster-role to the jenkins service account, granting it cluster-wide permissions.

  • Token Generation: Generates an authentication token for the jenkins service 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.

  1. Creating namespace webapps in EKS:
kubectl create ns webapps
  1. Create a Jenkins service account in the webapps namespace. Create a file service-account.yml with content as:
apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins
  namespace: webapps with content as:
  1. Apply the YAML definition
kubectl apply -f service-account.yml

  1. 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.yml with 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"]
  1. Apply the YAML definition
kubectl apply -f role.yml

  1. Create and apply a role binding:
  • The next step is to bind the created role app-role to the jenkins service account, giving it the necessary permissions in the webapps namespace. Create a file named rolebind.yml with 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

  1. Apply the YAML definition
kubectl apply -f rolebind.yml
  1. Create and apply a secret:
  • Next, create a secret token for the Jenkins service account. Create a file secret.yml with the content:
apiVersion: v1
kind: Secret
type: kubernetes.io/service-account-token
metadata:
  name: mysecretname
  annotations:
    kubernetes.io/service-account.name: jenkins
  1. 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:

  1. Copy Token: Run kubectl describe secret mysecretname -n webapps and copy the token.

  2. Log in to Jenkins: Go to http://<jenkins_public_ip>:8080 and log in.

  3. 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:

  1. Go to Manage Jenkins.

📁 Manage Files:

  1. Click on Manage Files.

➕ Add New Config:

  1. Select Add a new config.

🔧 Global Maven Settings XML:

  1. Choose Global Maven settings XML.

✏️ Replace ID:

  1. Change the ID to maven-settings and 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-releases and 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

  1. Log in to SonarQube
    🔐 Open your SonarQube instance and log in.

  2. Navigate to Webhooks
    ⚙️ Go to Administration > Configuration > Webhooks.

  3. Click Create to Add a New Webhook
    ➕ Add a webhook.

  4. 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/

  1. 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)

  1. Navigate to New Pipeline
    🛠️ From the Jenkins dashboard, click New Item.

  2. Create Pipeline

    • ✏️ Enter the Name: Blue-Green.

    • 📂 Select Pipeline: Choose Pipeline as the project type.

    • ✅ Click OK.

  3. Configure Pipeline
    ⚙️ Scroll to the Pipeline section and define your pipeline script or choose Pipeline script from SCM.

  4. 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 the DOCKER_TAG parameter.

    • 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:

  1. Environment Check: Depending on the DEPLOY_ENV parameter, either the app-deployment-blue.yml or app-deployment-green.yml file is selected.

  2. 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:

  1. Condition Check: The stage only runs if the SWITCH_TRAFFIC parameter is set to true

  2. Traffic 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:

  1. Pods:

    • pod/bankapp-blue-f549f7b45-k5pts: This pod is Running with 1/1 ready, indicating that the application is up and functioning properly.

    • pod/mysql-f5c84b88-nnsgl: This MySQL pod is also Running with 1/1 ready, which means the database is operational as well.

  2. Services:

    • service/bankapp-service: This LoadBalancer service is correctly exposing the bankapp on 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.

  3. Deployments:

    • deployment.apps/bankapp-blue: It shows that 1/1 is ready and available, meaning the deployment is healthy.

    • deployment.apps/mysql: Also healthy with 1/1 ready.

  4. ReplicaSets:

    • The old ReplicaSet bankapp-blue-6855f6f4f7 has scaled down to 0 pods, which is good as it indicates the old version of the deployment is no longer active.

    • The new ReplicaSet bankapp-blue-f549f7b45 has 1 pod 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/bankapp in 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, not sandhya/bankapp:blue.

  • Verify Image Existence: Ensure the image sandhyadev836/bankapp:blue exists 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.large with 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.

  1. 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
  1. Configure Blackbox Exporter:

    Create the blackbox.yml configuration 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 to http_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

  1. Install Prometheus:
sudo apt install prometheus -y

  1. 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

  1. 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

  1. 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
  1. 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:

  1. 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
  1. Reload Systemd and Start the Service:
sudo systemctl daemon-reload
sudo systemctl start blackbox_exporter
sudo systemctl enable blackbox_exporter
  1. Verify Blackbox Exporter:

Access the status page at http://<your-ec2-ip>:9115.


8. Configure Grafana

  1. Access Grafana:

Navigate to http://<your-ec2-ip>:3000 and log in with the default credentials (admin/admin).

  1. 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>:9090 and click Save & Test.

  1. Import Dashboard:
  • Click on Import Dashboard (left pane).

  • Enter the dashboard ID: 7587 and 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.

  1. 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.

  2. 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.

  3. 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.

  4. 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! 💪

A

Hi Sandhya,

Did u follow any resources for this, if yes pls can you share them.

Thanks

S
Sandhya B1y ago

Hi Abhishek, I have followed Aditya Jaiswal's YouTube video.

2

More from this blog

💻 Sandhya Babu's DevOps Journey 🚀

46 posts

🌟 Welcome to My Blog! 🌟

Dive into my DevOps and Cloud Computing journey with tutorials and insights on Kubernetes, CI/CD, Docker, and more. Join me in exploring tech together!