z6c - personal blog about topics

Christian Müller – Letzte Änderung: 05.10.2016 17:31 Uhr

(unvollständig) Tutorial: etckeeper, gitlab und ansible

Viele Server zentral und automatisiert zu verwalten; Dafür gibt es mittlerweile rund zwei Dutzend Systeme. Alle paar Jahre schaue ich mir diese Systeme an und stelle fest, daß sie mir nicht gefallen.

Viele der bisher getesteten Systeme basieren auf einer Client/Server Struktur und/oder nutzen zentrale Datenbanken zur Verwaltung der Clients. Dies ist mir zu unflexibel.

Ansible ist anders: Voraussetzung auf dem Client sind SSH Zugriff und ein installiertes Python. Das finde ich sogar auf Vyos-, Ubiquiti- und Junos Routern vor :-)

etckeeper versioniert /etc eigenständig als git Repository und pusht auf Wunsch auch periodisch die Änderungen auf einen GitLab Server. Und per Ansible wird das ganze mit möglichst wenig manuellem Aufwand auf die vorhandenen Linuxserver ausgerollt.

Hier eine Schritt für Schritt Anleitung, wie man dieses Setup erhält.

(Viele Beispiele sind von http://docs.ansible.com übernommen)

Die genutzten Tools

Voraussetzungen

  • Installation von Ansible, wie in der Dokumentation beschrieben.
  • Adminsitrativer SSH Zugriff auf die zu verwaltenden Maschinen
    • als root
    • oder per sudo
  • Python auf den zu verwaltenden Maschinen

Konfiguration

Sobald Ansible installiert ist (pip install ansible), legen wir eine hosts Datei an:

192.0.2.50
aserver.example.org
bserver.example.org

Diese kann auch in Kategorien unterteilt werden:

[lokal]
192.0.2.50

[Webserver]
aserver.example.org
bserver.example.org

Die hosts Datei wird von Ansible in /etc/ansible/hosts erwartet. Da ich dies auf meinem Desktop als unpraktisch empfinde, erstellte ich mir einen Ordner ansible in meinem per Seafile gesyncten Ordner und linkte diesen per sudo ln -s /etc/ansbile ~/Seafile/DevOps/ansible nach /etc/ansible.

Es ist zwar lustig anzusehen, aber äußerst unpraktisch im Tagesgeschäft, daß Ansible per default (und sofern installiert) cowsay für die Tasknamen nutzt. Möchte man dies nicht, schaltet man es im Environment oder per .profile hiermit ab: export ANSIBLE_NOCOWS=1.

Erster Start

Hier ein paar demonstrative Aufrufe aus der offiziellen Doku:

# as bruce
ansible all -m ping -u bruce
# as bruce, sudoing to root
ansible all -m ping -u bruce --sudo
# as bruce, sudoing to batman
ansible all -m ping -u bruce --sudo --sudo-user batman

# With latest version of ansible `sudo` is deprecated so use become
# as bruce, sudoing to root
ansible all -m ping -u bruce -b
# as bruce, sudoing to batman
ansible all -m ping -u bruce -b --become-user batman

ansible all -a "/bin/echo hello"

Erweiterte Definintion von Hosts

Ein Eintrag wie dieser:

jumper ansible_port=5555 ansible_host=192.0.2.50 ansible_user=root

definiert, daß man einen Host unter dem Namen jumper auf Port 5555 der IP 192.168.0.2.50 mit dem Benutzernamen root anspricht.

Definition von Playbooks

Um die Automatisierung so nennen zu dürfen, definiert man in Playbooks Ketten von Abläufen, die dann ausgeführt werden.

zsh und oh-my-zsh installer (beta)

Um später auf den Maschinen manierlich schaffen zu können, schiebe ich hier erstmal ein Playbook ein, das einem auf den Targethosts zsh installiert, zur Default Shell macht und sie sinnvoll konfiguriert per oh-my-zsh.

Das Playbook liegt bei mir in einem Unterordner roles und sieht folgendermaßen aus:

---
# - hosts: Webserver
- hosts: '{{ target }}'
  tasks:
   - name: Check if vim is installed
     stat: path=/usr/bin/vim.basic
     register: vim_bin
   - name: Installiere vim
     apt: pkg=vim state=installed update_cache=true
     when: not vim_bin.stat.exists
   - name: Setze vim als default editor
     shell: update-alternatives --set editor /usr/bin/vim.basic
   - name: Check if zsh is installed
     stat: path=/usr/bin/zsh
     register: zsh_bin
   - name: Install zsh
     apt: pkg=zsh state=installed update_cache=true
     when: not zsh_bin.stat.exists
   - name: Check if zsh is installed
     stat: path=/usr/bin/zsh
     register: zsh_bin
   - name: Set zsh as default Shell for User
     shell: chsh -s $(which zsh)
     when: zsh_bin.stat.exists
   - name: Check if git is installed
     stat: path=/usr/bin/git
     register: git_bin
   - name: Install git
     apt: pkg=git state=installed update_cache=true
     when: not git_bin.stat.exists
   - name: Check if curl is installed
     stat: path=/usr/bin/curl
     register: curl_bin
   - name: Install curl
     apt: pkg=curl state=installed update_cache=true
     when: not curl_bin.stat.exists
   - name: Install oh-my-zsh
     shell: sh -c "$(curl -fsSL https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"
     when: zsh_bin.stat.exists
   - name: done
     debug: msg="done."

Aufgerufen wird das Playbook mit dem Kommando:

ansible-playbook roles/systemtools.yml --extra-vars "target=jumper"

Inhaltlich sollte das Playbook selbsterklärend sein, die hosts Zeilen definieren (auskommentiert) "Wende dies auf alle Hosts der Gruppe oder des Namens Webserver an" bzw. Wende dies auf alle Hosts mit dem Namen oder der Gruppe Variable Target an.

Bei Erfolg sieht das ganze dann so aus:

cm@cmmini > ~/ansible > $ ansible-playbook roles/zsh.yml --extra-vars "target=rtm-pi"

PLAY [rtm-pi] ******************************************************

TASK [setup] *******************************************************
ok: [rtm-pi]

TASK [Check if zsh is installed] ***********************************
ok: [rtm-pi]

TASK [Install zsh] *************************************************
changed: [rtm-pi]

TASK [Check if zsh is installed] ***********************************
ok: [rtm-pi]

TASK [Set zsh as default Shell for User] ***************************
changed: [rtm-pi]

TASK [Check if git is installed] ***********************************
ok: [rtm-pi]

TASK [Install git] *************************************************
skipping: [rtm-pi]

TASK [Check if curl is installed] **********************************
ok: [rtm-pi]

TASK [Install curl] ************************************************
skipping: [rtm-pi]

TASK [Install oh-my-zsh] *******************************************
changed: [rtm-pi]

TASK [done] ********************************************************
ok: [rtm-pi] => {
    "msg": "done."
}

PLAY RECAP *********************************************************
rtm-pi                     : ok=9    changed=3    unreachable=0    failed=0

Morgen wird dieser Beitrag dann um die etckeeper und GitLab Konfiguration erweitert.

... to be continued

Kommentare / Diskussion: