Skip to main content

Jenkins: Kubernetes Deployment, Storage Setup (Storage Class, PersistentVolume with NFS), TLS Encryption with Nginx Ingress and Kubernetes Secret

739 words·
Jenkins Kubernetes Helm

Overview
#

In this tutorial I’m using a Kubernetes K8s cluster with MetalLB deployed with Kubespray on Debian 12 servers:

192.168.30.21 node1 # Controller / Master Node
192.168.30.22 node2 # Controller / Master Node
192.168.30.23 node3 # Worker Node
192.168.30.24 node4 # Worker Node

192.168.30.60 NFS Server, Bitbucket Data Center Container, Deployment Host

NFS Prerequisites
#

NFS Server Setup
#

Jenkins Folder Structure
#

Create the folder structure for the PersistentVolume:

# Create folder structure
sudo mkdir -p /srv/nfs/k8s_share/jenkins-volume

# Change permissions
sudo chown -R 1000:1000 /srv/nfs/k8s_share/jenkins-volume

NFS Exports
#

I’m using the following NFS server configuration:

# Install NFS package
sudo apt install nfs-kernel-server

# Open NFS configuration
sudo vi /etc/exports
# NFS configuration: Define the kubernetes nodes
/srv/nfs/k8s_share 192.168.30.71(rw,sync,no_root_squash)
/srv/nfs/k8s_share 192.168.30.72(rw,sync,no_root_squash)
/srv/nfs/k8s_share 192.168.30.73(rw,sync,no_root_squash)
/srv/nfs/k8s_share 192.168.30.74(rw,sync,no_root_squash)
# Restart NFS server
sudo systemctl restart nfs-server

Install NFS on Kubernetes Nodes
#

Install the NFS utilities package on the Kubernetes nodes:

# Install NFS utilities package
sudo apt install nfs-common -y

Verify the NFS connectivity:

# Verify that the NFS server is correctly configured
/usr/sbin/showmount -e 192.168.30.60

Kubernetes Prerequisites
#

Create Namespace
#

# Create a namespace for the Jenkins deployment
kubectl create namespace jenkins

StorageClass, PV, PVC
#

# Create a manifest for the Jenkins volume
vi jenkins-volume.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: jenkins-pv
  namespace: jenkins
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: Immediate

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: jenkins-pv
  namespace: jenkins
spec:
  storageClassName: jenkins-pv
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 20Gi
  volumeMode: Filesystem
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /srv/nfs/k8s_share/jenkins-volume
    server: 192.168.30.60
# Deploy the manifest
kubectl create -f jenkins-volume.yaml

Verify Storage Resources
#

# List PV & PVC
kubectl get pv,pvc -n jenkins

# Shell output:
NAME                          CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
persistentvolume/jenkins-pv   20Gi       RWO            Retain           Available           jenkins-pv     <unset>                          38s

Helm
#

Add Jenkins Repository
#

# Add the Jenkins repository
helm repo add jenkinsci https://charts.jenkins.io

# Update the repository index
helm repo update
# List Helm Charts
helm search repo jenkinsci

# Shell output:
NAME                    CHART VERSION   APP VERSION     DESCRIPTION
jenkinsci/jenkins       5.2.2           2.452.2         Jenkins - Build great things at any scale! As t...

Save Helm Chart Values
#

# Save the values for the Jenkins chart
helm show values jenkinsci/jenkins > jenkins-values.yaml

Adopt Helm Chart Values
#

# Open the Helm Chart manifest
vi jenkins-values.yaml
# Define the service type: (Default is ClusterIP)
serviceType: NodePort


# Storage
storageClass: jenkins-pv # Define the PV
# -- Annotations for the PVC
annotations: {}
# -- Labels for the PVC
labels: {}
# -- The PVC access mode
accessMode: "ReadWriteOnce"
# -- The size of the PVC
size: "8Gi"


# Deactivate the serviceAccount
serviceAccount:
  # -- Configures if a ServiceAccount with this name should be created
  create: false


# Install default plugins
installPlugins:
  - kubernetes:4246.v5a_12b_1fe120e
  - workflow-aggregator:596.v8c21c963d92d
  - git:5.2.2
  - configuration-as-code:1810.v9b_c30a_249a_4c

Install Jenkins
#

# Deploy Jenkins
helm install jenkins jenkinsci/jenkins -f jenkins-values.yaml -n jenkins

# Delete Jenkins
helm delete jenkins -n jenkins

Verify Service Resources
#

# List resources in the "jenkins" namespace
kubectl get all -n jenkins

# Shell output:
NAME            READY   STATUS    RESTARTS   AGE
pod/jenkins-0   2/2     Running   0          64s

NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/jenkins         NodePort    10.233.38.174   <none>        8080:32266/TCP   64s
service/jenkins-agent   ClusterIP   10.233.35.121   <none>        50000/TCP        64s

Kubernetes TLS Certificate Secret
#

In this setup I’m using a Let’s Encrypt wildcard certificate.

# Create a Kubernetes secret for the TLS certificate
kubectl create secret tls jenkins-tls --cert=./fullchain.pem --key=./privkey.pem -n jenkins

Nginx Ingress for NodePort Service
#

# Create ingress manifest
vi jenkins-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: jenkins
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
  tls:
  - hosts:
    - jenkins.jklug.work
    secretName: jenkins-tls
  rules:
  - host: jenkins.jklug.work
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: jenkins  # Define AWX ingress service name
            port:
              number: 8080
# Deploy ingress resource
kubectl create -f jenkins-ingress.yml -n jenkins

# Delete ingress resource
kubectl delete -f jenkins-ingress.yml -n jenkins

DNS Entry
#

The DNS entry for the Nginx ingress must point to one of the worker nodes:

192.168.30.23 jenkins.jklug.work
# Or 
192.168.30.24 jenkins.jklug.work

Jenkins Webinterface
#

Webinterface
#

# Access the webinterface: Via NodePort
192.168.30.21:32266
192.168.30.22:32266
192.168.30.23:32266
192.168.30.24:32266

# Access the webinterface: Via Ingress
https://jenkins.jklug.work

Login & Retrieve Password
#

# Default user
admin
# Retrieve admin password
kubectl exec --namespace jenkins -it svc/jenkins -c jenkins -- /bin/cat /run/secrets/additional/chart-admin-password && echo

# Shell output:
YbGzyCogoJb8phkLqdo2kF

Restart Jenkins
#

Jenkins can be restarted from within the webinterface as follows:

  • Navigate to: https://jenkins.jklug.work/safeRestart

  • Click “Restart”


Links #

# Official Documentation
https://www.jenkins.io/doc/book/installing/