Strukturen, Playbooks, Vaults - so habe ich es gemacht
Prolog
Ich möchte meine Erfahrungen mit Ansible mit euch teilen und werde hier mal aufführen wie ich Ansible auf meinem Lernweg aufbaue. Bedenkt aber stets, dass ich gerade erst mit Ansible anfange und vorher noch nie etwas mit zentralem Konfigurationsmanagement zu tun hatte. Ich zeige euch hier lediglich meine Überlegungen, die wahrscheinlich hier und da noch verbessert werden müssten. Ein Nachbauen macht ihr immer auf eigene Gefahr hin.
Vorraussetzungen - Ansible Eigenheiten
Was solltet ihr beachten bzw. vorausschauend planen, wenn ihr Ansible einsetzen wollt?
Benutzer für zentrale Verwaltungsaufgaben
Das Arbeiten mit Ansible wird euch viel einfacher fallen, wenn ihr einen einzigen Benutzer auf allen euren Hosts angelegt habt und dieser SUDO Rechte hat. Dann könnt ihr euer Ansible Management einheitlich aufbauen und habt nicht zig verschiedene User, die ihr berücksichtigen müsst.
Ja, das ist sicherlich Geschmackssache und in manchen Situationen im Bezug auf Sicherheit sollte man das abwandeln und auf mehrere spezifische Benutzer zurückgreifen.
Ordnerstruktur
Ansible Docs: https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html#directory-layout
Von Ansible wird keine Struktur vorgegeben. Man hat also die freie Entscheidungsgewalt. So habe ich also das hier angefangen zu strukturieren:
root@server:/etc/ansible# tree
.
├── ansible.cfg
├── archive
│ ├── azure.bak
│ ├── configure-linuxserver-rsyslog-to-graylog.yml.alt
│ ├── hosts.bak
│ └── install-prometheus-node-exporter.yml.bak
├── azure
├── group_vars
│ ├── production
│ │ ├── vars
│ │ └── vault
│ ├── init-linuxserver
│ │ ├── vars
│ │ └── vault
│ └── linuxserver
│ ├── vars
│ └── vault
├── playbooks
│ ├── packages
│ │ ├── install-production-prometheus-node-exporter.yml
│ │ ├── install-prometheus-node-exporter.yml
│ │ └── install-systemtools.yml
│ ├── services
│ │ └── connect-graylog.yml
│ ├── systemsettings
│ │ ├── set-timezone-europe-berlin.yml
│ │ └── update-hosts-file.yml
│ └── users
│ └── create-user-webdata.yml
└── vault_pwd
Inventory
Ansible Docs: https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html
Meine Inventory Datei heißt azure, weil ich Ansible im Zuge einer Azure Evaluierung einsetze.
root@vm-azure-manager:/etc/ansible# cat azure
# This is the default ansible 'hosts' file.
#
# It should live in /etc/ansible/hosts
#
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups
#Here i was experimenting where do set this option for being applied everywhere.
#ansible_ssh_common_args='-o StrictHostKeyChecking=no'
[prometheus]
prometheus-01
[grafana]
grafana-01
[graylog]
graylog-01
[es-nodes]
es-node-01
[prod-es-nodes]
prod-es00
[prod-hcmongos]
prod-hcmongo
[prod-parsmongos]
prod-parsmongo
[prod-dockers]
prod-docker
[prod-postgres]
prod-postgres
[prod-rabbits]
prod-rabbit
[prod:children]
prod-es-nodes
prod-hcmongos
prod-dockers
prod-parsmongos
prod-postgres
prod-rabbits
[init-linuxserver:children]
prometheus
grafana
graylog
es-nodes
[linuxserver:children]
prometheus
grafana
graylog
es-nodes
[graylogclients:children]
grafana
prometheus
es-nodes
Bisher habe ich folgendes gemeistert:
- Einstellungen in separate Unterverzeichnisse zu kapseln und Gruppen bezogen Einstellungen zu vergeben
- Hosts in Gruppen zu unterteilen
- Gruppen zu verschachteln
Durch die Verschachtelung von Gruppen kann ich meine Hosts kategorisieren und habe eine ähnliche Vorangehensweise wie beim Administrieren von Benutzerrechten, d.h. bei Änderungen den Aufwand zu minimieren, weil man z.B. einen neuen Host nur noch einer Gruppe zuweist oder einen alten aus einer Gruppe löschen muss.
Ansible Vault
Ansible Docs: https://docs.ansible.com/ansible/latest/user_guide/vault.html
Ich am Anfang die Passwörter für meine User, die Ansible benutzen sollte, klar lesbar in meine Konfig-Dateien geschrieben. Da ich davon aber absolut kein Freund bin, habe ich mich also zeitnah darum gekümmert und herausgefunden, dass es die sog. Ansible-Vault gibt. Vault heißt Tresor. Also ein verschlüsselter Container, der eure Passwärter und sonstige Einstellungen beinhalten kann. Ich habe aktuell nur ein Passwort darin gespeichert.
Wie ihr schon anhand meiner Ordnerstruktur gesehen habt, gibt es jeweils in jedem Unterordner einer Gruppe eine Datei namens "vault". Das sind meine geschützten Bereiche für die jeweilige Gruppe.
So hier habe ich es gemacht:
- Eine Schlüsseldatei "vault_password_file" erstellt und in Klartext den Schlüssel eingetragen, der global zum Ver- und Entschlüsseln benutzt werden soll.
Man muss keinen globalen Schlüssel verwenden. Das kann man so einstellen wie man es möchte.
root@server:# nano vault_pwd- Schlüssel eintragen
- Globale Schlüsseldatei in der ansbile.cfg aktiviert
vault_password_file = /etc/ansible/vault_pwd
- zu verschlüsselnde Variablen mit einem Editor in die jeweilige vault Datei eintragen
- vault Datei verschlüsseln:
ansible-vault encrypt vault-
Da wir einen globalen Schlüssel aktiviert haben, wird dieser automatisch zum Verschlüsseln benutzt, sodass ihr keinen Schlüssel an der Stelle eingeben müsst.
- So habe ich z.B. das Passwort hinterlegt, dass benutzt wird um SUDO Rechte zu aktivieren:
-
vault_ansible_become_pass: DAS-PASSWORT- Ansible empfiehlt als Variablennamen der zu verschlüsselnden Variable ein "vault_" als Präfix zu verwenden. Ich finde das gut, da man so gleich den Bezug der Verwendung herstellen kann.
-
-
- Passwort in unverschlüsselter Variable aus verschlüsselter Variable aufrufen
- So sieht der Aufruf dann in meiner "vars" Datei aus:
ansible_become_pass: "{{ vault_ansible_become_pass }}" - Die Syntax nennt sich jinja2
- So sieht der Aufruf dann in meiner "vars" Datei aus:
Alles was ich jetzt mit Ansible mache, funktioniert mit verschlüsselten Passwörtern.
Playbooks
Ansible Docs: https://docs.ansible.com/ansible/latest/user_guide/playbooks.html
Ansible-Systembenutzer bereitstellen
Funktionen
- User mit Home Verzeichnis anlegen
- SSH Key hinterlegen
- SUDO Rechte vergeben
Probleme
Man benötigt natürlich auf allen Hosts für das erstmalige Bereitstellen mit Ansible einen Systemuser mit SUDO Rechten. Da ich für Ansible Arbeiten einen eigenen Systemuser nutzen möchte, habe ich als erstes einen neuen user auf allen Hosts angelegt. Dafür habe ich den User benutzt, den man mit der Installation von Debian anlegen muss.
Playbook "create-user-ansibleadmin.yml
root@server:/etc/ansible# cat playbooks/users/create-user-ansibleadmin.yml
---
- hosts: init-linuxserver
remote_user: initial-user-from-fresh-install-with-sudo-rights
become: yes
become_method: sudo
become_user: root
tasks:
- name: Ansible create user ansibleadmin with home directory
user:
name: ansibleadmin
createhome: yes
- name: create directory .ssh
file:
path: /home/ansibleadmin/.ssh
state: directory
owner: ansibleadmin
group: ansibleadmin
mode: 0700
- name: Ansible copy the ssh public key of the user ansibleadmin to the remote host
copy:
src: "/home/ansibleadmin/.ssh/id_rsa.pub"
dest: "/home/ansibleadmin/.ssh/authorized_keys"
owner: ansibleadmin
group: ansibleadmin
- name: Add user ansibleadmin to sudo group and grant sudo rights
user:
name: ansibleadmin
groups: sudo
Debian Paket mit apt installieren
Playbook "install-systemtools.yml"
root@server:/etc/ansible# cat playbooks/packages/install-systemtools.yml
---
- hosts: linuxserver
remote_user: ansibleadmin
become: yes
become_method: sudo
become_user: root
tasks:
- name: install lsb-release
apt: name=lsb-release state=present
- name: install lsof
apt: name=lsof state=present
Datei kopieren - hosts Datei bereitstellen
Playbook "update-hosts-file.yml"
root@server:/etc/ansible# cat playbooks/systemsettings/update-hosts-file.yml
---
- hosts: linuxserver
remote_user: ansibleadmin
become: yes
become_method: sudo
become_user: root
tasks:
- name: copy the hosts file from host "server" to the group linuxserver
copy:
src: "/etc/hosts"
dest: "/etc/hosts"
owner: root
group: root
Hintergrund
Ich arbeite in meiner testumgebung mit den Hosts Dateien, weil ich auf die Schnelle kein DNS aufbauen konnte. Zum Einen bin ich kein Experte für DNS (erst einmal damit rumprobiert) und Zweitens wollte ich so schnell wie möglich alle Hosts mit Namen anstelle von IP Adressen ansprechen.
Zeitzone einstellen
Playbook "set-timezone-europe-berlin.yml"
root@server:/etc/ansible# cat playbooks/systemsettings/set-timezone-europe-berlin.yml
---
- hosts: linuxserver
remote_user: ansibleadmin
become: yes
become_method: sudo
become_user: root
tasks:
- name: set timezone to Europe/Berlin
timezone:
name: Europe/Berlin
Hintergrund
Da ich die Debian VMs in Azure über den RessourcenManager von Azure bereitstellen lassen habe, gab es nachträglich Einstellungen, die angepasst werden mussten. DarunterDazu fielgehörte u.a. die Zeitzone.