Optimierung der Jenkins-Executor-Konfiguration für schnellere Builds

Optimieren Sie Ihre CI/CD-Leistung durch die Beherrschung der Jenkins-Executor-Konfiguration. Dieser Expertenleitfaden erklärt, wie Sie die optimale Anzahl von Executoren basierend auf CPU- und I/O-Einschränkungen berechnen, Warteschlangenzeiten reduzieren und den Agentendurchsatz maximieren. Lernen Sie wesentliche Konfigurationsstrategien kennen, einschließlich der Nutzung von Pipeline-Parallelität, der Verwaltung statischer vs. dynamischer Agenten und der Identifizierung von Engpässen anhand wichtiger Metriken wie Warteschlangenlänge und I/O-Wartezeit. Setzen Sie diese umsetzbaren Schritte um, um schnellere Builds und eine effizientere Jenkins-Umgebung zu erreichen.

Optimierung der Jenkins-Executor-Konfiguration für schnellere Builds

Die Optimierung von Jenkins-Executoren ist im Grunde genommen Kapazitätsplanung in kleinen Schritten. Ein Executor ist ein Slot, in dem Jenkins Arbeit auf einem Knoten ausführen kann. Fügen Sie zu wenige Slots hinzu, und Jobs warten in der Warteschlange. Fügen Sie zu viele hinzu, und jeder Build kämpft um CPU, Arbeitsspeicher, Festplatte, Netzwerk und manchmal denselben Abhängigkeitscache.

Das Ziel ist nicht "mehr Executors". Das Ziel ist eine kürzere Gesamt-Feedbackzeit, ohne einzelne Builds unzuverlässig zu machen.

Controller-Executors auf Null setzen

Bei den meisten modernen Jenkins-Installationen sollte der Controller Arbeiten planen, die UI bedienen, Job-Konfigurationen speichern und Agenten koordinieren. Er sollte keinen Code kompilieren oder Testsuiten ausführen.

Setzen Sie Controller-Executors auf 0, es sei denn, Sie haben einen kleinen, bewussten administrativen Job, der dort ausgeführt werden muss. Ein ausgelasteter Build auf dem Controller kann die UI aushungern, die Warteschlangenplanung verzögern und Plugin-Probleme schwerer diagnostizierbar machen. Wenn der Controller instabil wird, spürt das jedes Team, das Jenkins verwendet.

Verlagern Sie Build-Arbeit auf Agenten mit klaren Labels:

linux && docker
linux && maven
windows && visualstudio
large-memory

Labels sind Teil der Executor-Optimierung, weil ein Job, der auf linux && docker wartet, sich nicht darum kümmert, dass Sie untätige Windows-Executors haben.

Beginnen Sie mit dem Arbeitslasttyp, nicht mit einer universellen Formel

Bei CPU-intensiven Builds beginnen Sie in der Nähe der Anzahl physischer oder virtueller CPU-Kerne. Ein 8-Kern-Build-VM, das C++-Kompilierung oder große Java-Testsuiten ausführt, könnte mit 6 bis 8 Executors beginnen und dann basierend auf Messungen nach unten oder oben angepasst werden.

Bei I/O-intensiven Builds können Sie möglicherweise mehr Executors als CPU-Kerne ausführen, da Jobs Zeit mit Warten auf Netzwerk-Downloads, Artefakt-Uploads oder Testdienste verbringen. Ein 8-Kern-Agent mit vielen Abhängigkeiten könnte 10 bis 12 Executors gut verarbeiten. Er könnte bei 6 auch zusammenbrechen, wenn die Festplatte langsam oder der Arbeitsspeicher knapp ist.

Der Arbeitsspeicher setzt oft die eigentliche Grenze. Wenn jeder Build 2 GB RAM verwenden kann und der Agent 16 GB hat, bleibt bei acht Executors kein Platz für das Betriebssystem, den Docker-Daemon, Sprachlaufzeiten, Browser-Tests oder den Dateisystem-Cache. In diesem Fall können vier oder fünf Executors schneller sein als acht, weil die Maschine das Auslagern vermeidet.

Verwenden Sie ein Arbeitsblatt wie dieses:

Agent RAM: 32 GB
Reserve für OS und Daemons: 4 GB
Verfügbar für Builds: 28 GB
Typischer Build-Spitzenwert: 3 GB
Start-Executors: 8 oder 9, dann unter Last validieren

Die Zahlen müssen nicht perfekt sein. Sie müssen explizit genug sein, damit Sie sie nach der Beobachtung echter Builds anpassen können.

Warteschlangengründe beobachten

