10 min read

In this article, Jonathan Baier, the author of Getting Started with Kubernetes – Second Edition, will show the reader how to integrate their build pipeline and deployments with a Kubernetes cluster. It will cover the concept of using Gulp.js and Jenkins in conjunction with your Kubernetes cluster.

This article will discuss the following topics:

  • Integrating with continuous deployment pipeline
  • Using Gulp.js with Kubernetes
  • Integrating Jenkins with Kubernetes

Integrating with continuous delivery pipeline

Continuous integration and delivery are key components to modern development shops. Speed to market or mean-time-to-revenue are crucial for any company that is creating their own software. We’ll see how Kubernetes can help you.

CI/CD (short for Continuous Integration / Continuous Delivery) often requires ephemeral build and test servers to be available whenever changes are pushed to the code repository. Docker and Kubernetes are well suited for this task, as it’s easy to create containers in a few seconds and just as easy to remove them after builds are run. In addition, if you already have a large portion of infrastructure available on your cluster, it can make sense to utilize the idle capacity for builds and testing.

In this article, we will explore two popular tools used in building and deploying software:

  • Gulp.js: This is a simple task runner used to automate the build process using JavaScript and Node.js
  • Jenkins: This is a fully-fledged continuous integration server

Gulp.js

Gulp.js gives us the framework to do Build as code. Similar to Infrastructure as code, this allows us to programmatically define our build process. We will walk through a short example to demonstrate how you can create a complete workflow from a Docker image build to the final Kubernetes service.

Prerequisites

For this section of the article, you will need a NodeJS environment installed and ready including the node package manager (npm). If you do not already have these packages installed, you can find instructions for installing them at https://docs.npmjs.com/getting-started/installing-node.

You can check whether NodeJS is installed correctly with a node -v command.

You’ll also need Docker CE and a DockerHub account to push a new image. You can find instructions to install Docker CE at https://docs.docker.com/installation/.

You can easily create a DockerHub account at https://hub.docker.com/.

After you have your credentials, you can log in with the CLI using $ docker login command.

Gulp build example

Let’s start by creating a project directory named node-gulp:

$ mkdir node-gulp
$ cd node-gulp

Next, we will install the gulp package and check whether it’s ready by running the npm command with the version flag, as follows:

$ npm install -g gulp

You may need to open a new terminal window to make sure that gulp is on your path. Also, make sure to navigate back to your node-gulp directory:

$ gulp -v

Next, we will install gulp locally in our project folder as well as the gulp-git and gulp-shell plugins, as follows:

$ npm install --save-dev gulp
$ npm install gulp-git -save
$ npm install --save-dev gulp-shell

Finally, we need to create a Kubernetes controller and service definition file, as well as a gulpfile.js file, to run all our tasks. Again, these files are available in the book file bundle, if you wish to copy them instead. Refer to the following code:

apiVersion: v1 
kind: ReplicationController 
metadata: 
  name: node-gulp 
  labels: 
    name: node-gulp 
spec: 
  replicas: 1 
  selector: 
    name: node-gulp 
  template: 
    metadata: 
      labels: 
        name: node-gulp 
    spec: 
      containers: 
      - name: node-gulp 
        image: <your username>/node-gulp:latest 
        imagePullPolicy: Always 
        ports: 
        - containerPort: 80

Listing 7-1: node-gulp-controller.yaml

As you can see, we have a basic controller. You will need to replace <your username>/node-gulp:latest with your Docker Hub username:

apiVersion: v1 
kind: Service 
metadata: 
  name: node-gulp 
  labels: 
    name: node-gulp 
spec: 
  type: LoadBalancer 
  ports: 
  - name: http 
    protocol: TCP 
    port: 80 
  selector: 
    name: node-gulp

Listing 7-2: node-gulp-service.yaml

Next, we have a simple service that selects the pods from our controller and creates an external load balancer for access, as earlier:

var gulp = require('gulp'); 
var git = require('gulp-git'); 
var shell = require('gulp-shell'); 

// Clone a remote repo 
gulp.task('clone', function(){ 
  return git.clone('https://github.com/jonbaierCTP/getting-started-with-kubernetes-se.git', function (err) { 
    if (err) throw err; 
  }); 

}); 

// Update codebase 
gulp.task('pull', function(){ 
  return git.pull('origin', 'master', {cwd: './getting-started-with-kubernetes-se'}, function (err) { 
    if (err) throw err; 
  }); 
}); 

//Build Docker Image 
gulp.task('docker-build', shell.task([ 
  'docker build -t <your username>/node-gulp ./getting-started-with-kubernetes-se/docker-image-source/container-info/', 
  'docker push <your username>/node-gulp' 
])); 

//Run New Pod 
gulp.task('create-kube-pod', shell.task([ 
  'kubectl create -f node-gulp-controller.yaml', 
  'kubectl create -f node-gulp-service.yaml' 
])); 

//Update Pod 
gulp.task('update-kube-pod', shell.task([ 
  'kubectl delete -f node-gulp-controller.yaml', 
  'kubectl create -f node-gulp-controller.yaml' 
]));

Listing 7-3: gulpfile.js

Finally, we have the gulpfile.js file. This is where all our build tasks are defined. Again, fill in your Docker Hub username in both the <your username>/node-gulp sections.

Looking through the file, first, the clone task downloads our image source code from GitHub. The pull tasks execute a git pull on the cloned repository. Next, the docker-build command builds an image from the container-info subfolder and pushes it to DockerHub. Finally, we have the create-kube-pod and update-kube-pod commands. As you can guess, the create-kube-pod command creates our controller and service for the first time, whereas the update-kube-pod command simply replaces the controller.

Let’s go ahead and run these commands and see our end-to-end workflow:

$ gulp clone
$ gulp docker-build

