top of page

DEPLOY WEBSERVER ON KUBERNETES USING JENKINSFILE APPROACH




Jenkinsfile

A Jenkinsfile is a text file that contains the definition of a Jenkins Pipeline and is checked into source control.


This Story explains deployment of a website using apache webserver on Kubernetes. There are a lot of other ways to do the same but, here I have used Jenkinsfile approach.


Demo

Pre-requisites:

  1. Jenkins

  2. Minikube

  3. Job-DSL plugin for Jenkins

  4. Build-Result Trigger plugin for Jenkins

  5. Github plugin for Jenkins

This story does not cover the installation of these softwares and plugins.


Process:

1. First we need to create the DSL script for the job. The DSL script will create 4 jobs. DSL scripts use groovy syntax and the script has been saved to a .groovy file and uploaded to Github. Create a seed job to pull the script from github repo and use the job DSL plugin to deploy the setup. On deploying the seed job for 1st time you may face an error that say Script not approved. Go to Manage Jenkins>In-Process Script Approval and approve the script. You have to do this each time you update the script. DSL script:-

job("Pull code from Github Repo"){
              description("The job will pull the code from github repo and save it to a folder")              scm{
                    github('chirag0202/project','master')
                  }              triggers{
                        githubPush()
                        }
                steps{
                      shell("sudo cp -rvf index.html /task6")
                      }
         
}
job("Deploy code on web server"){
              description("The job will deploy the code on a webserver")                  scm{
                    github('chirag0202/webserver-kube','master')
                  }                  triggers{
                        upstream("Pull code from Github Repo")
                        }                  steps{
                      shell(readFileFromWorkspace("job2.sh"))
                      }                  steps{
                      shell(readFileFromWorkspace("job2-2.sh"))
                      }
          
}
job("Test Webserver"){
              description("The job will test the webserver")              triggers{
                        upstream("Deploy code on web server")
                        }              steps{
                      shell(readFileFromWorkspace("job3.sh"))
                      }
          
}
job("Send Email"){
              description("Send email to developer if job 3 fails")              triggers{
                buildResult('* * * * *') {
                   combinedJobs()
                   triggerInfo('Test Webserver', BuildResult.UNSTABLE, BuildResult.FAILURE)
        }
      }
                steps{
                      shell("python3 /mail/mail.py")
                      }}
buildPipelineView('Deploy Webserver Using Groovy') {
    title('Deploy Webserver Using Groovy')
    displayedBuilds(4)
    selectedJob('Pull code from Github Repo')
    alwaysAllowManualTrigger()
    showPipelineParameters()
}


2. Job 1 will pull the code for Website from SCM(Github) when the developer has pushed the code to the repository and copy it to a separate directory.



3. Job 2 will deploy the webserver on Kubernetes. The build steps for Jobs 2 and 3 are saved in 3 shell scripts.


Kubernetes Manifest for Webserver

apiVersion: v1
kind: Service
metadata:
  name: webtest
  labels:
    app: webtest
spec:
  ports:
  - port: 80
    nodePort: 30003
  selector:
    app: webtest
    tier: production
  type: NodePort
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: webtest-pv-claim
  labels: 
    app: webtest
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webtest
  labels:
    app: webtest
spec:
  selector:
   matchLabels:
     app: webtest
     tier: production
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: webtest
        tier: production
    spec:
       containers:
       - image: vimal13/apache-webserver-php
         name: webtest
         ports:
         - containerPort: 80
           name: webtest
         volumeMounts:
         - name: webtest-pv
           mountPath: /var/www/html
       volumes:
       - name: webtest-pv
         persistentVolumeClaim:
           claimName: webtest-pv-claim

Kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - http.yaml

Groovy Script 1 for Job 2

if sudo /usr/local/bin/kubectl get all --kubeconfig /root/.kube/config |grep webtest
then
sudo /usr/local/bin/kubectl delete all --all --kubeconfig /root/.kube/config 
sudo /usr/local/bin/kubectl delete pvc --all --kubeconfig /root/.kube/config 
sudo /usr/local/bin/kubectl create -k . --kubeconfig /root/.kube/config 
else
sudo /usr/local/bin/kubectl create -k . --kubeconfig /root/.kube/config 
fi

Groovy Script 2 for Job 2

sleep 15
sudo /usr/local/bin/kubectl cp /task6/* $(sudo /usr/local/bin/kubectl get pod --kubeconfig /root/.kube/config|grep webtest| awk '{print $1}'):/var/www/html --kubeconfig /root/.kube/config 
sudo /usr/local/bin/kubectl get all --kubeconfig /root/.kube/config

The sleep 15 command acts as a buffer which allows the webserver to successfully deploy.



4. Job 3 tests if there is any error in the deployment. The website will be available at http://<minikube ip>:<port no.>


Groovy Script for Job 3

status=$(sudo curl -s -o /dev/null -w "%{http_code}" http://192.168.99.106:30003/index.html)
if status==200
then
exit 0
else 
exit 1
fi


5. If webserver deployment fails or Job 3 build is unstable, Job 4 will send an email to the Developer. I have used a simple python script to send the email. .


Python Script for Job 4

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
mail_content = 'Webserver deployment failed.'
sender_address = <mail id of sender>
sender_pass = <password>
receiver_address = <mail id of receiver>
#Setup the MIME
message = MIMEMultipart()
message['From'] = sender_address
message['To'] = receiver_address
message['Subject'] = 'A test mail sent by Python. It has an attachment.'   #The subject line
#The body and the attachments for the mail
message.attach(MIMEText(mail_content, 'plain'))
#Create SMTP session for sending the mail
session = smtplib.SMTP('smtp.gmail.com', 587) #use gmail with port
session.starttls() #enable security
session.login(sender_address, sender_pass) #login with mail_id and password
text = message.as_string()
session.sendmail(sender_address, receiver_address, text)
session.quit()
print('Mail Sent')


The DSL script has set up BuildResultTrigger Plugin which will trigger job 4 if webserver build fails.


6. The DSL script also creates a Build Pipeline View that shows the build status of all the jobs.



7. If the build is successful the website is deployed.



8. If the website build fails or the build is unstable the developer will receive this email.




Source: medium


The Tech Platform

0 comments
bottom of page