Die Jenkins-Build-Warteschlange sagt Ihnen, warum Arbeit wartet. "Warte auf nächsten verfügbaren Executor" unterscheidet sich von "Es gibt keine Knoten mit dem Label." Ersteres deutet auf Kapazitätsdruck hin. Letzteres deutet auf ein Label- oder Agent-Provisionierungsproblem hin.

Wenn Entwickler sich beschweren, dass Jenkins langsam ist, überprüfen Sie:

  • Warteschlangenlänge nach Label.
  • Durchschnittliche Wartezeit in der Warteschlange.
  • Agent online/offline Wechsel.
  • Builds, die auf gesperrte Ressourcen warten.
  • Parallele Pipeline-Stages, die mehr Executor-Slots verbrauchen als erwartet.

Eine einzelne Pipeline mit zehn parallelen Branches kann zehn Executor-Slots verbrauchen. Das kann genau das sein, was Sie für eine Testmatrix wollen. Es kann auch jeden anderen Job auf einer kleinen Jenkins-Installation aushungern.

Einen Executor pro Einweg-Agent verwenden

Für Kubernetes-Agenten und viele Cloud-erstellte Agenten ist ein Executor pro Pod oder Instanz normalerweise das sauberste Modell. Der Pod ist die Isolationseinheit. Wenn Sie mehr Parallelität benötigen, erstellen Sie mehr Pods, anstatt nicht zusammenhängende Builds in denselben Einweg-Workspace zu packen.

Dieses Modell macht Ressourcenanfragen wichtig:

resources:
  requests:
    cpu: "2"
    memory: "4Gi"
  limits:
    memory: "6Gi"

Wenn die Anfragen zu niedrig sind, kann Kubernetes zu viele Jenkins-Agenten auf einen Knoten packen. Jenkins sieht verfügbare Executors, aber der Cluster-Knoten ist überlastet. Wenn die Limits zu eng sind, schlagen Builds mit Speicherfehlern fehl, die wie Anwendungsprobleme aussehen.

Bei statischen VM-Agenten können mehrere Executors in Ordnung sein. Stellen Sie nur sicher, dass das Workspace-Layout, die Cache-Verzeichnisse und die Tool-Installationen für gleichzeitige Jobs ausgelegt sind.

Die lauten Jobs drosseln

Einige Jobs sollten nicht so viele Kopien ausführen, wie Jenkins planen kann. Datenbank-Integrationstests, Browser-Tests, Lasttests und Image-Builds können gemeinsam genutzte Systeme schnell sättigen.

Verwenden Sie Job-Level-Drosselung, sperrbare Ressourcen oder Pipeline-Steuerungen:

pipeline {
  agent { label 'linux && docker' }
  options {
    disableConcurrentBuilds()
  }
  stages {
    stage('Build Image') {
      steps {
        sh 'docker build -t app:${BUILD_NUMBER} .'
      }
    }
  }
}

Für eine gemeinsam genutzte Staging-Datenbank ist eine Sperre klarer:

lock('staging-db') {
  sh './run-integration-tests.sh'
}

Dies kann dazu führen, dass ein Job wartet, aber es verhindert, dass fünf Jobs gemeinsam fehlschlagen und ihre gesamte Executor-Zeit verschwenden.

Den Agenten messen, nicht nur Jenkins

Jenkins kann Ihnen Informationen über Warteschlangenzeit und Executor-Nutzung geben. Das Betriebssystem sagt Ihnen, ob die Executor-Anzahl sinnvoll ist.

Auf Linux-Agenten überprüfen Sie:

uptime
mpstat 1
iostat -xz 1
free -h
df -h
docker system df

Hohe CPU bei niedriger I/O-Wartezeit bedeutet CPU-gebundene Arbeit. Hohe I/O-Wartezeit bedeutet, dass das Hinzufügen von Executors die Builds wahrscheinlich verlangsamen wird. Swap-Nutzung während Builds ist ein starkes Signal, die Executors zu reduzieren oder den Arbeitsspeicher zu erhöhen. Eine fast volle Festplatte kann Checkout, Archivierung und Docker-Builds zum Kriechen bringen.

Beobachten Sie auch die einzelne Build-Dauer. Wenn die Warteschlangenzeit um eine Minute sinkt, aber jeder Build fünf Minuten langsamer wird, ist die höhere Executor-Anzahl kein Gewinn.

In kleinen Schritten optimieren

Ändern Sie die Executor-Anzahlen schrittweise. Erhöhen Sie einen Agenten von 4 auf 6, beobachten Sie ein paar geschäftige Tage und entscheiden Sie dann. Große Sprünge verbergen die Ursache von Regressionen.

