Rolling-update in Kubernetes using Dynamic Jenkins Node
Rolling-update is a strategy used in Kubernetes to deploy the latest updated containers as new pods in deployment without hindering any clients connected. It involves gradual launching of new pods and removal of old pods and transferring the new traffic to the new pods. If some clients are already connected then it waits for them to disconnect and then transfers them to new pods and then updates those pods. There is no disruption of services even for a short time.
Dynamic Jenkins node gives us the liberty to run the jobs in the desired environment on top of docker containers. It ensures that there is no wastage of resource as in case of static nodes the resources are used even if there is no job running on them.
In this task, we are going to create a Docker image configured with kubectl to run Kubernetes commands and use it to run the Jenkins job as a Dynamic node. Using Jenkins job we will create a new image using the updated code and Dockerfile as pushed by the developer on GitHub. Then, we either launch newly updated Docker images having latest updates by the developer or rollout the updates on Kubernetes.
TASK - 4 Description :
Create A dynamic Jenkins cluster and perform task-3 using the dynamic Jenkins cluster.
Steps to proceed as:
1. Create container image that’s has Linux and other basic configuration required to run Slave for Jenkins. ( example here we require kubectl to be configured )
2. When we launch the job it should automatically starts job on slave based on the label provided for dynamic approach.
3. Create a job chain of job1 & job2 using build pipeline plugin in Jenkins
4. Job1 : Pull the Github repo automatically when some developers push repo to Github and perform the following operations as:
i. Create the new image dynamically for the application and copy the application code into that corresponding docker image
ii. Push that image to the docker hub (Public repository) ( Github code contain the application code and Dockerfile to create a new image )
5. Job2 ( Should be run on the dynamic slave of Jenkins configured with Kubernetes kubectl command): Launch the application on the top of Kubernetes cluster performing following operations:
i. If launching first time then create a deployment of the pod using the image created in the previous job. Else if deployment already exists then do rollout of the existing pod making zero downtime for the user.
ii. If Application created first time, then Expose the application. Else don’t expose it.
CREATING DOCKER IMAGE FOR DYNAMIC NODE :
Firstly for creating config file for the kubenetes client, we copy 3 files( ca.crt, client.crt and client.key) from the .kube file of the base OS where our Kubernetes cluster are running to the root folder of the docker image. Then we write the config file using links to the same. The config file for the cluster running in the VM :
apiVersion: v1 kind: Config clusters: - cluster: server: https://192.168.99.103:8443 certificate-authority: /root/ca.crt name: vkcluster contexts: - context: cluster: vkcluster user: vikash name: vkcontext current-context: vkcontext users: - name: vikash user: client-certificate: /root/client.crt client-key: /root/client.key
Now to copy these files into the image so we keep them in the same directory as the Dockerfile used to create the image. The Dockerfile uses CentOS:7 image and installs java, kubectl program and openssh-server program to enable ssh.
FROM centos:7 RUN yum install java-1.8.0-openjdk-devel -y RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl RUN chmod +x ./kubectl RUN mv kubectl /usr/bin/ RUN mkdir /root/.kube/ COPY config /root/.kube/ COPY ca.crt /root/ COPY client.key /root/ COPY client.crt /root/ RUN mkdir /jenkins-launch RUN yum install openssh-server -y RUN yum install net-tools -y RUN echo 'root:redhat' | chpasswd RUN /usr/bin/ssh-keygen -A EXPOSE 22 CMD /usr/sbin/sshd -D
To run the file we use the command :
docker build -t vikashkr437/kubectl-ssh-node:v1
Then we upload this image to docker hub and this requires login to the docker hub account too.
docker push vikashkr437/kubectl-ssh-node:v1
SETTING UP JENKINS DYNAMIC NODE :
In order to set up the Base OS having Docker services running and we assume that the Docker service is configured to accept local requests from localhost IP at port 4243. Then, two plugins Docker and Yet Another Docker is installed on Jenkins
After this, the Dynamic worker node needs to be configured. For this we go to Manage Jenkins > Manage Nodes and Clouds
From there configure cloud is selected and then a new cloud with name 'docker' is added.
Docker Cloud details is clicked and the details are added. The host IP of the OS where docker services is running is put on port 4243. To enable the cloud enabled and expose DOCKER_HOST is ticked.
Next the Docker Agent templates is added. Here we put the name of the image we earlier created and add label to it. Also the working directory and Name is specified. In connect method 'Connect with SSH' is selected and ssh credentials for logging into the container is also added and selected.
CREATING JOBS :
T4JOB1 : This Job runs on the dynamic docker node created by us restricting where the project can run with the label of the docker template set while creating the node. It pulls the GitHub repository as soon as the developer pushes the code along with the Dockerfile. It then builds the Docker image from the Dockerfile and copies the code into it. After this it pushes the image to the public repository of Docker Hub. For buiding the image and pushing it we use the build step of Build/Publish Docker Image and add our Docker hub credentials to allow it to push the image to the public repository.
T4JOB2 : Similar to the last job this job also runs on top of dynamic node. It then using the Docker image we uploaded in the last job it creates a deployment and exposes it if the deployment is not already created. If the deployment is already created then it will roll out the update using the deployment strategy RollingUpdate with zero downtime.
Build Pipeline : A build pipeline is created for the two jobs so that they can function one after the other and is easy to monitor.
Running Job for First time html code deployed contains "Hello World" and the Dockerfile uploaded was :
FROM centos:7 RUN yum install /sbin/service -y RUN yum install httpd -y COPY *.html /var/www/html CMD /usr/sbin/httpd -DFOREGROUND && /bin/bash
EXPOSE 80
After T4JOB1 runs the status of the job is :
Then T4JOB2 runs and the deployment is created.
The Kubernetes Deployment created can be seen using "kubectl get all" command.
The website can be seen at port 30069.
Then we change the code to html "Hello New World" and push on GitHub to trigger a new build.
After the pipeline is completed we can see the roll out of update in the Kubernetes deployment and the new container is replaced.
The new website comes up at the same port.
GitHub link for deployment Dockerfile :
GitHub link for Jenkins Node Dockerfile and config file for kubectl :