Integration von Ansible mit Jenkins: Automatisierung Ihrer CI/CD-Pipeline
Integrieren Sie Ansible mit Jenkins, um Playbooks aus CI/CD-Pipelines auszuführen, SSH-Anmeldeinformationen zu verwalten und konsistent bereitzustellen.
Integration von Ansible mit Jenkins: Automatisierung Ihrer CI/CD-Pipeline
Die Integration von Ansible mit Jenkins ermöglicht Ihrer CI/CD-Pipeline, ein Artefakt zu erstellen, Tests durchzuführen und mit denselben Playbooks bereitzustellen, die Sie auch außerhalb von Jenkins verwenden. Die größte Herausforderung besteht darin, Anmeldeinformationen, Inventar und Playbook-Ausführung zu verknüpfen, ohne die Pipeline in einen Haufen von Shell-Befehlen zu verwandeln.
Diese Anleitung zeigt einen praktischen Aufbau: Jenkins orchestriert die Pipeline, während Ansible die Bereitstellung und Konfiguration auf den Zielhosts übernimmt. Die Beispiele gehen von SSH-basierten Linux-Bereitstellungen aus, aber das gleiche Muster funktioniert mit umgebungsspezifischen Inventaren und Rollen.
Wie Jenkins und Ansible zusammenpassen
Bevor Sie die Pipeline schreiben, trennen Sie die Verantwortlichkeiten:
- Jenkins: Checkt Code aus, erstellt Artefakte, führt Tests durch, sammelt Logs und entscheidet, wann Bereitstellungsphasen ausgeführt werden.
- Ansible: Verbindet sich mit Zielhosts, kopiert Artefakte, schreibt Konfigurationen, verwaltet Dienste und hält Bereitstellungsschritte idempotent.
Warum Jenkins mit Ansible integrieren?
Diese Aufteilung gibt Ihrem Team eine klare Grenze:
- Jenkins speichert den Release-Ablauf in einer
Jenkinsfile. - Ansible speichert Infrastrukturaktionen in Playbooks und Rollen.
- Inventardateien entscheiden, welche Hosts zu Staging, Produktion oder anderen Umgebungen gehören.
- Jenkins-Anmeldeinformationen schützen SSH-Schlüssel, Vault-Passwörter und Tokens.
Voraussetzungen für die Integration
Bevor Sie beginnen, stellen Sie sicher, dass Sie Folgendes haben:
- Einen funktionierenden Jenkins-Controller und mindestens einen Agenten, der Bereitstellungsjobs ausführen kann.
- Ansible, installiert auf dem Jenkins-Agenten, der
ansible-playbookausführt. - Zielmaschinen, die von diesem Agenten über SSH erreichbar sind.
- Ein dediziertes SSH-Schlüsselpaar für die Automatisierung.
- Anwendungscode, Inventar, Playbooks und Rollen in der Versionskontrolle.
Einrichten von Jenkins für Ansible
Jenkins benötigt zwei Dinge, bevor es Ansible sicher ausführen kann: die Ansible-Laufzeit auf einem Agenten und Anmeldeinformationen für die Zielhosts.
1. Installieren des Ansible-Plugins
Sie können ansible-playbook direkt über einen Shell-Schritt aufrufen, aber das Jenkins-Ansible-Plugin kann die Konfiguration und Ausgabe einfacher handhabbar machen.
- Navigieren Sie zu
Manage Jenkins>Manage Plugins. - Gehen Sie zum Tab
Availableund suchen Sie nach "Ansible". - Wählen Sie das "Ansible"-Plugin aus und klicken Sie auf
Install without restartoderDownload now and install after restart.
2. Konfigurieren von SSH-Anmeldeinformationen
Ansible verwendet SSH, um eine Verbindung zu Zielservern herzustellen. Speichern Sie den privaten Schlüssel in Jenkins-Anmeldeinformationen und nicht im Repository.
- Gehen Sie zu
Manage Jenkins>Manage Credentials. - Wählen Sie den von Ihren Jobs verwendeten Anmeldeinformationsspeicher aus.
- Klicken Sie auf
Add Credentials. - Wählen Sie
SSH Username with private key. - Legen Sie eine stabile ID fest, z. B.
ansible-ssh-key. - Geben Sie den SSH-Benutzernamen ein, der auf den Zielmaschinen verwendet wird.
- Fügen Sie den privaten Schlüssel hinzu und speichern Sie die Anmeldeinformationen.
Tipp: Best Practices für die Schlüsselverwaltung
- Hartcodieren Sie niemals private SSH-Schlüssel in einer Jenkinsfile, einem Inventar oder einem Playbook.
- Verwenden Sie dedizierte Automatisierungsschlüssel, keine persönlichen Schlüssel.
- Rotieren Sie Schlüssel nach einem Zeitplan, der der Sicherheitsrichtlinie Ihres Teams entspricht.
Entwerfen Ihrer Jenkins-Pipeline mit Ansible
Verwenden Sie eine deklarative Pipeline in einer Jenkinsfile, damit die Bereitstellungslogik zusammen mit dem Anwendungscode überprüft wird.
Grundlegende Pipelinestruktur
Hier ist ein kompaktes Beispiel für einen Build, ein Staging-Deployment und ein gated Production-Deployment:
// Jenkinsfile
pipeline {
agent any
environment {
// Definieren Sie bei Bedarf Umgebungsvariablen
ANSIBLE_HOST_KEY_CHECKING = 'False' // Seien Sie vorsichtig in der Produktion, bevorzugen Sie known_hosts
}
stages {
stage('Checkout Source') {
steps {
git 'https://your-scm-url/your-repo.git'
}
}
stage('Build Application') {
// Diese Phase könnte ein JAR, WAR, Docker-Image usw. erstellen.
// Beispiel: Erstellen eines Spring Boot JAR
steps {
sh 'mvn clean package'
}
}
stage('Run Unit Tests') {
steps {
sh 'mvn test'
}
}
stage('Deploy to Staging') {
steps {
script {
// Verwenden Sie den SSH-Agenten, um den privaten Schlüssel für Ansible verfügbar zu machen
sshagent(credentials: ['ansible-ssh-key']) {
// Ansible-Playbook ausführen
sh 'ansible-playbook -i inventory/staging.ini playbooks/deploy_app.yml \
-e "app_version=$(cat target/VERSION)"'
}
}
}
}
stage('Deploy to Production') {
// Diese Phase erfordert möglicherweise eine manuelle Genehmigung
input {
message "Bereitstellung für die Produktion fortsetzen?"
ok "In Produktion bereitstellen"
}
steps {
script {
sshagent(credentials: ['ansible-ssh-key']) {
sh 'ansible-playbook -i inventory/production.ini playbooks/deploy_app.yml \
-e "app_version=$(cat target/VERSION)"'
}
}
}
}
}
post {
always {
echo 'Pipeline beendet.'
}
success {
echo 'Pipeline erfolgreich!'
// slackSend channel: '#deployments', message: "Bereitstellung erfolgreich: ${env.BUILD_URL}"
}
failure {
echo 'Pipeline fehlgeschlagen!'
// slackSend channel: '#deployments', message: "Bereitstellung fehlgeschlagen: ${env.BUILD_URL}"
}
}
}
Wichtige Details zur Pipeline
agent anyfunktioniert für eine Demo. Verwenden Sie in der Produktion ein Agenten-Label, das garantiert, dass Ansible installiert ist.sshagent(credentials: ['ansible-ssh-key'])macht den privaten Schlüssel nur innerhalb dieses Blocks verfügbar.ansible-playbook -i inventory/staging.ini playbooks/deploy_app.ymlhält die Zielumgebung explizit.- Der
input-Block für die Produktion fügt ein manuelles Gate vor einer sensiblen Bereitstellung hinzu. - Vermeiden Sie es, die Host-Key-Überprüfung in der Produktion zu deaktivieren. Verwalten Sie stattdessen
known_hostsauf dem Jenkins-Agenten.
Beispiel-Ansible-Playbook: Bereitstellen einer Webanwendung
Hier sind ein vereinfachtes inventory/staging.ini und playbooks/deploy_app.yml für eine Java-Webanwendung. Ihr Artefaktname, Dienstmanager und Pfade können abweichen.
inventory/staging.ini
[web_servers]
web1.example.com
web2.example.com
[database_servers]
db1.example.com
[all:vars]
ansible_user=ubuntu
playbooks/deploy_app.yml
---
- name: Webanwendung bereitstellen
hosts: web_servers
become: yes
vars:
app_name: my-webapp
app_path: /opt/{{ app_name }}
app_port: 8080
app_version: "{{ app_version | default('1.0.0') }}"
tasks:
- name: Sicherstellen, dass das Anwendungsverzeichnis existiert
ansible.builtin.file:
path: "{{ app_path }}"
state: directory
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: '0755'
- name: Anwendungs-JAR auf das Ziel kopieren
ansible.builtin.copy:
src: "target/{{ app_name }}-{{ app_version }}.jar"
dest: "{{ app_path }}/{{ app_name }}.jar"
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: '0644'
notify: App-Dienst neu starten
- name: Sicherstellen, dass die systemd-Dienstdatei existiert
ansible.builtin.template:
src: templates/my-webapp.service.j2
dest: /etc/systemd/system/{{ app_name }}.service
owner: root
group: root
mode: '0644'
notify: App-Dienst neu starten
- name: Sicherstellen, dass der App-Dienst gestartet und aktiviert ist
ansible.builtin.systemd:
name: "{{ app_name }}"
state: started
enabled: yes
handlers:
- name: App-Dienst neu starten
ansible.builtin.systemd:
name: "{{ app_name }}"
state: restarted
daemon_reload: yes
templates/my-webapp.service.j2 (Systemd-Dienstvorlage)
[Unit]
Description={{ app_name }}-Anwendung
After=network.target
[Service]
User={{ ansible_user }}
ExecStart=/usr/bin/java -jar {{ app_path }}/{{ app_name }}.jar --server.port={{ app_port }}
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
Dieses Playbook erstellt das App-Verzeichnis, kopiert das erstellte JAR, schreibt eine systemd-Unit und startet den Dienst. Der Handler startet den Dienst nur neu, wenn sich das Artefakt oder die Unit-Datei ändert.
Best Practices und Tipps
- Halten Sie Playbooks idempotent, sodass ein erneutes Ausführen einer fehlgeschlagenen Pipeline keinen zusätzlichen Schaden verursacht.
- Speichern Sie Vault-Passwörter in Jenkins-Anmeldeinformationen und übergeben Sie sie über eine temporäre Passwortdatei oder eine genehmigte Anmeldeinformationsbindung.
- Organisieren Sie die Bereitstellungslogik in Rollen, z. B.
webserver,databaseundapp_deploy. - Verwenden Sie separate Inventare oder
group_varsfür Staging und Produktion. - Führen Sie Ansible auf dedizierten Jenkins-Agenten aus, nicht auf dem Controller.
- Verwenden Sie
-voder-vvnur, wenn Sie mehr Details benötigen; vermeiden Sie es, Geheimnisse in Logs preiszugeben. - Testen Sie Playbooks, bevor Jenkins sie ausführt, insbesondere für Produktionsrollen.
Wann Sie einen Fachmann hinzuziehen sollten
Ziehen Sie einen Jenkins- oder Plattformadministrator hinzu, wenn die Pipeline in der Produktion bereitstellt, gemeinsame Anmeldeinformationen verwaltet, auf viele Hosts schreibt oder Auditkontrollen benötigt. Die Handhabung von Anmeldeinformationen, die Überprüfung von Host-Schlüsseln und das Rollback-Verhalten verdienen eine zweite Überprüfung vor dem ersten Produktionseinsatz.
Fazit
Verwenden Sie Jenkins für die Orchestrierung und Ansible für den Bereitstellungsstatus. Bewahren Sie Anmeldeinformationen in Jenkins auf, halten Sie Playbooks in der Versionskontrolle, machen Sie das Inventar explizit und testen Sie dieselben Ansible-Befehle außerhalb der Pipeline, bevor Sie die Produktionsbereitstellung automatisieren.