The Ultimate CI/CD DevOps Pipeline Project

Introduction

This article provides a comprehensive guide on setting up a Continuous Integration/Continuous Deployment (CI/CD) pipeline using various DevOps tools. The project involves deploying a board game application on a Kubernetes cluster, with the pipeline set up in Jenkins.

Phase 1: Infrastructure Setup

Setting Up the Environment

The environment setup involves creating an Ubuntu EC2 instance in AWS. Here are the steps to create an Ubuntu EC2 instance:

  1. Sign in to the AWS Management Console.
  2. Navigate to the EC2 dashboard.
  3. Click on the “Instances” link in the EC2 dashboard sidebar.
  4. Click the “Launch Instance” button.
  5. In the “Step 1: Choose an Amazon Machine Image (AMI)” section, select “Ubuntu” from the list of available AMIs.
  6. Choose the Ubuntu version you want to use. For example, “Ubuntu Server 20.04 LTS”.
  7. In the “Step 2: Choose an Instance Type” section, select the instance type that fits your requirements. The default option (usually a t2.micro instance) is suitable for testing and small workloads.
  8. Configure instance details such as network settings, subnets, IAM role, etc. You can leave these settings as default for now.
  9. Specify the size of the root volume (default is usually fine for testing purposes).
  10. Optionally, add tags to your instance for better organization and management.
  11. In the “Step 6: Configure Security Group” section, configure the security group to allow SSH access (port 22) from your IP address. You may also want to allow other ports based on your requirements (e.g., HTTP, HTTPS).
  12. Review the configuration of your instance.
  13. Select an existing key pair or create a new one.
  14. Check the acknowledgment box.
  15. Click “Launch Instances”.
  16. Access Your Instance: Use Mobaxterm

Setting Up Kubernetes

A Kubernetes cluster is set up using kubeadm. The cluster is configured to use Calico for networking and NGINX for ingress control. Here are the steps to set up Kubernetes:

  1. Update System Packages [On Master & Worker Node]
sudo apt-get update
  1. Install Docker[On Master & Worker Node]
sudo apt install docker.io -y 
sudo chmod 666 /var/run/docker.sock
  1. Install Required Dependencies for Kubernetes[On Master & Worker Node]
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg 
sudo mkdir -p -m 755 /etc/apt/keyrings
  1. Add Kubernetes Repository and GPG Key[On Master & Worker Node]