Führen Sie Notizen:

2026-05-24: linux-build-03 Executors 4 -> 6
Grund: Warteschlange für linux && maven durchschnittlich 12 Minuten
Beobachten: CPU, iowait, Maven-Cache-Lock-Konkurrenz, Build-Dauer
Rückgängig: auf 4 setzen, wenn p95-Build-Dauer stärker als erwartet steigt

Diese kurze Aufzeichnung hilft, wenn jemand zwei Wochen später fragt, warum der Agent langsam ist.

Das praktische Ziel

Ein gesundes Jenkins-Setup hat die meisten Agenten während Spitzenzeiten ausgelastet, kurze Warteschlangen für häufige Labels, kein Swapping, vorhersagbare Build-Dauer und keine Controller-Builds. Es hat auch genügend label-spezifische Kapazität, sodass ein fehlender Docker-Agent nicht dazu führt, dass nicht zusammenhängende Maven-Jobs warten.

Executor-Optimierung ist keine einmalige Einstellung. Sie ändert sich, wenn Ihre Teams parallele Stages hinzufügen, zu größeren Testsuiten übergehen, Docker-Builds einführen oder von statischen VMs zu Kubernetes-Agenten migrieren. Überprüfen Sie sie, wenn die Warteschlangenzeit sichtbar wird, wenn Agenten zu swappen beginnen oder wenn der schnellste Fix, den Leute vorschlagen, "füge einfach mehr Executors hinzu" ist. Manchmal ist das richtig. Oft ist der bessere Fix ein neuer Agenten-Pool, bessere Labels oder weniger gleichzeitige Kopien des Jobs, der alle anderen beeinträchtigt.

Parallele Stages brauchen ein Budget

Pipeline-Parallelität kann ein großer Gewinn sein, aber sie verbraucht schnell Executors. Ein Matrix-Build über vier Java-Versionen und drei Betriebssysteme kann zwölf Branches erzeugen. Wenn jeder Branch auf einem separaten Agenten läuft, kann dieser eine Build zwölf Executors verbrauchen, bevor die Deployment-Stages überhaupt beginnen.

Das ist akzeptabel, wenn das Team dafür geplant hat. Es ist schmerzhaft, wenn ein einzelner Pull-Request Release-Builds aushungert. Setzen Sie Grenzen um große Fan-Out-Jobs:

options {
  parallelsAlwaysFailFast()
}

Verwenden Sie Labels, die teure Branches an den richtigen Pool senden, und erwägen Sie, die vollständige Matrix auf dem Hauptzweig auszuführen, während Sie auf Pull-Requests eine kleinere Matrix ausführen. Das Ziel ist schnelles Feedback dort, wo es wichtig ist, nicht maximale Parallelität überall.

Interaktive und Batch-Erwartungen trennen

Nicht jeder Jenkins-Job verdient das gleiche Warteschlangenziel. Ein Produktions-Hotfix-Build, ein Pull-Request-Validierungsjob, ein nächtlicher Sicherheitsscan und ein wöchentlicher Bereinigungsjob können alle in Jenkins ausgeführt werden, aber sie sollten nicht gleichberechtigt konkurrieren.

Sie können sie mit Labels, Ruhezeiten, Drosselungen und geplanten Zeitfenstern trennen. Schwere nächtliche Jobs sollten laufen, wenn der interaktive PR-Verkehr gering ist. Langlaufende Lasttests sollten ihre eigenen Agenten haben. Release-Jobs verdienen möglicherweise reservierte Kapazität oder ein Label, das normale Branch-Jobs nicht verwenden können.

Dies ist weniger eine Frage der Politik als der Zuverlässigkeit. Wenn jede Arbeitslast einen Executor-Pool teilt, bestimmt die lauteste Arbeitslast das Erlebnis für alle.

Was dokumentiert werden sollte

Führen Sie für jeden Agenten-Pool eine kleine Aufzeichnung:

label: linux && docker
Agententyp: statische VM
Executors pro Agent: 4
Hauptarbeitslasten: Docker-Image-Builds, Integrationstests
Bekannte Grenzen: Festplatten-I/O und Docker-Layer-Wachstum
Bereinigung: nächtliches docker prune, Workspace-Bereinigung nach Build
Besitzer: Plattform-Team

Diese Aufzeichnung macht zukünftige Optimierungen viel einfacher. Wenn die Warteschlangenzeit wächst, können Sie entscheiden, ob Sie mehr Agenten desselben Typs hinzufügen, eine Arbeitslast in einen neuen Pool aufteilen oder die Parallelität der Jobs reduzieren, die die Konkurrenz verursachen.