The first time through, you can run the create-kube-pod command, as follows:

$ gulp create-kube-pod

This is all there is to it. If we run a quick kubectl describe command for the node-gulp service, we can get the external IP for our new service. Browse to that IP and you’ll see the familiar container-info application running. Note that the host starts with node-gulp, just as we named it in the previously mentioned pod definition:

Service launched by Gulp build

On subsequent updates, run the pull and update-kube-pod commands, as shown here:

$ gulp pull
$ gulp docker-build
$ gulp update-kube-pod

This is a very simple example, but you can begin to see how easy it is to coordinate your build and deployment end to end with a few simple lines of code. Next, we will look at how to use Kubernetes to actually run builds using Jenkins.

Kubernetes plugin for Jenkins

One way we can use Kubernetes for our CI/CD pipeline is to run our Jenkins build slaves in a containerized environment. Luckily, there is already a plugin, written by Carlos Sanchez, which allows you to run Jenkins slaves in Kubernetes’ pods.

Prerequisites

You’ll need a Jenkins server handy for this next example. If you don’t have one you can use, there is a Docker image available at https://hub.docker.com/_/jenkins/.

Running it from the Docker CLI is as simple as this:

docker run --name myjenkins -p 8080:8080 -v /var/jenkins_home jenkins

Installing plugins

Log in to your Jenkins server, and from your home dashboard, click on Manage Jenkins. Then, select Manage Plugins from the list.

A note for those installing a new Jenkins server: When you first log in to the Jenkins server, it asks you to install plugins. Choose the default ones or no plugins will be installed:
Jenkins main dashboard

The credentials plugin is required, but should be installed by default. We can check the Installed tab if in doubt, as shown in the following screenshot:

Jenkins installed plugins

Next, we can click on the Available tab. The Kubernetes plugin should be located under Cluster Management and Distributed Build or Misc (cloud). There are many plugins, so you can alternatively search for Kubernetes on the page. Check the box for Kubernetes Plugin and click on Install without restart.

This will install theKubernetes Plugin and the Durable Task Plugin:

Plugin installation
If you wish to install a nonstandard version or just like to tinker, you can optionally download the plugins. The latest Kubernetes and Durable Task plugins can be found here:
        Kubernetes plugin: https://wiki.jenkins-ci.org/display/JENKINS/Kubernetes+Plugin
        Durable Task plugin: https://wiki.jenkins-ci.org/display/JENKINS/Durable+Task+Plugin
Next, we can click on the Advanced tab and scroll down to Upload Plugin. Navigate to the durable-task.hpi file and click on Upload. You should see a screen that shows an installing progress bar. After a minute or two, it will update to Success.
Finally, install the main Kubernetes plugin. On the left-hand side, click on Manage Plugins and then the Advanced tab once again. This time, upload the kubernetes.hpi file and click on Upload. After a few minutes, the installation should be complete.

Configuring the Kubernetes plugin

Click on Back to Dashboard or the Jenkins link in the top-left corner. From the main dashboard page, click on the Credentials link. Choose a domain from the list; in my case, I just used the default Global credentials domain. Click on Add Credentials:

Add credentials screen

Leave Kind as Username with password and Scope as Global. Add your Kubernetes admin credentials. Remember that you can find these by running the config command:

$ kubectl config view

You can leave ID blank, give it a sensible description, and click on the OK button.

Now that we have our credentials saved, we can add our Kubernetes server. Click on the Jenkins link in the top-left corner and then Manage Jenkins. From there, select Configure System and scroll all the way down to the Cloud section. Select Kubernetes from the Add a new cloud dropdown and a Kubernetes section will appear, as follows:

New Kubernetes cloud settings

You’ll need to specify the URL for your master in the form of https://<Master IP>/.

Next, choose the credentials we added from the drop-down list. Since Kubernetes use a self-signed certificate by default, you’ll also need to check the Disable https certificate check checkbox.

Click on Test Connection and if all goes well, you should see Connection successful appearing next to the button.

If you are using an older version of the plugin, you may not see the Disable https certificate check checkbox. If this is the case, you will need to install the self-signed certificate directly on the Jenkins Master.

Finally, we will add a pod template by choosing Kubernetes Pod Template from the Add Pod Template dropdown next to Images.

This will create another new section. Use jenkins-slave for the Name and Labels section. Click on Add next to Containers and again use jenkins-slave for the Name. Use csanchez/jenkins-slave for the Docker Image and leave /home/jenkins for the Working Directory.

Labels can be used later on in the build settings to force the build to use the Kubernetes cluster:
Kubernetes cluster addition

Here is the Pod Template that expands below the cluster addition:

Kubernetes pod template

Click on Save and you are all set. Now, new builds created in Jenkins can use the slaves in the Kubernetes pod we just created.

Here is another note about firewalls. The Jenkins Master will need to be reachable by all the machines in your Kubernetes cluster, as the pod could land anywhere. You can find out your port settings in Jenkins under Manage Jenkins and Configure Global Security.

Bonus fun

Fabric8 bills itself as an integration platform. It includes a variety of logging, monitoring, and continuous delivery tools. It also has a nice console, an API registry, and a 3D game that lets you shoot at your pods. It’s a very cool project, and it actually runs on Kubernetes. Refer to http://fabric8.io/.

It’s an easy single command to set up on your Kubernetes cluster, so refer to http://fabric8.io/guide/getStarted/gke.html.

Summary

We looked at two continuous integration tools that can be used with Kubernetes. We did a brief walk-through of deploying the Gulp.js task on our cluster. We also looked at a new plugin used to integrate Jenkins build slaves into your Kubernetes cluster. You should now have a better sense of how Kubernetes can integrate with your own CI/CD pipeline.

LEAVE A REPLY

Please enter your comment!
Please enter your name here