curl -fsSL [2](https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key) | sudo gpg -- dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring. gpg 
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring. gpg] [3](https://pkgs.k8s). io/core: /stable : /v1. 28/deb/ /' | sudo tee /etc/apt/sources. list.d/kubernetes. list
  1. Update Package List[On Master & Worker Node]
sudo apt update
  1. Install Kubernetes Components[On Master & Worker Node]
sudo apt install -y kubeadm=1.28.1-1.1 kubelet=1.28.1-1.1 kubectl=1.28.1-1.1
  1. Initialize Kubernetes Master Node [On MasterNode]
sudo kubeadm init -- pod-network-cidr=10.244.0.0/16
  1. Configure Kubernetes Cluster [On MasterNode]
mkdir -p $HOME/ .kube 
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
  1. Deploy Networking Solution (Calico) [On MasterNode]
kubectl apply -f https: //docs. projectcalico.org/v3.20/manifests/calico. yaml
  1. Deploy Ingress Controller (NGINX) [On MasterNode]
kubectl apply -f [4](https://raw.githubusercontent). com/kubernetes/ingress - nginx/controller-v0.49.0/deploy/static/provider/baremetal/deploy. yaml

Setting Up Jenkins

Jenkins is installed on the Ubuntu instance. Various plugins like Eclipse Temurin Installer, Pipeline Maven Integration, Config File Provider, SonarQube Scanner, Kubernetes CLI, Kubernetes, Docker, and Docker Pipeline Step are installed in Jenkins to support the pipeline. Here are the steps to install Jenkins on Ubuntu:

  1. Install OpenJDK 17 JRE Headless
sudo apt install openjdk-17-jre-headless -y
  1. Download Jenkins GPG key
sudo wget -O /usr/share/keyrings/jenkins-keyring.asc \\ [5](https://pkg). jenkins. io/debian-stable/jenkins. io-2023. key
  1. Add Jenkins repository to package manager sources

/dev/null “>

echo deb [signed-by=/usr/share/keyrings/jenkins-keyring. asc] \\ [6](https://pkg.jenkins.io/debian-stable) binary/ | sudo tee | /etc/apt/sources. list.d/jenkins. list > /dev/null
  1. Update package manager repositories
sudo apt-get update
  1. Install Jenkins
sudo apt-get install jenkins -y

Setting Up Nexus

Nexus is set up using a Docker container. It is used as a repository to store build artifacts. Here are the steps to set up Nexus:

  1. Update package manager repositories
sudo apt-get update
  1. Install necessary dependencies
sudo apt-get install -y ca-certificates curl
  1. Create directory for Docker GPG key
sudo install -m 0755 -d /etc/apt/keyrings
  1. Download Docker’s GPG key
sudo curl -fsSL [7](https://download.docker.com/linux/ubuntu/gpg) -o /etc/apt/keyrings/docker.asc
  1. Ensure proper permissions for the key
sudo chmod a+r /etc/apt/keyrings/docker.asc
  1. Add Docker repository to Apt sources

/dev/null “>

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
  1. Update package manager repositories
sudo apt-get update
  1. Install Docker
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugi
  1. Create Nexus using docker container
docker run -d -- name nexus -p 8081: 8081 sonatype/nexus3: latest

Setting Up SonarQube

SonarQube is also set up using a Docker container. It is used for code quality and security analysis. Here are the steps to set up SonarQube:

  1. Update package manager repositories
sudo apt-get update
  1. Install necessary dependencies
sudo apt-get install -y ca-certificates curl
  1. Create directory for Docker GPG key
sudo install -m 0755 -d /etc/apt/keyrings
  1. Download Docker’s GPG key
sudo curl -fsSL [7](https://download.docker.com/linux/ubuntu/gpg) -o /etc/apt/keyrings/docker.asc
  1. Ensure proper permissions for the key
sudo chmod a+r /etc/apt/keyrings/docker.asc
  1. Add Docker repository to Apt sources

/dev/null “>

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
  1. Update package manager repositories
sudo apt-get update
  1. Install Docker
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  1. Create Sonarqube Docker container
docker run -d --name sonar -p 9000:9000 sonarqube:lts-community

Phase 2: Private Git Setup

Steps to create a private Git repository, generate a personal access token, connect to the repository, and push code to it:

Create a Private Git Repository:

Go to your preferred Git hosting platform (e.g., GitHub, GitLab, Bitbucket).

Log in to your account or sign up if you don’t have one.

Create a new repository and set it as private.

Generate a Personal Access Token:

Navigate to your account settings or profile settings.

Look for the “Developer settings” or “Personal access tokens” section.

Generate a new token, providing it with the necessary permissions (e.g., repo access).

Clone the Repository Locally:

Open Git Bash or your terminal.

Navigate to the directory where you want to clone the repository.

Use the git clone command followed by the repository’s URL. For example:

  • git clone <repository_URL>

Replace <repository_URL> with the URL of your private repository.

Add Your Source Code Files:

Navigate into the cloned repository directory.

Paste your source code files or create new ones inside this directory.

Stage and Commit Changes:

Use the git add command to stage the changes:

  • git add .

Use the git commit command to commit the staged changes along with a meaningful message:

  • git commit -m "Your commit message here"

Push Changes to the Repository:

Use the git push command to push your committed changes to the remote repository:

  • git push

If it’s your first time pushing to this repository, you might need to specify the remote and branch:

  • git push -u origin master

Replace master with the branch name if you’re pushing to a different branch.

Enter Personal Access Token as Authentication:

When prompted for credentials during the push, enter your username (usually your email) and use your personal access token as the password.

By following these steps, you’ll be able to create a private Git repository, connect to it using Git Bash, and push your code changes securely using a personal access token for authentication.

Phase 3: CI/CD Pipeline

Pipeline Configuration

The pipeline is configured in Jenkins using a declarative pipeline script. The pipeline stages include Git checkout, code compilation, unit testing, file system scan, SonarQube analysis, quality gate check, build packaging, artifact publishing to Nexus, Docker image build and push, deployment to Kubernetes, and deployment verification.

Here is an example of a Jenkins pipeline configuration:

pipeline {
agent any
tools {
jdk 'jdk17'
maven 'maven3'
}
environment {
SCANNER_HOME = tool 'sonar-scanner'
}
stages {
stage('Git Checkout') {
steps {
git branch: 'main', credentialsId: 'git-cred', url: 'YOUR_GIT_REPO_URL'
}
}
stage('Compile') {
steps {
sh "mvn compile"
}
}
stage('Test') {
steps {
sh "mvn test"
}
}
stage('File System Scan') {
steps {
sh "trivy fs --format table -o trivy-fs-report.html ."
}
}
stage('SonarQube Analysis') {
steps {
withSonarQubeEnv('sonar') {
sh '''$SCANNER_HOME/bin/sonar-scanner -Dsonar.projectName=BoardGame -Dsonar.projectKey=BoardGame -Dsonar.java.binaries=.'''
}
}
}
stage('Quality Gate') {
steps {
script {
waitForQualityGate abortPipeline: false, credentialsId: 'sonar-token'
}
}
}
stage('Build') {
steps {
sh "mvn package"
}
}
stage('Publish To Nexus') {
steps {
withMaven(globalMavenSettingsConfig: 'global-settings', jdk: 'jdk17', maven: 'maven3', mavenSettingsConfig: '', traceability: true) {
sh "mvn deploy"
}
}
}
stage('Build & Tag Docker Image') {
steps {
script {
withDockerRegistry(credentialsId: 'docker-cred', toolName: 'docker') {
sh "docker build -t adijaiswal/boardshack:latest ."
}
}
}
}
stage('Docker Image Scan') {
steps {
sh "trivy image --format table -o trivy-image-report.html adijaiswal/boardshack:latest"
}
}
stage('Push Docker Image') {
steps {
script {
withDockerRegistry(credentialsId: 'docker-cred', toolName: 'docker') {
sh "docker push adijaiswal/boardshack:latest"
}
}
}
}
stage('Deploy To Kubernetes') {
steps {
withKubeConfig(caCertificate: '', clusterName: 'kubernetes', contextName: '', credentialsId: 'k8-cred', namespace: 'webapps', restrictKubeConfigAccess: false, serverUrl: 'https://YOUR_K8S_CLUSTER_IP:6443') {
sh "kubectl apply -f deployment-service.yaml"
}
}
}
stage('Verify the Deployment') {
steps {
withKubeConfig(caCertificate: '', clusterName: 'kubernetes', contextName: '', credentialsId: 'k8-cred', namespace: 'webapps', restrictKubeConfigAccess: false, serverUrl: 'https://YOUR_K8S_CLUSTER_IP:6443') {
sh "kubectl get pods -n webapps"
sh "kubectl get svc -n webapps"
}
}
}
}
post {
always {
script {
def jobName = env.JOB_NAME
def buildNumber = env.BUILD_NUMBER
def pipelineStatus = currentBuild.result ?: 'UNKNOWN'
def bannerColor = pipelineStatus.toUpperCase() == 'SUCCESS' ? 'green' : 'red'
def body = <html> <body> <div style="border: 4px solid ${bannerColor}; padding: 10px; "> <h2>${jobName} - Build ${buildNumber}</h2> <div style="background-color: ${bannerColor}; padding: 10px; "> <h3 style="color: white; ">Pipeline Status: ${pipelineStatus.toUpperCase()}</h3> </div> <p>Check the <a href="${BUILD_URL}">console output</a>.</p> </div> </body> </html>
emailext (
subject: "${jobName} - Build ${buildNumber} - ${pipelineStatus.toUpperCase()}",
body: body,
to: 'jaiswaladi246@gmail.com',
from: 'jenkins@example.com',
replyTo: 'jenkins@example.com',
mimeType: 'text/html',
attachmentsPattern: 'trivy-image-report.html'
)
}
}
}
}

Please replace YOUR_GIT_REPO_URL and YOUR_K8S_CLUSTER_IP with your actual Git repository URL and Kubernetes cluster IP respectively.

Phase 4: Monitoring

For monitoring the application and the Kubernetes cluster, you can use Prometheus, Node Exporter, Black Box Exporter, and Grafana. Here are the links to download these tools:

After downloading these tools, you can follow their respective installation and configuration guides to set up monitoring for your application and Kubernetes cluster.

Please note that this is a draft and might need further refinements. Also, remember to replace any sensitive information with placeholders when sharing the final article. Let me know if you need help with anything else!

Leave a Comment

Your email address will not be published. Required fields are marked *

© 2025 Roshan Kumar Thapa. All Rights Reserved.