Book Image

The DevOps 2.4 Toolkit

By : Viktor Farcic
Book Image

The DevOps 2.4 Toolkit

By: Viktor Farcic

Overview of this book

Building on The DevOps 2.3 Toolkit: Kubernetes, Viktor Farcic brings his latest exploration of the Docker technology as he records his journey to continuously deploying applications with Jenkins into a Kubernetes cluster. The DevOps 2.4 Toolkit: Continuously Deploying Applications with Jenkins to a Kubernetes Cluster is the latest book in Viktor Farcic’s series that helps you build a full DevOps Toolkit. This book guides readers through the process of building, testing, and deploying applications through fully automated pipelines. Within this book, Viktor will cover a wide-range of emerging topics, including an exploration of continuous delivery and deployment in Kubernetes using Jenkins. It also shows readers how to perform continuous integration inside these clusters, and discusses the distribution of Kubernetes applications, as well as installing and setting up Jenkins. Work with Viktor and dive into the creation of self-adaptive and self-healing systems within Docker.
Table of Contents (12 chapters)
Now It Is Your Turn

Using StatefulSets to run Stateful applications

Let's see a StatefulSet in action and see whether it beings any benefits. We'll use Jenkins as the first application we'll deploy. It is a simple application to start with since it does not require a complicated setup and it cannot be scaled. On the other hand, Jenkins is a stateful application. It stores all its state into a single directory. There are no "special" requirements besides the need for a PersistentVolume.

A sample Jenkins definition that uses StatefulSets can be found in sts/jenkins.yml.

 1 cat sts/jenkins.yml

The definition is relatively straightforward. It defines a Namespace for easier organization, a Service for routing traffic, and an Ingress that makes it accessible from outside the cluster. The interesting part is the StatefulSet definition.

The only significant difference, when compared to Deployments, is that the StatefulSet can use volumeClaimTemplates. While Deployments require that we specify PersistentVolumeClaim separately, now we can define a claim template as part of the StatefulSet definition. Even though that might be a more convenient way to define claims, surely there are other reasons for this difference. Or maybe there isn't. Let's check it out by creating the resources defined in sts/jenkins.yml.

A note to minishift users
OpenShift does not allow setting fsGroup in the security context, it uses Routes instead of Ingress, and Services accessible through Routes need to be the LoadBalancer type. Due to those changes, I had to prepare a different YAML specification for minishift. Please execute oc apply -f sts/jenkins-oc.yml --record instead of the command that follows.
 1  kubectl apply \
 2      -f sts/jenkins.yml \
 3      --record

We can see from the output that a Namespace, an Ingress, a Service, and a StatefulSet were created. In case you're using minishift and deployed the YAML defined in sts/jenkins-oc.yml, you got a Route instead Ingress.

A note to GKE users
GKE uses external load balancer as Ingress. To work properly, the type of the service related to Ingress needs to be NodePort. We'll have to patch the service to change its type. Please execute the command that follows.
kubectl -n jenkins patch svc jenkins -p '{"spec":{"type": "NodePort"}}'

Let's confirm that the StatefulSet was rolled out correctly.

 1  kubectl -n jenkins \
 2      rollout status sts jenkins

Now that jenkins StatefulSet is up and running, we should check whether it created a PersistentVolumeClaim.

 1  kubectl -n jenkins get pvc

The output is as follows.

jenkins-home-jenkins-0 Bound  pvc-... 2Gi      RWO          gp2        2m

It comes as no surprise that a claim was created. After all, we did specify volumeClaimTemplates as part of the StatefulSet definition. However, if we compare it with claims we make as separate resources (for example, with Deployments), the format of the claim we just created is a bit different. It is a combination of the claim name (jenkins-home), the Namespace (jenkins), and the indexed suffix (0). The index is an indication that StatefulSets might create more than one claim. Still, we can see only one, so we'll need to stash that thought for a while. Similarly, we might want to confirm that the claim created a PersistentVolume.

 1  kubectl -n jenkins get pv
A note to minishift users
You'll see a hundred volumes instead of one. Minishift does not (yet) uses default storage classes. Instead, we have a hundred volumes without a storage class so that enough volumes are available for testing purposes. Only one of them will be with the status Bound.

Finally, as the last verification, we'll open Jenkins in a browser and confirm that it looks like it's working correctly. But, before we do that, we should retrieve the hostname or the IP assigned to us by the Ingress controller.

A note to GKE users
Please change hostname to ip in the command that follows. The jsonpath should be {.status.loadBalancer.ingress[0].ip}. Please note that GKE Ingress spins up an external load balancer and it might take a while until the IP is generated. Therefore, you might need to repeat the command that follows until you get the IP.
A note to minikube users
Please change the following command to CLUSTER_DNS=$(minikube ip).
A note to minishift users
Please change the following command to CLUSTER_DNS=jenkins-jenkins.$(minishift ip)

 1  CLUSTER_DNS=$(kubectl -n jenkins \
 2      get ing jenkins \
 3      -o jsonpath="{.status.loadBalancer.ingress[0].hostname}")
4 5 echo $CLUSTER_DNS

We retrieved the hostname (or IP) from the Ingress resource, and now we are ready to open Jenkins in a browser.

 1  open "http://$CLUSTER_DNS/jenkins"
A note to Windows users
Git Bash might not be able to use the open command. If that's the case, replace the open command with echo. As a result, you'll get the full address that should be opened directly in your browser of choice.
In some cases (for example, GKE), it might take a few minutes until the external load balancer is created. If you see 40x or 50x error message, please wait for a while and try to open Jenkins in the browser again.

You might see browser's message that the connection is not private. That's normal since we did not specify an SSL certificate. If that's the case, please choose to proceed. In Chrome, you should click the ADVANCED link, followed by Proceed to... for the rest of the browsers... Well, I'm sure that you already know how to ignore SSL warnings in your favorite browser.

You should see a wizard. We won't use it to finalize Jenkins setup. All we wanted, for now, is to explore StatefulSets using Jenkins as an example. There are a few things we're missing for Jenkins to be fully operational and we'll explore them in later chapters. For now, we'll remove the whole jenkins Namespace.

 1  kubectl delete ns jenkins

From what we experienced so far, StatefulSets are a lot like Deployments. The only difference was in the volumeClaimTemplates section that allowed us to specify PersistentVolumeClaim as part of the StatefulSet definition, instead of a separate resource. Such a minor change does not seem to be a reason to move away from Deployments. If we limit our conclusions to what we observed so far, there are no good arguments to use StatefulSets instead of Deployments. The syntax is almost the same, and the result as well. Why would we learn to use a new controller if it provides no benefits?

Maybe we could not notice a difference between a StatefulSet and a Deployment because our example was too simple. Let's try a slightly more complicated scenario.