In großen IT-Umgebungen, die Hunderte oder Tausende von Hosts umfassen, müssen Playbooks so gestaltet werden, dass sie sowohl skalierbar als auch wartbar sind. Das Ziel ist es, die Komplexität zu reduzieren, indem Playbooks modular aufgebaut und in kleinere, handhabbare Einheiten zerlegt werden.
Eine der effektivsten Strategien zur Verwaltung großer Playbooks besteht darin, diese in mehrere kleinere Playbooks zu unterteilen, die jeweils eine spezifische Aufgabe oder Rolle abdecken. Diese können dann nach Bedarf kombiniert oder in einer bestimmten Reihenfolge ausgeführt werden.
Beispielstruktur:
site.yml # Haupt-Playbook, das andere Playbooks aufruft
webservers.yml # Playbook zur Konfiguration von Webservern
dbservers.yml # Playbook zur Konfiguration von Datenbankservern
loadbalancers.yml # Playbook zur Konfiguration von Load BalancernBeispiel für ein Haupt-Playbook mit
import_playbook (empfohlen seit Ansible 2.4):
---
# Moderne Ansible-Syntax für bessere Performance und Fehlerbehandlung
- import_playbook: webservers.yml
- import_playbook: dbservers.yml
- import_playbook: loadbalancers.ymlHinweis: Während include zur Laufzeit
evaluiert wird, wird import_playbook zur Parse-Zeit
verarbeitet, was zu besserer Performance und frühzeitiger
Fehlererkennung führt.
Rollen sollten genutzt werden, um wiederverwendbare und modulare Playbooks zu erstellen. Jede Rolle sollte eine klar definierte Aufgabe haben und in sich abgeschlossen sein, sodass sie unabhängig getestet und verwaltet werden kann.
Beispiel für die Verwendung von Rollen:
---
- name: Einrichtung einer kompletten Webserver-Umgebung
hosts: webservers
roles:
- common # Rolle für allgemeine Aufgaben wie Benutzerverwaltung, Security-Updates
- nginx # Rolle zur Konfiguration von Nginx als Webserver
- php # Rolle zur Installation und Konfiguration von PHPTags können verwendet werden, um spezifische Teile eines Playbooks selektiv auszuführen, ohne das gesamte Playbook durchlaufen zu müssen. Dies ist besonders nützlich, wenn Sie nur einen bestimmten Teil Ihrer Infrastruktur aktualisieren oder testen möchten.
Beispiel für die Verwendung von Tags:
---
- name: Installiere und konfiguriere Nginx
hosts: webservers
tasks:
- name: Installiere Nginx
apt:
name: nginx
state: present
tags:
- install
- nginx
- name: Konfiguriere Nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
tags:
- configure
- nginxAusführung eines spezifischen Teils des Playbooks:
ansible-playbook site.yml --tags "install"In großen, dynamischen Umgebungen reichen statische Inventory-Dateien oft nicht aus. Dynamische Inventories ermöglichen es, Host-Informationen zur Laufzeit aus externen Quellen abzurufen.
Beispiel für AWS EC2 Dynamic Inventory:
# aws_ec2.yml
plugin: aws_ec2
regions:
- us-east-1
- eu-west-1
keyed_groups:
- key: tags
prefix: tag
- key: instance_type
prefix: instance_type
compose:
ansible_host: public_ip_addressAusführung mit dynamischem Inventory:
ansible-playbook -i aws_ec2.yml site.ymlFür spezielle Umgebungen können eigene Inventory-Scripts entwickelt werden:
#!/usr/bin/env python3
# custom_inventory.py
import json
import requests
def get_inventory():
# Abrufen der Host-Informationen aus CMDB/API
response = requests.get('https://cmdb.company.com/api/hosts')
hosts_data = response.json()
inventory = {
'_meta': {'hostvars': {}},
'webservers': {'hosts': []},
'dbservers': {'hosts': []}
}
for host in hosts_data:
group = host['role'] + 'servers'
if group in inventory:
inventory[group]['hosts'].append(host['name'])
inventory['_meta']['hostvars'][host['name']] = {
'ansible_host': host['ip'],
'environment': host['env']
}
return inventory
if __name__ == '__main__':
print(json.dumps(get_inventory(), indent=2))In großen Umgebungen, insbesondere in verteilten Systemen, müssen Playbooks in der Lage sein, komplexe Abhängigkeiten zwischen verschiedenen Komponenten zu verwalten. Dies erfordert eine sorgfältige Planung und Strukturierung der Playbooks.
Rollen können so gestaltet werden, dass sie ihre Abhängigkeiten
selbst verwalten. Dies kann in der meta/main.yml der Rolle
definiert werden, um sicherzustellen, dass benötigte Rollen oder Tasks
vor der Ausführung bereitgestellt werden.
Beispiel für Abhängigkeiten in einer Rolle:
---
# meta/main.yml der nginx-Rolle
dependencies:
- role: common
vars:
some_var: 42
- role: ssl_certificates
when: nginx_ssl_enabled | default(false)Manchmal müssen Aufgaben in einer bestimmten Reihenfolge auf
verschiedenen Hosts ausgeführt werden. Ansible bietet Mechanismen, um
sicherzustellen, dass Tasks auf verschiedenen Hosts koordiniert werden,
z.B. durch die Verwendung von serial oder
wait_for.
Beispiel für koordinierte Aufgaben:
---
- name: Verteile Konfigurationen und starte Services in der richtigen Reihenfolge
hosts: webservers
serial: 1
tasks:
- name: Verteilen der Konfiguration
template:
src: webserver.conf.j2
dest: /etc/webserver.conf
- name: Starte den Webserver
service:
name: webserver
state: started
- name: Warte auf Service-Verfügbarkeit
wait_for:
port: 80
host: "{{ ansible_host }}"
timeout: 30Empfohlene Verzeichnisstruktur für große Umgebungen:
inventories/
├── production/
│ ├── hosts.yml
│ ├── group_vars/
│ │ ├── all.yml
│ │ ├── webservers.yml
│ │ └── dbservers.yml
│ └── host_vars/
│ ├── web01.yml
│ └── db01.yml
├── staging/
│ ├── hosts.yml
│ └── group_vars/
└── development/
├── hosts.yml
└── group_vars/
Beispiel für hierarchische Gruppierung:
# inventories/production/hosts.yml
all:
children:
europe:
children:
germany:
children:
frankfurt:
hosts:
web01.fra.company.com:
web02.fra.company.com:
munich:
hosts:
web03.muc.company.com:
americas:
children:
usa:
children:
east:
hosts:
web01.nyc.company.com:In großen Umgebungen ist es wichtig, dass Playbook-Versionen und Konfigurationen konsistent und nachvollziehbar verwaltet werden. Dies kann durch den Einsatz von Versionskontrollsystemen und durch das Einführen von Versionskennzeichnungen in Playbooks und Konfigurationsdateien erreicht werden.
Feature Branch Workflow für Playbooks:
# Entwicklung neuer Features
git checkout -b feature/nginx-optimization
# ... Änderungen an Playbooks
git commit -m "Add nginx performance tuning"
git push origin feature/nginx-optimization
# Merge über Pull Request nach Code Review
# Deployment auf verschiedene Umgebungen
git checkout main
git tag v1.2.3Environment-spezifische Branches:
# Struktur für verschiedene Umgebungen
main # Produktionsreife Version
├── staging # Staging-Umgebung
└── develop # EntwicklungsumgebungPlaybooks sollten in einem Versionskontrollsystem wie Git verwaltet werden, um Änderungen nachverfolgen und Rollbacks durchführen zu können. Dies ermöglicht es auch, mehrere Versionen eines Playbooks parallel zu verwalten (z.B. für verschiedene Umgebungen).
Beispiel für die Verwaltung von Playbooks in Git:
git init
git add playbooks/
git commit -m "Initial commit: Basic infrastructure playbooks"
git tag v1.0.0Versionskennzeichnungen in Playbooks und Konfigurationsdateien helfen dabei, sicherzustellen, dass immer die richtige Version eines Playbooks ausgeführt wird, insbesondere in Umgebungen mit mehreren Teams oder Releases.
Beispiel für eine Versionskennzeichnung in einem Playbook:
---
# Version 1.2.3 - Nginx Performance Optimization
- name: Setup Webserver
hosts: webservers
vars:
playbook_version: "1.2.3"
playbook_name: "webserver-setup"
pre_tasks:
- name: Log Playbook-Version
debug:
msg: "Executing {{ playbook_name }} version {{ playbook_version }}"Die Automatisierung von Playbook-Deployments ist ein entscheidender Faktor für die Skalierbarkeit und Zuverlässigkeit in großen IT-Umgebungen. Durch die Integration von Ansible in CI/CD-Pipelines und die Automatisierung des gesamten Deployments kann sichergestellt werden, dass Playbooks konsistent und schnell auf eine große Anzahl von Hosts angewendet werden.
Die Integration von Ansible in CI/CD-Pipelines ermöglicht es, Playbooks automatisch nach jeder Codeänderung oder jedem Commit auszuführen. Dies gewährleistet, dass Änderungen schnell und zuverlässig auf allen benötigten Systemen ausgerollt werden.
Beispiel für eine GitLab CI-Konfiguration:
stages:
- validate
- deploy-staging
- deploy-production
variables:
ANSIBLE_HOST_KEY_CHECKING: "False"
validate_playbooks:
stage: validate
script:
- ansible-playbook --syntax-check site.yml
- ansible-lint playbooks/
deploy_staging:
stage: deploy-staging
script:
- ansible-playbook -i inventories/staging site.yml
only:
- develop
deploy_production:
stage: deploy-production
script:
- ansible-playbook -i inventories/production site.yml
only:
- main
when: manualansible-pullIn einigen Szenarien kann es sinnvoll sein, die Hosts selbst die
Playbooks abrufen und ausführen zu lassen, anstatt sie zentral zu
pushen. Dies kann durch die Verwendung von ansible-pull
erreicht werden, was besonders in dynamischen Umgebungen nützlich
ist.
Beispiel für die Verwendung von
ansible-pull:
# Auf dem Ziel-Host
ansible-pull -U https://github.com/myrepo/playbooks.git \
-d /opt/ansible \
-i localhost, \
site.ymlCron-Job für regelmäßige Updates:
# /etc/cron.d/ansible-pull
*/30 * * * * root /usr/local/bin/ansible-pull -U https://github.com/company/ansible-configs.git -d /opt/ansible -i localhost, local.yml >> /var/log/ansible-pull.log 2>&1In sehr großen Umgebungen kann es notwendig sein, zusätzliche Orchestrierungstools zu verwenden, um die Ausführung von Playbooks über mehrere Rechenzentren oder Cloud-Regionen hinweg zu koordinieren.
Beispiele für Orchestrierungstools:
AWX/Ansible Tower: Bietet eine grafische Benutzeroberfläche und zusätzliche Funktionen für die Verwaltung und Orchestrierung von Ansible-Playbooks.
# Job Template in AWX
name: "Production Webserver Deployment"
project: "Infrastructure Playbooks"
playbook: "webservers.yml"
inventory: "Production Inventory"
credentials: "SSH Key"Terraform: Kann zur Bereitstellung und Verwaltung der Infrastruktur in Kombination mit Ansible verwendet werden.
# Terraform + Ansible Provisioner
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1d0"
instance_type = "t2.micro"
provisioner "local-exec" {
command = "ansible-playbook -i '${self.public_ip},' webserver.yml"
}
}Parallelisierung und Batch-Processing:
---
- name: Large Scale Deployment
hosts: all
strategy: linear
serial:
- 10% # Starte mit 10% der Hosts
- 50% # Dann 50%
- 100% # Schließlich alle
max_fail_percentage: 5
tasks:
- name: Deploy Application
include_tasks: deploy_app.ymlAnsible-Konfiguration für bessere Performance:
# ansible.cfg
[defaults]
host_key_checking = False
gathering = smart
fact_caching = memory
fact_caching_timeout = 86400
forks = 50
pipelining = True
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null
control_path = /tmp/ansible-ssh-%%h-%%p-%%rBeispiel für Custom Callback Plugin:
# callback_plugins/deployment_tracker.py
from ansible.plugins.callback import CallbackBase
import json
import requests
class CallbackModule(CallbackBase):
def v2_playbook_on_stats(self, stats):
# Sende Deployment-Status an Monitoring-System
summary = {
'timestamp': datetime.now().isoformat(),
'hosts_ok': len(stats.ok),
'hosts_failed': len(stats.failures),
'hosts_unreachable': len(stats.dark)
}
requests.post('https://monitoring.company.com/api/deployments',
json=summary)Automatischer Rollback bei Fehlern:
---
- name: Application Deployment with Rollback
hosts: webservers
vars:
app_version: "{{ ansible_date_time.epoch }}"
tasks:
- name: Create Backup
command: cp -r /opt/app /opt/app.backup.{{ app_version }}
- name: Deploy New Version
unarchive:
src: "app-{{ version }}.tar.gz"
dest: /opt/app
register: deploy_result
- name: Rollback on Failure
command: |
rm -rf /opt/app
mv /opt/app.backup.{{ app_version }} /opt/app
when: deploy_result is failed