Skip to main content

Command Palette

Search for a command to run...

Project 15: Jenkins Driven: CI/CD for Uber Clone (Step By Step Implementation)

Updated
β€’11 min read
Project 15: Jenkins Driven: CI/CD for Uber Clone (Step By Step Implementation)

Introduction:

Welcome to "Jenkins Driven: CI/CD for Uber Clone" – an immersive journey into the heart of DevSecOps automation. πŸš€ In this project, we leverage the power of Jenkins to orchestrate a robust CI/CD pipeline for deploying an Uber clone app. From setting up AWS resources and Terraform provisioning to integrating SonarQube for security scans, Docker for containerization, and Kubernetes for seamless deployment – this guide is your compass through the intricate landscape of modern software development. 🌐 Fasten your seatbelts as we navigate the cloud-native realm, ensuring a smooth ride from code to production. Let's embark on this Jenkins-driven adventure in building and securing your Uber-inspired application! πŸ› οΈπŸ’»

Technologies Used in This Project:

  1. Jenkins: πŸš€ As the heart of the CI/CD pipeline, Jenkins orchestrates the seamless integration and deployment of the Uber Clone app, ensuring efficiency and automation in the software development lifecycle.

  2. Terraform: ☁️ Leveraging Terraform, we automate the provisioning of AWS resources and the creation of an Elastic Kubernetes Service (EKS) cluster, enabling scalable and efficient infrastructure management.

  3. SonarQube: πŸ” SonarQube enhances code quality by providing continuous inspection and reporting. It identifies and fixes security vulnerabilities and ensures adherence to coding standards in our Uber Clone application.

  4. Docker: 🐳 Docker facilitates containerization, enabling the consistent deployment of the Uber Clone app across different environments. It enhances scalability, portability, and resource efficiency.

  5. Kubernetes: 🚒 Kubernetes orchestrates the deployment, scaling, and management of containerized applications. In our project, it ensures the efficient running of the Uber Clone app, enhancing scalability and reliability.

  6. Node.js: 🌐 Node.js powers the backend of our Uber Clone app, providing a scalable and high-performance runtime environment for building server-side applications.

  7. OWASP Dependency-Check: πŸ›‘οΈ This tool scans project dependencies for known vulnerabilities, ensuring that our Uber Clone app is protected against potential security threats.

  8. Trivy: πŸ•΅οΈβ€β™‚οΈ Trivy performs container image vulnerability scanning, allowing us to identify and mitigate security risks in the Docker images used in our project.

  9. GitHub: πŸ›‚ GitHub serves as the version control and collaboration platform, enabling effective team collaboration, version tracking, and code review for the Uber Clone project.

  10. Elastic Kubernetes Service (EKS): 🌐 Amazon EKS simplifies the deployment, management, and scaling of containerized applications using Kubernetes, enhancing the scalability and availability of our Uber Clone app.

Project Overview:

Project:

GITHUB REPO: https://github.com/patelajay745/uber-clone.git

Step 1 : Launch Ec2 Instance with Ubnuntu AMI and t2.large type. I have used following terraform file to launch it.

provider "aws" {
  region = "us-east-2" # Change this to your desired AWS region
}

resource "aws_instance" "my_instance" {
  count = 1


  ami                    = "ami-05fb0b8c1424f266b" # Specify the AMI ID for your desired Amazon Machine Image
  instance_type          = "t2.large"
  key_name               = "admin-ajay" # Change this to your key pair name
  vpc_security_group_ids = [aws_security_group.terraform-instance-sg.id]


  tags = {
    Name = "Jenkins_Server"
  }
 #for storage
  root_block_device {
    volume_size = 30
  }


}

output "jenkins_public_ip" {
    value = [for instance in aws_instance.my_instance : instance.public_ip]

}



