DevOps has become a part of the software lifecycle management with CI/CD pipeline to deliver a change to production in an automated way.
In CI/CD pipeline the popular open source tools are Github for source code repository, Jenkins for Continuous Integration, build, test & deployment orchestration, SonarQube for static code analysis and Nexus for artifacts repository. There are many open source tools available for testing too. This article is not much about DevOps or CI/CD pipline rather it will describe how to create the CI/CD pipeline on Kubernetes cluster environment using kubectl.
These are methods of operating system virtualization that allows us to run an application and its dependencies in resource-isolated processes. Containers allows a developer to package an application with parts it needs, such as libraries and other dependencies, and ship it all out as one package. There are many container options that are available and Docker is one such open source container which is very widely used.
It is a portable open-source platform for managing containerised workloads and services that facilitates both declarative configuration and automation. Kubernetes has become the default tool to manage the containers in most of the public, private & hybrid cloud and also on the bare metal systems.
This write-up describes on how to create Kubernetes cluster with Jenkins, Sonar, Nexus as pods on AWS cloud. It doesnt includes details about functionality of Jenkins, SonarQube, Nexus.
I have already write an article on setting up a Kubernetes cluster on AWS Cloud with one master and two worker nodes. For futher details refer the link - https://dev.to/sr_balaji/kubernetes-cluster-setup-on-aws-13m6
The list of Kubernetes components that is used in this cluster are detalied below. I have provided a very high-level details on the Kubernetes components. For further details please refer https://kubernetes.io.
Cluster: It is set of a physical or virtual machine and, in Kubernetes, all machine are managed as a cluster.
Node: It is a worker machine in Kubernetes. It may be a Virtual or physical machine. (In this article I have used EC2 instance to provision the Kubernetes Cluster)
Pod: It is a group of one or more containers (such as Docker containers), with shared storage/network, and a set of specifications to run the containers. A pod’s contents are always co-located, co-scheduled and runs in a shared context.
Deployment: It provides declarative updates for Pods and ReplicaSets.
Persistent Volume: It is a piece of storage in the cluster that has been provisioned by an administrator. It is a node in cluster resource.
Persistent Volume Claim: It is a request for storage by an user.
Service: It is an abstraction that defines a logical set of Pod(s)
Storageclass: It provides a way for administrators to describe the “classes” of storage they offer.
In this Kubernetes cluster, I have created a single instance of the Jenkins, SonarQube & Nexus and configured in such a way that one instance of these servers is always available. The data of these servers are persisted, and even in the event of these servers getting crashed, it rebuilds automatically with the data that are preserved.
I have created separate storage class for Jenkins, SonarQube & Nexus with data persistence. Each of the servers are available as a separate pod with their ports exposed as a service. I have used deployment to create pods for individual tools.
Jenkins is an open source Continuous Integration (CI)/Continuous Delivery (CD) orchestration tool. It offers a simple way to set up a CI/CD environment for any languages & source code repositories. I have created the following list of Kubernetes components to host Jenkins server on the cluster.
I have created the storage class on the cluster for Jenkins data.
kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: jenkins-storage labels: app: jenkins-storage provisioner: kubernetes.io/aws-ebs parameters: type: gp2 zone: eu-west-2a allowVolumeExpansion: true
I have created a Persistent Volume claim and allocated 2GB as the storage space to presist Jenkins data.
kind: PersistentVolumeClaim apiVersion: v1 metadata: name: jenkins-data annotations: volume.beta.kubernetes.io/storage-class: "jenkins-storage" spec: accessModes: - ReadWriteOnce resources: requests: storage: 2Gi
I have created a deployment script which pulls the Jenkins official image from internet and I have configured Jenkins with the default port 8080. Its data are persisted on the persistent volume which is created in the previous step. This deployment is created with single Replica which means Kubernetes will make sure that one instance of Jenkins is always up & running. In this configuration the port is not exposed to the cluster which will be covered in the next section.
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: jenkins spec: replicas: 1 template: metadata: labels: app: jenkins spec: securityContext: runAsUser: 1000 fsGroup: 1000 containers: - name: jenkins image: jenkins:2.60.3 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 volumeMounts: - name: jenkins-home mountPath: /var/jenkins_home volumes: - name: jenkins-home persistentVolumeClaim: claimName: jenkins-data
I have created a Service to expose Jenkins on port 9500 rather than on its default port.
apiVersion: v1 kind: Service metadata: name: jenkins labels: app: jenkins spec: type: NodePort ports: - port: 9500 targetPort: 8080 name: jenkinsport selector: app: jenkins type: LoadBalancer
I have created storage class, persistent volume, deployment, and service for Jenkins so far. All the components for Jenkins are created and it is up running.
$kubectl get deployment $kubectl get pod $kubectl get svc
In this article, I have covered on how to setup Jenkins with single Replicaset on a Kubernetes cluster. I will cover the setup of SonarQube and Nexus in the next articles.
yaml files are space sensitive and the scripts that are available in this article might have tab spaces instead of whitespace. These scripts will fail, if you copy and paste without changing the tab to whitespace.