Ansible

Ansible ist ein Open-Source Automatisierungs-Werkzeug zur Orchestrierung und allgemeinen Konfiguration und Administration von Computern. Es kombiniert Softwareverteilung, Ad-hoc-Kommando-Ausführung und Konfigurationsmanagement. Es verwaltet Netzwerkcomputer unter anderem über SSH und erfordert keinerlei zusätzliche Software auf dem zu verwaltenden System. Module nutzen zur Ausgabe JSON und können in jeder beliebigen Programmiersprache geschrieben sein. Das System nutzt YAML zur Formulierung wiederverwendbarer Beschreibungen von Systemen. Quelle: Wikipedia

Implementiert ist Ansible in Python und führt Befehle über SSH aus.

  • facts:
  • inventory: Liste der Ziele (via SSH) auf die Aufgaben angewendet werden sollen
  • module: Funktionen von Ansible
  • variablen (in Playbooks, als host- oder groupvars, als extra-vars )
  • handlers: abschließende Tätigkeiten (Ausführung bei Bedarf)
  • playbook: Eine Art Drehbuch was zu tun ist (Liste von Anweisungen, Variablen, Tasks und Verweise auf Rollen)
  • roles („Rollen“): ausgelagerte Playbooks, die zur Wiederverwendung optimiert sind
  • tasks: einzelne Arbeitsschritte die jeder Host durchläuft
  • vault: Speicher für Zugangsdaten
  • ansible-galaxy (requirements): Sammlung von Rollen unter https://galaxy.ansible.com
  • YAML: ist einfache Auszeichnungssprache dessen Syntax alle Dateien haben müssen

Definition von Idempotenz (engl. „idempotence“): „the property of certain operations in mathematics and computer science that can be applied multiple times without changing the result beyond the initial application“ (Quelle)

Generell geht darum bestimmte Aufgaben wiederholbar zu machen, d.h. eine Aufgabe sollte nicht bei jedem Lauf neu ausgeführt werden (was weitere Aktionen wie Server-restarts bedeuten kann) sondern nur wenn sich etwas ändert. Das Ergebnis sollte aber auch jedes mal die gleiche sein.

  • aktuelle Version: sudo -H pip install ansible
  • bestimmte-Version: sudo -H pip install ansible==2.7.8

SSH-Fingerprint check

Problem: Bei neue Hosts sind die Fingerprints lokal unbekannt, d.h. Ansible scheitert an der interaktiven Nachfrage von SSH (ob der Fingerprint akzeptiert werden soll).

Das könnte auf zwei Arten gelöst werden:

  1. Entweder man deaktiviert den Check komplett
    1. per Config (es werden alle Fingerprints ignoriert): in ansible.cfg (/etc/ansible/ansible.cfg oder ~/.ansible.cfg)
      [defaults]
      host_key_checking = False
  2. fallweise über Umgebungsvariable (ANSIBLE_HOST_KEY_CHECKING = False), z.B. mit export ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook …
  3. etwas unschöner auch über die SSH-Config (fallweise –ssh-common-args='-o StrictHostKeyChecking=no' bzw. permanent)
  4. oder einen task schreiben um die neuen Fingerprints lokal abzulegen:
      - name: Write the new ec2 instance host key to known hosts
        connection: local
        shell: "ssh-keyscan -H {{ inventory_hostname }} >> ~/.ssh/known_hosts"

Quellen: https://stackoverflow.com/questions/32297456/how-to-ignore-ansible-ssh-authenticity-checking

Ansible hat das Henne-Ei-Problem Python zu benötigen aber um das zu Installieren braucht man bereits Python. Bei Debian/Ubuntu in der Minimalinstallation ist Python z.B. nicht installiert.

Aber auch das lässt sich mit Ansible-Mitteln lösen, dazu muss

  • erstmal das erheben der facts („gather_facts: False“) abgeschaltet werden (weil das bereits mit Python realisiert ist)
  • dann mittels raw-Modul direkt ein SSH-Kommando abgesetzt werden (Achtung: das beachtet kein Umgebungsvariablen wie z.B. Proxy-Einstellungen!)
  • und zuletzt explizit nachgeholt werden (mit dem setup-Modul) um in weiteren tasks auf die facts zugreifen zu können.

Hier ein passendes Playbook:

---
- hosts: all
  gather_facts: False
  # become: yes
  pre_tasks:
  - name: Install python for Ansible
    raw: test -e /usr/bin/python || (apt-get -y update && apt install -y python)
    register: output
    changed_when: output.stdout != ""
  tasks:
  - name: Gathering Facts now
    setup:

https://gist.github.com/gwillem/4ba393dceb55e5ae276a87300f6b8e6f

.ansible/roles

Beispiel: das inventory in der Datei hosts enthält ein Gruppe „meine-Server“ auf denen der Befehl „uname -a“ ausgeführt werden soll: ansible -i hosts meine-Server -a 'uname -a'

Verwendung:

  • Interaktiv: --ask-vault-pass
  • in Skripten: --vault-password-file ~/.vault_pass
  • config
    • aus Umgebungsvariable ANSIBLE_CONFIG (export ANSIBLE_CONFIG=~/.ansible.cfg)
    • pro Benutzer: ~/.ansible.cfg
    • systemweit: /etc/ansible/ansible.cfg
    • Anweisung vault_password_file = /path/to/vault_password_file
    • via Umgebungsvariable: ANSIBLE_VAULT_PASSWORD_FILE (export ANSIBLE_VAULT_PASSWORD_FILE=~/.vault_pass.txt)

Verwaltung des Vault-files:

  • anlegen: ansible-vault create myVaultfile.yml
  • editieren 1): ansible-vault edit myVaultfile.yml
  • anzeigen: ansible-vault view myVaultfile.yml
  • entschlüsseln: ansible-vault decrypt myVaultfile.yml
  • Passwort ändern: ansible-vault rekey myVaultfile.yml

verschlüsselte Zeichenketten

Statt eines vault-files sind auch einzelne verschlüsselte Zeichenketten (encrypt_string) möglich, beispielweise z.B. um einzelne Variablen zu befüllen.

Beispiel: Hier bekommt die Variable DB_password den Inhalt „test“, was mit Passwort „test“ verschlüsselt wird:

  • interaktiv nach verschlüsselter Zeichenkette fragen: ansible-vault encrypt_string
  • … oder den Standard-input (=stdin) nehmen (via echo, cat, …) und die Ansible-Variable DB_password befüllen:
    echo -n test | ansible-vault encrypt_string --stdin-name 'DB_password'
    New Vault password: 
    Confirm New Vault password: 
    Reading plaintext input from stdin. (ctrl-d to end input)
    DB_password: !vault |
              $ANSIBLE_VAULT;1.1;AES256
              34343731306634383662333232613932373137626262643234633561356464663430343430636532
              3863333730383735363965643363386462376634366136650a353463663661316163373530386337
              38353365383830613935363838653833636530353537383834643865333130323032386661643132
              3132306637383466610a626164653830323565333635396662653066636237656262313965373263
              6264
    Encryption successful

→ diese Ausgabe kann direkt in yaml-Dateien benutzt werden.

Ein Playbook das verschlüsselte vault-strings benutzt muss von nun an bei m Aufruf entschlüsselt werden: ansible-playbook site.yml --ask-vault-pass

In awx/tower muss der credential type=Vault vorhanden sein: https://docs.ansible.com/ansible-tower/latest/html/userguide/credentials.html#id13

mehrere Benutzer (Vault-IDs)

awx


1)
es wird der Standard-Editor aus der Umgebungsvariablen $EDITOR benutzt