#Create security group 
resource "aws_security_group" "terraform-instance-sg" {
  name        = "terraform-craeted-sg"
  description = "Allow inbound ports 22, 8080"
  vpc_id      = "vpc-0a35a83de5d6649ab"

  #Allow incoming TCP requests on port 22 from any IP
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  #Allow incoming TCP requests on port 443 from any IP
  ingress {
    description = "Allow HTTPS Traffic"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    description = "Allow Sonar Traffic"
    from_port   = 9000
    to_port     = 9000
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  #Allow incoming TCP requests on port 8080 from any IP
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  #Allow incoming TCP requests on port 8080 from any IP
  ingress {
    from_port   = 8080
    to_port     = 8080
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }


  #Allow all outbound requests
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

Step 2 : Create an IAM role for the newly created EC2 instance.

Navigate to IAM Roles and click on "Create Role."

Select "EC2" as the use case and proceed to the next step. Search for "AdministratorAccess" (for learning purposes) and click "Next."

Provide a name for the role and click "Create Role."

Now, attach the role to the EC2 instance. Choose the instance, then go to Actions > Security > Modify IAM role.

Select the created role from the list and click on "Update IAM role."

Step 3: Install Required packages.

Install the required packages by SSHing into the EC2 instance.

Create two scripts, namely "jenkins-docker.sh" and "other-packages.sh"

jenkins-docker.sh

#!/bin/bash
sudo apt update -y
sudo apt install fontconfig openjdk-17-jre -y
java -version
sudo wget -O /usr/share/keyrings/jenkins-keyring.asc \
  https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
  https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
  /etc/apt/sources.list.d/jenkins.list > /dev/null
sudo apt-get update -y
sudo apt-get install jenkins -y
sudo systemctl enable jenkins 
sudo systemctl start jenkins 

#install docker
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg -y
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] 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
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
sudo usermod -aG docker ubuntu
newgrp docker

other-packages.sh

#!/bin/bash
# install trivy
sudo apt-get install wget apt-transport-https gnupg lsb-release -y
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] 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 -y
#install terraform
sudo apt install wget -y
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform
#install Kubectl on Jenkins
sudo apt update
sudo apt install curl -y
curl -LO https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
kubectl version --client
#install Aws cli
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
sudo apt-get install unzip -y
unzip awscliv2.zip
sudo ./aws/install

Execute both scripts using the following command.

chmod 777 jenkins-docker.sh
chmod 777 other-packages.sh
./jenkins-docker.sh
./other-packages.sh

Verify the installation of all packages.

docker --version 
trivy --version
aws --version
terraform --version
kubectl version

Grant executable permissions for docker.sock and initiate the Docker container for SonarQube.

sudo chmod 777 /var/run/docker.sock
docker run -d --name sonar -p 9000:9000 sonarqube:lts-community

Step 4: Establish a connection between Jenkins and SonarQube.

Copy the IP address of the EC2 instance and paste it into the browser.

<Ec2-ip:8080>

It will prompt for a password.

Retrieve the password and complete the installation.

Jenkins Dashboard.

Now access SonarQube using:

<ec2-ip:9000>

It will ask for the default username and password. Enter "admin" in both.

The SonarQube dashboard will look like this.

Step 5: Terraform Configuration and EKS Provisioning

Now, navigate to Jenkins and add the Terraform plugin to facilitate the AWS EKS provisioning through the Pipeline Job.

Follow these steps:

  1. Access the Jenkins dashboard –> Manage Jenkins –> Plugins.

  1. In the Available Plugins section, search for "Terraform" and install it.

To determine the path to Terraform, you can use the following command in terminal(Ec2 SSH):

which terraform

Navigate back to the Jenkins dashboard and follow these steps to add Terraform to the tools:

Find the section for adding tools, and look for Terraform in the list.

Add Terraform, specifying the name and the path to the Terraform executable on your system (the path you obtained using the which terraform command).

Modify the S3 bucket name in the backend.tf file. If you have forked the Git repository, navigate to the EKS_terraform folder and make the necessary changes. Update the S3 bucket name according to your preferences or project requirements. This ensures that Terraform uses the correct backend configuration for storing its state files.

Create a new Jenkins job for provisioning Amazon EKS. This job will be responsible for managing the deployment and configuration of your EKS cluster.

