Kubernetes – Helm and Minikube

Let’s try setting up some CI/CD with other tools, so we can experiment with the newest offerings in the Kubernetes ecosystem. First, let’s explore how easy it is to install Jenkins with Helm.

First, open the Minikube dashboard so you can see what happens when we install various things. Do this with the following command:

$ minikube dashboard

Let’s create a namespace for the Jenkins environment, as follows:

$ kubectl get namespaces
NAME          STATUS AGE
default       Active 3d
kube-public   Active 3d
kube-system   Active 3d

Now, let’s create a template:

$ mkdir -p ~/gsw-k8s-helm && cd ~/gsw-k8s-helm
$ cat <<K8s >> namespace-jenkins.yaml
apiVersion: v1
kind: Namespace
metadata:
 name: gsw-k8s-jenkins
K8s

Now, you can create the namespace as follows:

kubectl create -f namespace-jenkins.yaml
namespace "gsw-k8s-jenkins" created

There are two ways to verify that it was actually created. First, you can take a look at the dashboard with the minikube dashboard command:

Secondly, you can look at the CLI with kubectl get namespaces:

$ helm-jenkins jesse$ kubectl get namespaces
NAME              STATUS AGE
default           Active 5d
gsw-k8s-jenkins   Active 1d
kube-public       Active 5d
kube-system       Active 5d

Let’s create a persistent volume for Jenkins to take advantage of. This will allow us to persist data in the cluster when Minikube reboots. In a production environment, you’d need to use some type of block or driver for your storage. Let’s create a jenkins-volume.yaml file called jenkins-persist.

Here’s what you’ll put into that file:

apiVersion: v1
kind: PersistentVolume
metadata:
 name: jenkins-persist
 namespace: jenkins-project
spec:
 storageClassName: jenkins-persist
 accessModes:
   - ReadWriteOnce
 capacity:
   storage: 20Gi
 persistentVolumeReclaimPolicy: Retain
 hostPath:
   path: /storage/jenkins-volume/

Now, let’s create the volume for Jenkins to use:

$ kubectl create -f jenkins-volume.yaml
persistentvolume "jenkins-persist" created

Great! Now, we’re ready to use Helm to install Jenkins nice and easily. Let’s use the following values file with our installation:

# Default values for jenkins.
# This is a YAML-formatted file.
# Declare name/value pairs to be passed into your templates.
# name: value
## Overrides for generated resource names
# See templates/_helpers.tpl
# nameOverride:
# fullnameOverride:
Master:
 Name: jenkins-master
 Image: "jenkins/jenkins"
 ImageTag: "2.127"
 ImagePullPolicy: "Always"
 Component: "jenkins-master"
 UseSecurity: true
 AdminUser: admin
 # AdminPassword: <defaults to random>
 Cpu: "200m"
 Memory: "256Mi"
 ServicePort: 8080
 # For minikube, set this to NodePort, elsewhere use LoadBalancer # <to set explicitly, choose port between 30000-32767>
ServiceType: NodePort
 NodePort: 32000
 ServiceAnnotations: {}
 ContainerPort: 8080
 # Enable Kubernetes Liveness and Readiness Probes
 HealthProbes: true
 HealthProbesTimeout: 60
 SlaveListenerPort: 50000
 LoadBalancerSourceRanges:
 - 0.0.0.0/0
 # List of plugins to be install during Jenkins master start
 InstallPlugins:
 - kubernetes:1.7.1
 - workflow-aggregator:2.5
 - workflow-job:2.21
 - credentials-binding:1.16
 - git:3.9.1
 - greenballs:1.15
 # Used to approve a list of groovy functions in pipelines used
the script-security plugin. Can be viewed under /scriptApproval
 ScriptApproval:
 - "method groovy.json.JsonSlurperClassic parseText
java.lang.String"
 - "new groovy.json.JsonSlurperClassic"
 - "staticMethod
org.codehaus.groovy.runtime.DefaultGroovyMethods leftShift
java.util.Map java.util.Map"
 - "staticMethod
org.codehaus.groovy.runtime.DefaultGroovyMethods split
java.lang.String"
 CustomConfigMap: false
 NodeSelector: {}
 Tolerations: {}
Agent:
 Enabled: true
 Image: jenkins/jnlp-slave
 ImageTag: 3.10-1
 Component: "jenkins-slave"
 Privileged: false
 Cpu: "200m"
 Memory: "256Mi"
 # You may want to change this to true while testing a new image
 AlwaysPullImage: false
 # You can define the volumes that you want to mount for this
container
 # Allowed types are: ConfigMap, EmptyDir, HostPath, Nfs, Pod,
Secret
 volumes:
 - type: HostPath
 hostPath: /var/run/docker.sock
 mountPath: /var/run/docker.sock
 NodeSelector: {}
Persistence:
 Enabled: true
 ## A manually managed Persistent Volume and Claim
 ## Requires Persistence.Enabled: true
 ## If defined, PVC must be created manually before volume will
be bound
 # ExistingClaim:
 ## jenkins data Persistent Volume Storage Class
 StorageClass: jenkins-pv
 Annotations: {}
 AccessMode: ReadWriteOnce
 Size: 20Gi
 volumes:
 # - name: nothing
 # emptyDir: {}
 mounts:
 # - mountPath: /var/nothing
 # name: nothing
 # readOnly: true
NetworkPolicy:
 # Enable creation of NetworkPolicy resources.
 Enabled: false
 # For Kubernetes v1.4, v1.5 and v1.6, use 'extensions/v1beta1'
 # For Kubernetes v1.7, use 'networking.k8s.io/v1'
 ApiVersion: networking.k8s.io/v1
## Install Default RBAC roles and bindings
rbac:
 install: true
 serviceAccountName: default
 # RBAC api version (currently either v1beta1 or v1alpha1)
 apiVersion: v1beta1
 # Cluster role reference
 roleRef: cluster-admin

Now that we’ve set the values file, let’s use it to deploy Jenkins:

helm install --name gsw-k8s-jenkins -f jenkins-vaules.yaml stable/jenkins --namespace gsw-k8s-jenkins
NAME:   gsw-k8s-jenkins
LAST DEPLOYED: Mon Jun 18 22:44:34 2018
NAMESPACE: gsw-k8s-jenkins
STATUS: DEPLOYED
RESOURCES:
…

We can get the randomly generated Jenkins secret by addressing the Kubernetes secret store API:

$ kubectl get secret --namespace gsw-k8s-jenkins gsw-k8s-jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode; echo
<YOUR_PASSWORD_HERE>

Verify that Jenkins has installed using the following commands:

$ helm ls
NAME REVISION UPDATED STATUS CHART NAMESPACE
gsw-k8s-jenkins 1 Mon Jun 18 22:44:34 2018 DEPLOYED jenkins-0.16.3 gsw-k8s-jenkins

Then, open up Jenkins’ home page. You should be able to visit the home page at http://192.168.99.100:3200.

Comments are closed.