Nachdem wir ja nun auch alle möglichen Dienstleistungen rund um Ansible anbieten, dachte ich mir, es kann nicht schaden, es mir auch mal zu Gemüte zu führen. Kurzum: Ich bin bisher begeistert davon, wie einfach man damit auch komplexe Aufgaben lösen kann und werde sicherlich mein Wissen in dieser Richtung noch vertiefen.

Meine ersten Gehversuche haben mir dann auch gleich geholfen, ein Problem zu lösen, das mich schon länger geplagt hat. IT’ler neigen ja dazu, auch selber eine umfangereiche Infrastruktur zu betreiben und dabei wird der Aufwand üblicherweise mit der Zeit nicht weniger. Ich habe durchaus einige ähnliche Systeme im Einsatz und kann getrost sagen, wenn ich bei ein paar repräsentativen Systemen geprüft habe, ob ich anstehende Updates sofort einspielen oder lieber warten sollte, kann ich sie für die restlichen Rechner auch gleich machen. Aber wie, ohne ständig von System zu System hüpfen zu müssen. Es gibt dafür natürlich Lösungen, aber die meisten, die ich gefunden habe, brauchen einfach deutlich zu viele Ressourcen und rentieren sich auch für meine mittlere zweistellige Anzahl an Rechnern nicht.

Also habe ich versucht, das Problem mit Ansible zu erschlagen und war auch in erstaunlich kurzer Zeit fertig. Inzwischen weiss ich, dass meine Lösung nicht sonderlich elegant ist und man noch einiges daran verbessern kann, aber ich denke, sie ist eingängig und deshalb möchte ich sie hier vorstellen.

Zuerst lege ich mir die Datei ~/ansible/hosts an, in der sämtliche Hosts namentlich aufgelistet werden. Ich habe sie anonymisiert und stark gekürzt, um den Blogartikel nicht unnötig in die Länge zu ziehen. z.B. ist hier nur ein NAT mit Hosts dargestellt, in meiner “echten” Liste sind es mehr, was “händische” Updates nicht einfacher macht.

[centos:children]
centos6
centos7

[debian:children]
debian-jessie
raspbian-stretch
debian-stretch

[centos6]
odin.example.com
kvasir.example.com

[centos7]
balder.example.com
heimdall.example.com
tyr.example.com

[raspbian-stretch]
rerun.asgard.example.com

[debian-jessie]
gullveig.example.com
[debian-stretch]
freyr.example.com

[solaris11]
surtur.asgard.example.com
[special-centos]
loki.asgard.example.com

[asgard]
loki.asgard.example.com
rerun.asgard.example.com
surtur.asgard.example.com

Zuerst werden hier Gruppen definiert, die andere Gruppen zusammenfassen. So sind die Gruppen centos6 und centos7 Teil von centos und alle Hosts in den Untergruppen auch gleichzeitig Mitglied in den Übergruppen. Bei genauem Hinsehen erkennt man auch, dass loki.asgard.example.com Mitglied in zwei Gruppen ist, was durchaus so beabsichtigt ist.

Das folgende Playbook ( ~/ansible/playbooks/update-all.yml ) kann nun (fast) alle Systeme auf einen Schlag aktualisieren. Wenn mir also mein Icinga 2 meldet, dass Updates anstehen, suche ich mir einen repräsentativen Host jeder Gruppe aus und prüfe, welche Updates anstehen. Denke ich, dass ich sie gefahrlos einspielen kann, starte ich das folgende Playbook.

---
- hosts: centos*:!special-centos
  remote_user: alice
  become: yes
  tasks: 
    - name: update everything
      yum:
        name: "*"
        state: latest
        exclude: "owncloud*"
- hosts: special-centos
  remote_user: alice
  become: yes
  tasks: 
    - name: update everything
      yum:
        name: "*"
        state: latest
        skip_broken: yes
