Complete CI/CD Setup on Local System using Jenkins, Ansible and Kubernetes

Complete CI/CD Setup on Local System using Jenkins, Ansible and Kubernetes

Prerequisites

  • Sample Maven web application GitHub project

  • Install and Configure Jenkins

  • Install and Configure Ansible

  • Install a VM and name it Kubernetes

  • I have written code in files by the names I have given for files or services or versions. Please make sure to change that portion if you are using different names or different versions or different tags

Jenkins Server

  • create maven directory under /opt and download maven

  • install git and maven and export path in .bash_profile file in root directory

# Download maven in /opt/maven
wget <https://dlcdn.apache.org/maven/maven-3/3.9.2/binaries/apache-maven-3.9.2-bin.tar.gz>

# Extract the tar file
tar -xvzf apache-maven-3.9.2

# Updating PATH and adding below lines in .bash_profile file, make sure to give versions you downloaded
JAVA_HOME=/usr/lib/jvm/java-11-openjdk-11.0.16.1.1-3.el9.x86_64/ # find java path by find / javac
M2_HOME=/opt/maven/apache-maven-3.9.2
M2=$M2_HOME/bin
PATH=$PATH:$JAVA_HOME:$M2_HOME:$M2:$HOME/bin
export PATH

#Installing GIT
yum install git -y

Ansible Server

# Adding ansadmin user to docker group
sudo usermod -aG docker ansadmin
  • Create folders docker and playbooks under /opt and give ownership of these folders and of /etc/ansible folder to ansadmin user
# Giving ownership of folders to ansadmin user
sudo chown -R ansadmin:ansadmin /opt/playbooks

# Giving ownership of folders to ansadmin user
sudo chown -R ansadmin:ansadmin /opt/docker

# Giving ownership of folders to ansadmin user
sudo chown -R ansadmin:ansadmin /etc/ansible
  • Create a Dockerfile and in /opt/docker folder
# Move to /opt/docker
cd /opt/docker

# Create a Dockerfile
vi Dockerfile

# Paste below content in Dockerfile
From tomcat
COPY ./webapp.war /usr/local/tomcat/webapps
  • Login to your dockerhub account
# Dockerhub login
docker login -u username -p password
  • In playbooks folder create these two playbooks service.yml and deployment.yml
# service.yml
---
- name: create service for deployment
  hosts: kubernetes
  # become: true
  user: ansadmin

  tasks:
  - name: create a service
    command: kubectl apply -f /opt/kubernetes/demoservice.yml

# deployment.yml
---
- name: Create pods using deployment
  hosts: kubernetes
  # become: true
  user: ansadmin

  tasks:
  - name: create a deployment
    command: kubectl apply -f /opt/kubernetes/demodeploy.yml

  - name: update deployment with new pods if image updated in docker hub
    command: kubectl rollout restart deployment.v1.apps/devopsdeployment
  • Add Kubernetes VM credentials and IP address in ansible host file present in /etc/ansible/hosts under hosts kubernetes

Kubernetes Server

  • As I don’t want to include my host windows system in the setup I am installing minikube as a container in a VM.

  • In Kubernetes VM create a directory kubernetes in /opt and download kubectl

# Download kubectl
curl -LO "<https://dl.k8s.io/release/$>(curl -L -s <https://dl.k8s.io/release/stable.txt>)/bin/linux/amd64/kubectl"

# Install kubectl
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
  • create demodeploy.yml and demoservice.yml files in /opt/kubernetes folder
# demodeploy.yml
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: devopsdeployment
spec:
  selector:
    matchLabels:
      app: devopsproject
  replicas: 2 # tells deployment to run 2 pods matching the template
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1

  template:
    metadata:
      labels:
        app: devopsproject
    spec:
      containers:
      - name: devopsproject
        image: rishibeesu/kubernetes_demo
        imagePullPolicy: Always
        ports:
        - containerPort: 8080

#demoservice.yml
apiVersion: v1
kind: Service
metadata:
  name: devopsservice
  labels:
    app: devopsproject
spec:
  selector:
    app: devopsproject
  type: LoadBalancer
  ports:
    - port: 8080
      targetPort: 8080
      nodePort: 31200
  • Create user ansadmin and give ownership of /opt/kubernetes folder
# Giving ownership of folder
sudo chown -R ansadmin:ansadmin /opt/kubernetes
  • Through ansadmin user start minikube
# Download minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-latest.x86_64.rpm

# Install minikube
sudo rpm -Uvh minikube-latest.x86_64.rpm

# Starting minikube
minikube start --driver=docker

Continuous Integration

  • Login to Jenkins

  • Install GitHub, Maven Invoker, Maven Integration and publish over SSH plugins

  • Add Ansible server details in Manage Jenkins >> Configure System

  • Creating a new job

    • Select maven project as we are deploying a java code

    • Source Code Management

      • Branches to build: */master

      • Repository: GitHub repo URL

    • Build

      • Root POM: pom.xml

      • Goals and options: clean install package

    • Post Build

      • Send files or execute commands over SSH

        • Name: ansible

        • Source files: webapp/target/*.war

        • Remove prefix: webapp/target

        • Remote directory: //opt//docker

      • Send files or execute commands over SSH

        • Name: ansible

        • Exec Command:

          • cd /opt/docker

          • docker rmi kubernetes_demo rishibeesu/kubernetes_demo

          • docker build -t kubernetes_demo .

          • docker tag kubernetes_demo rishibeesu/kubernetes_demo

          • docker push rishibeesu/kubernetes_demo

      • Build other projects

        • Give name of the continuous delivery job we are gonna configure

        • Select trigger only if build is stable

Continuous Delivery

  • Create a new job

    • Post Build

      • Send files or execute commands over SSH

        • Name: ansible

        • Exec Command:

          • cd /opt/playbooks

          • ansible-playbook -v /opt/playbooks/deployment.yml

          • ansible-playbook -v /opt/playbooks/service.yml

Demo

  • Now run the job either manually or you can configure poll scm and do it automatically

  • As the minikube server is present as container inside a VM to access our pods use kubectl port forward

# kubectl port forward
kubectl port-forward --address 0.0.0.0 service/devopsservice 42042:8080
  • You can access the website using the below URL
# URL
https://<Kubernetes IP>:42042
  • If code is changed in GitHub either through poll scm or manual build we can see changes reflected in the website