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
- als
- 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 Ordneransible
in meinem per Seafile gesyncten Ordner und linkte diesen persudo 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