- hosts: debian*:raspbian*
  remote_user : alice
  become: yes
  tasks:
    - name: install dmidecode
      apt:
        name: dmidecode
        update_cache: yes
    - name: update package cache
      apt:
        update_cache: yes
    - name: upgrade packages
      apt:
        upgrade: dist
        force: yes
    - name: autoremove dependencies
      apt:
        autoremove: yes

Das erste Play verbindet sich zu allen centos Hosts, die nicht Teil der Gruppe centos-special sind und führt das Modul yum aus, das mit der Option latest alle Pakete aktualisiert. Explizit ausgeklammert ist dabei owncloud, da hier immer Nacharbeiten nötig sind. Dabei nutzt Ansible den User alice, für den ein SSH Key hinterlegt ist und wird per sudo zu root. Das muss natürlich vorher erlaubt werden, wobei Ansible auch ermöglicht, für sudo Passwörter mitzugeben. Ist dieses Play durchgelaufen, sind alle CentOS Maschinen, ausser loki aktualisiert. Dabei handelt es sich um eine “gewachsene Speziallösung” auf der diverse Pakete aus Drittrepositories installiert sind, die inzwischen in defekten Abhängigkeiten festhängen. Hier wird das yum Modul also mit der skip_broken Option aufgerufen, das diese verbogenen Pakete ausklammert.

Das Paket deltarpm um Gebrauch von deltarpms zu machen, habe ich über ein anderes Playbook installiert, könnte man aber prinzipiell auch noch hier vor den ersten Plays aufnehmen.

Nach den CentOS Hosts kommen die Debian Maschinen an die Reihe. Hier wird erst dmidecode installiert, das für den reibungslosen Ablauf nötig ist und z.B. bei raspbian nicht gleich installiert war. Ist das Paket bereits installiert, überspringt Ansible diesen Schritt nach einer Prüfung. Die Tasks für Debian haben alle das Update des package cache deaktiviert, was den Ablauf sehr beschleunigt. Der erste Task führt dieses Update durch und das reicht für alle weiteren. Zum Schluss werden noch nicht mehr benötigte Dependencies entfernt.

Damit Ansible sich auch in das NAT “asgard” verbinden kann, habe ich entsprechende Optionen in ~/ansible/hosts/group_vars/asgard hinterlegt.

ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q asgard.example.com" -o ConnectTimeout=800s'
ntp_server: 192.168.74.19

Damit wird festgelegt, dass ansible sich zu allen diesen Hosts über einen Jumphost verbinden muss. Dabei gibt der Name der Datei an, für welche Gruppe von Hosts die darin enthaltenen Optionen gelten. Die Adresse des NTP Servers hat keinen Einfluss auf dieses Playbook, soll aber zeigen, dass man hier auch einfach andere Variablen setzen kann.

Der Solaris Host bleibt hier aussen vor, da es dafür noch kein fertiges Modul für Updates gibt. Hier greife ich ggf. noch händisch ein.

Inzwischen weiss ich, dass man die verwendeten Module auch einfach abhängig vom Fact des Betriebssystems machen kann und noch den einen oder anderen Kniff. Aber in der aktuellen Version ist das Playbook wohl besser verständlich.

Wer mehr über Ansible wissen will, sollte unbedingt mal in einer unserer Schulungen vorbeischauen.

Thomas Widhalm

Autor: Thomas Widhalm

Thomas war Systemadministrator an einer österreichischen Universität und da besonders für Linux und Unix zuständig. Seit 2013 möchte er aber lieber die große weite Welt sehen und hat sich deshalb dem Netways Consulting Team angeschlossen. Er möchte ausserdem möglichst weit verbreiten, wie und wie einfach man persönliche Kommunikation sicher verschlüsseln kann, damit nicht dauernd über fehlenden Datenschutz gejammert, sondern endlich was dagegen unternommen wird. Mittlerweile wird er zum logstash - Guy bei Netways und hält Schulungen und erstellt Schulungsunterlagen zu diesem faszinierenden Tool. Seit 2017 stellt er sich neuen Herausforderungen als Lead Support Engineer und versucht sein Wissen aus den vorgenannten Tätigkeiten im Produktsupport umzusetzen.