Basierend auf dem vorherigen Tutorial über das Betreiben von Jenkins in einem Kubernetes-Cluster ist es jetzt an der Zeit, die Kubernetes-Infrastruktur zu nutzen, um Build-Jobs über den Cluster zu skalieren.

Beispiel-Build-Jobs

Erstelle zuerst zwei Projekte, um das Setup zu testen. Die Jobs werden nichts Nützliches tun - sie werden nur 10 Sekunden warten und dann beenden.

Erstelle die Jobs, indem du im Dashboard auf “New Item” klickst und “Freestyle Project” auswählst.

Im Abschnitt “Build” füge einen “Execute shell”-Build-Schritt hinzu.

Der Befehl, den der Build-Job ausführen soll, ist:

sleep 10

Nach dem Speichern erscheint der neue Job im Dashboard. Erstelle einen weiteren Job, sodass es insgesamt zwei gibt.

Wenn beide Jobs gleichzeitig ausgelöst werden, erscheinen sie unter “Build Executor Status”.

Vorerst werden beide Jobs innerhalb des Jenkins-Pods ausgeführt. Das wird langfristig nicht skalieren.

Das Ziel ist, jede Build-Job-Instanz in einem neu erstellten Pod auszuführen, dessen Lebenszyklus an den Build-Job gebunden ist:

  • Wenn ein Job ausgelöst wird, wird ein neuer Pod erstellt.
  • Der Job läuft innerhalb dieses Pods.
  • Wenn der Job beendet ist, wird der Pod gelöscht.

Um dies zu erreichen, ist zusätzliche Konfiguration erforderlich.

Kubernetes-Plugin installieren

Installiere das Kubernetes-Plugin über:

  • Manage Jenkins
  • Manage Plugins

Dann:

  • Available
  • wähle “Kubernetes”
  • klicke “Install without restart”

Das Plugin wird installiert:

Kubernetes-Secrets hinzufügen

Zwei Kubernetes-Secrets (Service-Accounts + RBAC) werden benötigt.

Das erste ist jenkins-robot.yaml:

apiVersion: v1
kind: ServiceAccount
metadata:
 name: jenkins-robot
 namespace: jenkins
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
 name: jenkins-robot
 namespace: jenkins
 labels:
 "app.kubernetes.io/name": 'jenkins'
rules:
- apiGroups: [""]
 resources: ["pods", "pods/exec", "pods/log", "persistentvolumeclaims", "events"]
 verbs: ["get", "list", "watch"]
- apiGroups: [""]
 resources: ["pods", "pods/exec", "persistentvolumeclaims", "events"]
 verbs: ["create", "apply", "delete", "deletecollection", "patch", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
 name: jenkins-robot-binding
 namespace: jenkins
roleRef:
 apiGroup: rbac.authorization.k8s.io
 kind: Role
 name: jenkins-robot
subjects:
- kind: ServiceAccount
 name: jenkins-robot
 namespace: jenkins

Das zweite ist jenkins-robot-global.yaml:

apiVersion: v1
kind: ServiceAccount
metadata:
 name: jenkins-robot-global
 namespace: jenkins
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
 name: jenkins-robot-global
 namespace: jenkins
 labels:
 "app.kubernetes.io/name": 'jenkins'
rules:
- apiGroups: [""]
 resources: ["pods", "pods/exec", "pods/log", "persistentvolumeclaims"]
 verbs: ["get", "list", "watch"]
- apiGroups: [""]
 resources: ["pods", "pods/exec", "persistentvolumeclaims"]
 verbs: ["create", "apply", "delete", "deletecollection", "patch", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
 name: jenkins-robot-global-binding
 namespace: jenkins
roleRef:
 apiGroup: rbac.authorization.k8s.io
 kind: ClusterRole
 name: jenkins-robot-global
subjects:
- kind: ServiceAccount
 name: jenkins-robot-global
 namespace: jenkins

Wende beide Manifeste an:

kubectl apply -n jenkins -f jenkins-robot.yaml
kubectl apply -n jenkins -f jenkins-robot-global.yaml

Diese Secrets müssen zu Jenkins hinzugefügt werden.

Rufe das erste Secret ab mit:

kubectl -n jenkins get serviceaccount jenkins-robot --template='{{range.secrets}}{{.name}}{{"\n"}}{{end}}' | xargs -n 1 kubectl -n jenkins get secret --template='{{ if.data.token }}{{.data.token }}{{end}}' | head -n 1 | base64 -d -

Kopiere das resultierende Token in die Zwischenablage, um es im nächsten Schritt einzufügen.

Erstelle in Jenkins die Credential über:

  • Manage Jenkins
  • Manage Credentials

Dann klicke:

  • New Item

Navigiere zu:

  • Global credentials (unrestricted)

Dann:

  • Add credentials

Gib diese Werte ein:

  • Kind: Secret text
  • Scope: Global
  • Secret: <the secret from the clipboard>
  • ID: Jenkins-Robot

Wiederhole für das jenkins-robot-global-Secret, das abgerufen werden kann mit:

kubectl -n jenkins get serviceaccount jenkins-robot-global --template='{{range.secrets}}{{.name}}{{"\n"}}{{end}}' | xargs -n 1 kubectl -n jenkins get secret --template='{{ if.data.token }}{{.data.token }}{{end}}' | head -n 1 | base64 -d -

Beide Credentials sollten jetzt in Jenkins erscheinen:

Die Kubernetes-Cloud zu Jenkins hinzufügen

Jenkins muss mit dem Kubernetes-Cluster konfiguriert werden, den es verwenden wird. Füge die Kubernetes-Cloud hinzu über:

  • Manage Jenkins
  • Manage Nodes and Clouds
  • Configure Clouds
  • Add a new cloud: Kubernetes

Unter “Kubernetes Cloud Details” gib an:

  • Name: Kubernetes
  • Kubernetes URL: https://<k8s-master-ip>:6443
  • Kubernetes Namespace: jenkins
  • Credentials: Jenkins-Robot
  • Jenkins Tunnel: <ip>:50000

Die IP des Cluster-Master-Nodes kann gefunden werden mit:

kubectl get nodes -o wide | grep master

Die IP für den Jenkins-Tunnel ist die IP des jenkins-jnlp-Service:

kubectl get service jenkins-jnlp -n jenkins

Belasse die restlichen Werte auf ihren Standardeinstellungen:

Teste die Verbindung mit dem “Test Connection”-Button.

Pod- und Container-Templates hinzufügen

Konfiguriere das Pod-Template wie folgt:

Pod Template:

  • Name: jnlp
  • Usage: Use this node as much as possible

Für dieses Tutorial verwenden die Agent-Container das jenkins/jnlp-agent-alpine-Image:

  • Name: jnlp
  • Docker image: jenkins/jnlp-agent-alpine

Füge ein HostPath-Volume hinzu:

  • Host path: /var/run/docker.sock
  • Mount path: /var/run/docker.sock

Füge ein EmptyDir-Volume hinzu:

  • Mount path: /home/jenkins/agent

Speichere die Konfiguration.

Konfiguriere schließlich Jenkins so, dass nur Agent-Nodes Build-Jobs ausführen:

  • Manage Jenkins
  • Manage Nodes and Clouds
  • master
  • Configure

Setze:

  • Number of executors: 0
  • Usage: Only build jobs with label expressions matching this node

Speichern.

Die Pod-Build-Agents testen

Löse beide Build-Jobs gleichzeitig aus. Du solltest zwei Pods unter “Build Executor Status” sehen.

Wenn die Pods laufen, werden die Jobs darin ausgeführt:

Ressourcen