Erstellen Sie Ihre erste deklarative Jenkins-Pipeline für CI/CD

Erstellen Sie eine erste deklarative Jenkins-Pipeline mit Stages, Agents, Checkout, Tests, Deployment-Gates, Anmeldeinformationen und Post-Aktionen.

Erstellen Sie Ihre erste deklarative Jenkins-Pipeline für CI/CD

Ihre erste deklarative Jenkins-Pipeline sollte eine praktische Frage beantworten: Kann Jenkins Ihren Code auschecken, bauen, testen und Bereitstellungsschritte nur dann ausführen, wenn der richtige Branch besteht? Eine Jenkinsfile gibt Ihnen diesen Workflow als Code im selben Repository wie Ihre App.

Die deklarative Syntax ist ein guter Ausgangspunkt, da sie eine vorhersagbare Struktur bietet: pipeline, agent, stages, steps und post.

Verstehen der deklarativen Pipeline-Struktur

Die deklarative Pipeline definiert den gesamten Workflow in einer Datei namens Jenkinsfile, die zusammen mit Ihrem Anwendungscode in Ihrem SCM-Repository (z.B. Git) gespeichert wird. Diese Praxis wird als Pipeline as Code bezeichnet.

Kernelemente einer deklarativen Pipeline

Eine deklarative Pipeline muss die folgenden Blöcke auf oberster Ebene enthalten:

  1. pipeline: Der obligatorische äußerste Block, der den Pipeline-Inhalt definiert.
  2. agent: Gibt an, wo die Pipeline oder eine bestimmte Stage ausgeführt wird (z.B. any, none oder spezifische Labels).
  3. stages: Enthält einen oder mehrere sequenzielle stage-Blöcke.
  4. stage: Definiert einen konzeptionellen Arbeitsblock (z.B. Build, Test, Deploy).
  5. steps: Enthält einen oder mehrere Befehle oder Funktionen, die innerhalb einer stage ausgeführt werden.
pipeline {
    agent any 
    environment { // Optional: Definiert Umgebungsvariablen
        APP_VERSION = '1.0.0'
    }
    stages {
        stage('Build') {
            steps {
                // Befehle kommen hier hin
            }
        }
    }
    post { // Optional: Aktionen, die nach Abschluss der Pipeline ausgeführt werden
        always { 
            echo 'Pipeline abgeschlossen.' 
        }
    }
}

Schritt 1: Einrichten des Jenkins-Jobs

Um eine Pipeline aus Code auszuführen, müssen Sie einen Jenkins-Job konfigurieren, der die Jenkinsfile aus Ihrem Repository liest.

  1. Navigieren Sie zu Ihrem Jenkins-Dashboard und wählen Sie Neues Element.
  2. Geben Sie einen Namen für Ihre Pipeline ein (z.B. my-first-ci-pipeline).
  3. Wählen Sie den Elementtyp Pipeline und klicken Sie auf OK.
  4. Scrollen Sie auf der Konfigurationsseite nach unten zum Abschnitt Pipeline.
  5. Ändern Sie die Definition von Pipeline-Skript zu Pipeline-Skript aus SCM.
  6. Wählen Sie Ihr SCM (z.B. Git).
  7. Geben Sie die Repository-URL ein und konfigurieren Sie bei Bedarf Ihre Anmeldeinformationen.
  8. Stellen Sie sicher, dass der Skriptpfad auf Jenkinsfile gesetzt ist (Standard).

Schritt 2: Definieren der Jenkinsfile für CI/CD

Wir werden eine umfassende Jenkinsfile erstellen, die einen einfachen CI/CD-Workflow simuliert und Standard-Stages für eine erfolgreiche Bereitstellung integriert.

Angenommen, Sie haben eine Repository-Struktur, die Ihren Anwendungsquellcode (z.B. ein einfaches Python- oder Java-Projekt) und die Jenkinsfile im Stammverzeichnis enthält.

Vollständiges Beispiel einer deklarativen Pipeline

Diese Pipeline verwendet den node-Agent (falls konfiguriert) und nutzt grundlegende Shell-Schritte (sh), um echte Arbeit zu simulieren. Die Bereitstellungs-Stage ist bedingt und läuft nur nach erfolgreichem Abschluss der vorherigen Stages.

