knuspermagier.de
Hallo. Ich bins! Philipp!

Erste Schritte mit Ansible

Seit Monaten bin ich auf der Suche nach einer Art Server automatisch zu konfigurieren, für die ich mich nicht drei Wochen in ein dickes Regelwerk einarbeiten muss.

Meine Anforderungen waren ja ganz einfach:

  1. Ich will bestimmen welche Pakete und Services auf dem Server sein sollen und welche Konfigurationsdateien wo rumliegen sollen. Diese sollen aus entsprechenden Templates mit Variablen generiert werden.

  2. Ich will nicht zwei Millionen verschachtelte Ordner mit tausend Dateien anlegen nur um nginx auf einem Server zu installieren.

  3. Ich will nicht auf meinem Rechner und auf dem Server zwanzig neue Services installieren müssen, damit alles automagisch zusammenfindet.

  4. Ich will eine Doku, mit der ich mir in 15 Minuten ein einfaches “nginx + PHP + mysql”-Setup-Script zusammenbauen kann, ohne von den Möglichkeiten total überwältigt zu werden.

Vor ein paar Wochen unternahm ich dann, weil ich beruflich mal wieder Server administrieren musste, einen neuen Versuch, etwas zu finden.

Folgende Sachen erfüllten meine Anforderungen leider nicht: Puppet, Chef, SaltStack.

(Das bedeutet nicht, dass sie nicht vielleicht auch dafür geeignet waren, aber ich fand in meiner Kurzrecherche nicht die nötigen Anhaltspunkte)

Zuerst dachte ich, dass auch Ansible den Test nicht bestehen wird, nach kurzem Studium der Dokumentation waren die Bedenken allerdings wie weggeblasen.

Dank des Getting Started-Guides bekam ich einen guten ersten Einblick und war tatsächlich in der Lage schnell und problemlos ein Playbook zu erstellen, mit dem ich die Server einrichten konnte.

Um diesem Post jetzt noch etwas mehr Inhalt als “Ansible ist toll” zu geben, hier ein wirklich kurzes Playbook.

Ziel soll es sein, einen Ubuntu-EC2-Server mit nginx, PHP und MySQL auszustatten.

---
- hosts: all
  gather_facts: false
  remote_user: ubuntu
  sudo: yes
  vars:
    http_port: 80
    api_root: /var/www/ansibletest.com/
  tasks:
  - name: update apt
    apt: update_cache=yes upgrade=full
  - name: install tools
    apt: name={{item}} state=present
    with_items:
      - vim
      - wget
      - curl
      - python-setuptools
      - screen

Jap. Ihr seht richtig. Yaml. Keine Ahnung was das soll, aber diesen einen Minuspunkt kann man wohl verkraften. Anscheinend startet man ein Playbook (so heißen diese Vorschriften bei Ansible) mit drei Minussen.

Dieser erste Block hier sorgt jedenfalls dafür, dass essentielle Dinge wie vim, wget und screen installiert sind. Vorher wird apt geupdated. Außerdem werden ein paar Variablen gesetzt, die später in die Konfigurations-Templates eingefügt werden. Diese können aber z.B. auch in der Host-Konfiguration pro Host, oder pro Gruppe von Hosts angegeben werden.

Sieht alles ziemlich verständlich aus, oder?

  - name: install nginx
     apt: name=nginx state=present
  - name: install php5 and modules
    apt: name={{item}} state=present
    with_items:
      - php5-fpm
      - php5-cli
      - php5-mcrypt
      - php5-curl
      - php5-mysql
      - php5-json
      - php5-readline
  - name: enable php5 modules
    shell: php5enmod mcrypt curl mysql json readline
  - name: install mysql
    apt: name=mysql-server state=present

Auch hier nur ganz einfache Anweisungen, hauptsächlich für apt. Spannender wird’s im letzten Teil, der die Konfigurationen erzeugt.

  - name: delete default config
    file: path=/etc/nginx/sites-available/default state=absent
    notify:
    - restart webserver
  - name: copy nginx config for api
    notify:
    - restart webserver
    template: src=templates/nginx-site.j2 dest=/etc/nginx/sites-available/ansibletest.conf
  - name: activate config
    file: src=/etc/nginx/sites-available/ansibletest.conf dest=/etc/nginx/sites-enabled/ansibletest.conf state=link
    notify:
    - restart webserver
  - name: ensure nginx is running
    service: name=nginx state=started enabled=yes
  - name: ensure php5-fpm is running
    service: name=php5-fpm state=started enabled=yes
handlers:
  - name: restart webserver
    service: name=nginx state=restarted
    service: name=php5-fpm state=restarted

(Die Templates spare ich mir hier jetzt mal, das sind einfache Jinja2-Templates mit {{ solchen Replacements }})

Das sieht dann schon ein bisschen unübersichtlicher aus, ist aber auch ganz einfach. Die Handler am Ende sind dann noch Tasks, die über das notify nur getriggert werden, wenn auch wirklich was passiert ist. So wird der Webserver nicht 200x neugestartet, sondern nur, wenn die Konfigurationsdatei ausgetauscht wurde.

Das ganze speichern wir jetzt als playbook.yaml.

Ansible will jetzt noch wissen, wo der Kram ausgeführt werden soll, dafür gibt es Inventory-Files. Die können auch ganz einfach aussehen:

[testserver]
ansibletest.com

Fertig. Das ganze dann mit ansible-playbook playbook.yaml -i inventory aufrufen und die Magie mit anschauen.

(Das Playbook gibt es hier nochmal am Stück als Gist)

Das war jetzt natürlich nur ein sehr kleiner Ausschnitt von dem, was mit Ansible möglich ist, und man könnte die Frage stellen, ob es sich schon für so kleine Aufgabenstellungen lohnt — ich finde aber schon. In meinem bisherigen Leben habe ich schon soviel Server aufgesetzt und immer wieder an den gleichen Stellen gegoogelt, was ich nun in die Konfiguration schreiben muss, damit PHP funktioniert, etc — hätte ich mich nur schon früher damit beschäftigt, hätte ich wohl einige Zeit gespart.

Ich freue mich auf jeden Fall darauf, Server in Zukunft nicht mehr anders vorzubereiten.

(Abgesehen vom Yaml, darauf freue ich mich nicht.)