I aim to incorporate build parameters to facilitate the application and destruction processes during the build phase exclusively. Please include the following configuration inside the job, as depicted in the image below.

Pipeline Code:


pipeline{
    agent any
    stages {
        stage('Checkout from Git'){
            steps{
                git branch: 'main', url: 'https://github.com/patelajay745/uber-clone.git'
            }
        }
        stage('Terraform version'){
             steps{
                 sh 'terraform --version'
             }
        }
        stage('Terraform init'){
             steps{
                 dir('EKS_TERRAFORM') {
                      sh 'terraform init'
                   }
             }
        }
        stage('Terraform validate'){
             steps{
                 dir('EKS_TERRAFORM') {
                      sh 'terraform validate'
                   }
             }
        }
        stage('Terraform plan'){
             steps{
                 dir('EKS_TERRAFORM') {
                      sh 'terraform plan'
                   }
             }
        }
        stage('Terraform apply/destroy'){
             steps{
                 dir('EKS_TERRAFORM') {
                      sh 'terraform ${action} --auto-approve'
                   }
             }
        }
    }
}

Click "Save," then proceed to "Build with Parameters." Choose "apply" and click "Build."

The EKS provisioning process will take some time. If everything is configured correctly, the status will resemble the image below.

Now check created resource in AWS console.

Step 6: Plugin Installation and Setup (Java, Sonar, Node.js, OWASP, Docker)

Navigate to the Jenkins dashboard.

Go to "Manage Jenkins" β†’ "Plugins" β†’ "Available Plugins."

Search for the following plugins:

  1. Eclipse Temurin Installer

  2. SonarQube Scanner

  3. NodeJS

  4. OWASP Dependency-Check

  5. Docker

  6. Docker Commons

  7. Docker Pipeline

  8. Docker API

  9. Docker Build Step

Step 7: Configuration of Global tools.

Navigate to "Manage Jenkins" β†’ "Tools" β†’ Install JDK(17) and Node.js(16) β†’ Click on "Apply and Save."

For SonarQube:

For Owasp:

For Docker:

Click on "Apply and Save."
Step 8: Configure Sonar Server in Manage Jenkins

Retrieve the Public IP Address of your EC2 Instance. Since SonarQube operates on Port 9000, access it via <Public IP>:9000.

Visit your SonarQube Server, navigate to Administration β†’ Security β†’ Users, click on Tokens, update the token by assigning it a name, and then generate the token.

Enter name of token then click on "Generate"

Copy the token, then go to the Jenkins Dashboard β†’ Manage Jenkins β†’ Credentials β†’ Add Secret Text. The entry should resemble this.

Now, Navigate to Dashboard β†’ Manage Jenkins β†’ System and Add like the below image.

Click on "Apply and Save."

In the Sonarqube Dashboard, also include a quality gate by navigating to Administration β†’ Configuration β†’ Webhooks.

Click on "Create"

In URL Section:
<http://jenkins-public-ip:8080>/sonarqube-webhook/>

Now, integrate Docker credentials into Jenkins for logging in and pushing the image:

Navigate to Manage Jenkins β†’ Credentials β†’ Global β†’ Add Credential.

Provide DockerHub Username and Password under Global Credentials.

Step 9: Pipeline up to Docker

Now, let's create a new job for our pipeline.

Add Following script in pipeline section.