// Jenkinsfile
pipeline {
    // 1. Agent-Definition: Gibt an, wo die gesamte Pipeline ausgeführt wird
    agent { 
        label 'my-build-agent' // Verwenden Sie ein spezifisches Label, falls verfügbar, oder 'any'
    }
    
    // 2. Umgebungsvariablen: Definieren Sie Variablen, die in der gesamten Pipeline verwendet werden können
    environment {
        CONTAINER_REGISTRY = 'registry.example.com'
        IMAGE_NAME = 'myapp'
    }
    
    stages {
        
        // Stage 1: Checkout (Quellcodeverwaltung)
        stage('Quellcode auschecken') {
            steps {
                // Der Schritt 'checkout scm' checkt den Code automatisch aus
                // basierend auf der Konfiguration, die in den Jenkins-Job-Einstellungen definiert ist.
                checkout scm
                sh 'echo "Quellcode erfolgreich ausgecheckt."'
            }
        }
        
        // Stage 2: Build-Artefakte
        stage('Artefakt bauen') {
            steps {
                sh 'echo "Starte Build für $IMAGE_NAME:$BUILD_ID"'
                // Simulation: Ein Docker-Image bauen oder eine jar/war-Datei kompilieren
                sh "docker build --label build_id=${BUILD_ID} -t ${CONTAINER_REGISTRY}/${IMAGE_NAME}:${BUILD_ID} ."
            }
        }
        
        // Stage 3: Tests und Qualitätstore
        stage('Tests ausführen') {
            steps {
                sh './run_unit_tests.sh'
                sh 'echo "Führe Integrationstests aus..."'
                // Beispiel zum Sammeln von Testergebnissen (erfordert entsprechende Plugins)
                // junit '**/target/surefire-reports/*.xml'
            }
        }
        
        // Stage 4: Bereitstellung (Bedingt)
        stage('In Staging bereitstellen') {
            // Die 'when'-Direktive stellt sicher, dass die Stage nur unter bestimmten Bedingungen läuft
            when {
                branch 'main'
            }
            steps {
                sh "docker push ${CONTAINER_REGISTRY}/${IMAGE_NAME}:${BUILD_ID}"
                sh 'kubectl apply -f k8s/deployment-staging.yaml'
                script {
                    // Script-Blöcke erlauben traditionelle Groovy-Logik innerhalb deklarativer Schritte
                    echo "Bereitstellung in der Staging-Umgebung erfolgreich."
                }
            }
        }
    }
    
    // 3. Post-Aktionen: Definieren Sie Aktionen basierend auf dem endgültigen Pipeline-Status
    post {
        success {
            echo 'Pipeline erfolgreich abgeschlossen. Team über Slack benachrichtigen...'
            // slackSend channel: '#devops-alerts', message: 'CI/CD Erfolg!'
        }
        failure {
            echo 'Pipeline fehlgeschlagen. Logs auf Fehler überprüfen.'
        }
        cleanup {
            sh 'docker image prune -f --filter "label=build_id=$BUILD_ID"'
        }
    }
}

Schritt 3: Ausführen und Überwachen der Pipeline

Sobald die Jenkinsfile committet und in den Branch gepusht wurde, der in Ihrem Jenkins-Job konfiguriert ist:

  1. Klicken Sie auf der Jenkins-Job-Seite auf Jetzt bauen (oder warten Sie auf den SCM-Polling/Webhook-Trigger).
  2. Überwachen Sie den Build im Bereich Build-Verlauf.
  3. Klicken Sie auf die laufende Build-Nummer und wählen Sie Konsolenausgabe, um die Ausführungsdetails Schritt für Schritt anzuzeigen.
  4. Sie können auch die Stage-Ansicht-Visualisierung (falls das Plugin installiert ist) verwenden, um den Fortschritt der Stages Checkout, Build, Test und Deploy grafisch zu sehen.

Best Practices und erweiterte Funktionen

Nutzung von Bibliotheken und gemeinsam genutztem Code

Vermeiden Sie für komplexe oder stark wiederholte Schritte, ausführliches Groovy direkt in der Jenkinsfile zu schreiben. Verwenden Sie stattdessen Shared Libraries. Diese externen Bibliotheken ermöglichen es Ihnen, gemeinsame Funktionen (wie Standard-Bereitstellungsroutinen oder Benachrichtigungsfunktionen) zu definieren, die aus mehreren Pipelines aufgerufen werden können, was Ihre Jenkinsfile sauberer macht.

// Aufruf eines Shared Library-Schritts
stage('Benutzerdefiniertes Setup') {
    steps {
        customLibrary.initializeEnvironment(env: 'prod')
    }
}

Arbeiten mit Anmeldeinformationen

Harten Sie niemals vertrauliche Informationen (Passwörter, Token, API-Schlüssel) direkt in der Jenkinsfile. Verwenden Sie das integrierte Credentials-Management-System von Jenkins.

Der Schritt withCredentials ermöglicht es Ihnen, sicher auf gespeicherte Geheimnisse zuzugreifen:

stage('Registry authentifizieren') {
    steps {
        withCredentials([usernamePassword(credentialsId: 'docker-registry-creds', 
                                          passwordVariable: 'PASS', 
                                          usernameVariable: 'USER')]) {
            sh '''
                printf '%s' "$PASS" | docker login \
                  --username "$USER" \
                  --password-stdin "$CONTAINER_REGISTRY"
            '''
        }
    }
}

Agent-Auswahl

Tipp: Definieren Sie Ihren agent immer spezifisch mit einem label anstelle von agent any. Die Verwendung von agent any bedeutet, dass die Pipeline auf dem Jenkins-Controller-Knoten ausgeführt werden könnte, was ein Sicherheitsrisiko darstellt und die Controller-Leistung beeinträchtigen kann. Stellen Sie sicher, dass Sie ordnungsgemäß konfigurierte Jenkins-Agents (Knoten) mit den erforderlichen Tools (Docker, Maven, Node.js) installiert haben.

Fazit

Halten Sie die erste Pipeline langweilig und zuverlässig: Wählen Sie ein echtes Agent-Label, checken Sie Code aus, bauen Sie, testen Sie, steuern Sie die Bereitstellung über den Branch und bewahren Sie Geheimnisse in Jenkins-Anmeldeinformationen. Sobald das funktioniert, fügen Sie Schritt für Schritt Artefaktveröffentlichung, Sicherheitsscans und Umgebungsförderung hinzu.