pipeline{
    agent any
    tools{
        jdk 'jdk17'
        nodejs 'node16'
    }
    environment {
        SCANNER_HOME=tool 'sonar-scanner'
    }
    stages {
        stage('clean workspace'){
            steps{
                cleanWs()
            }
        }
        stage('Checkout from Git'){
            steps{
                git branch: 'main', url: 'https://github.com/patelajay745/uber-clone.git'
            }
        }
        stage("Sonarqube Analysis "){
            steps{
                withSonarQubeEnv('sonar-server') {
                    sh ''' $SCANNER_HOME/bin/sonar-scanner -Dsonar.projectName=Uber \
                    -Dsonar.projectKey=Uber'''
                }
            }
        }
        stage("quality gate"){
           steps {
                script {
                    waitForQualityGate abortPipeline: false, credentialsId: 'Sonar-Token'
                }
            }
        }
        stage('Install Dependencies') {
            steps {
                sh "npm install"
            }
        }
        stage('OWASP FS SCAN') {
            steps {
                dependencyCheck additionalArguments: '--scan ./ --disableYarnAudit --disableNodeAudit', odcInstallation: 'DP-Check'
                dependencyCheckPublisher pattern: '**/dependency-check-report.xml'
            }
        }
         stage('TRIVY FS SCAN') {
            steps {
                sh "trivy fs . > trivyfs.txt"
            }
        }
        stage("Docker Build & Push"){
            steps{
                script{
                   withDockerRegistry(credentialsId: 'docker', toolName: 'docker'){
                       sh "docker build -t uber ."
                       sh "docker tag uber patelajay745/uber:latest "
                       sh "docker push patelajay745/uber:latest "
                    }
                }
            }
        }
        stage("TRIVY"){
            steps{
                sh "trivy image patelajay745/uber:latest > trivyimage.txt"
            }
        }
        stage("deploy_docker"){
            steps{
                sh "docker stop uber || true"  // Stop the container if it's running, ignore errors
                sh "docker rm uber || true" 
                sh "docker run -d --name uber -p 3000:3000 patelajay745/uber:latest"
            }
        }
    }
}

Click on "Apply and Save."

Click on "Build Now"

Now see the reports on SonarQube dashboard.

When you log in to Dockerhub, you will see a new image is created

Step 10: Deployment on EKS

SSH to Jenkins server and enter following command:

aws eks update-kubeconfig --name <CLUSTER NAME> --region <CLUSTER REGION>
aws eks update-kubeconfig --name EKS_CLOUD --region us-east-2

Check status of worker node.

Get config file using following code.

cat ~/.kube/config

Copy it and save it in a document or another folder, naming it secret-file.txt.

Note: Create a file named secret-file.txt in your file explorer, store the configuration within it, and utilize it in the Kubernetes credential section.

Now install required plugin for kubernates in Jenkins.

Go to "Manage Jenkins" β†’ "Plugins" β†’ "Available Plugins."

Search for the following plugins:

Navigate to Manage Jenkins β†’ Credentials β†’ Global β†’ Add Credential.

Add Final Stage into pipeline to deploy on the Kubernetes cluster.

stage('Deploy to Kubernetes') {
            steps {
                script {
                    dir('K8S') {
                        withKubeConfig(caCertificate: '', clusterName: '', contextName: '', credentialsId: 'k8s', namespace: '', restrictKubeConfigAccess: false, serverUrl: '') {
                            // Apply deployment and service YAML files
                            sh 'kubectl apply -f deployment.yml'
                            sh 'kubectl apply -f service.yml'

                            // Get the external IP or hostname of the service
                            def externalIP = sh(script: 'kubectl get svc uber-service -o jsonpath="{.status.loadBalancer.ingress[0].hostname}"', returnStdout: true).trim()

                            // Print the URL in the Jenkins build log
                            echo "Service URL: http://${externalIP}/"
                        }
                    }
                }
            }
        }

Find Weburl from Jenkins Console output.

Access on web browser.

Final pipeline.

Step 11: Destroy EKS cluster when your done with project.

Don't Forget to Destroy Terraform created Ec2 instance for Jenkins server.

Conclusion

Congratulations on completing the "Jenkins Driven: CI/CD for Uber Clone" project! πŸŽ‰ This immersive journey guided you through setting up AWS resources, Terraform provisioning, integrating SonarQube for security scans, and deploying with Docker and Kubernetes. Embrace the power of CI/CD with Jenkins, ensuring a seamless ride from code to production for your Uber-inspired application. πŸŒπŸš€

If you have any questions or feedback, feel free to reach out. Happy coding! πŸ’»πŸ› οΈ

For learners: It's okay to make mistakes. Every mistake helps you learn. Check out my pipeline that didn't work. πŸš€

More from this blog

Ajay Patel

116 posts