Laissez-faire-Flair mit Ansible
Mit dem Open Source Softwarepaket Ansible kann man sehr gut mehrere Server gleichzeitig bedienen. Dabei gibt man nicht, wie sonst üblich, konkrete Befehle aus, die ausgeführt werden, sondern man gibt nur den Zielzustand vor und Ansible macht den Rest. Ich habe mich schon länger dafür interessiert, aber noch nicht die Zeit gefunden mich damit auseinander zu setzen. Bis jetzt.
Ansible Minimalsetup
Um mit Ansible beginnen zu können, braucht es nicht viel. Ein Linuxrechner mit dem Paket Ansible und Python3 genügen. Auf den Zielrechnern braucht es nur einen SSH-Zugang für Ansible (und auch Python3, wenn ich mich nicht täusche, aber das war bis jetzt überall installiert).
Im Projektordner erstellt man die Datei namens ansible.cfg
mit folgendem Inhalt:
[defaults]
private_key_file = /home/username/.ssh/id_ed25519
inventory = ./inventory/hosts
Hier wird der öffentliche SSH-Schlüssel referenziert. Das wird noch wichtig. Hier sieht man wie das geht. LearnLinuxTV hat auch ein Video zu SSH-Keys und Ansible. Seine Ansible Serie ist überhaupt sehr empfehlenswert.
Der nächste Punkt das sog. “Inventory” (hier einfach “hosts” genannt) legt die einzelnen Maschinen und ihre Gruppenmitgliedschaft fest:
[debian]
192.168.0.46
192.168.0.47
192.168.0.48
Hier einfach ein paar Debian VMs, das Inventory kann so einfach oder komplex (mit dynamischer Befüllung!) sein, wie man möchte.
Damit kann man eigentlich schon loslegen und mit sog. “Ad-Hoc-Befehlen” sein Unwesen treiben. Hier ein einfacher Ad-Hoc-Befehl für einen Ping:
ansible -i ./inventory/hosts debian -m ping -u root
Anschließend braucht es noch eine Anleitung, das “Playbook”. In diesem Fall für ein Update von allen Maschinen in der Gruppe debian
:
- hosts: debian
become: yes
tasks:
- name: Ensure up-to-date Cache and Upgrade
apt:
update_cache: yes
upgrade: 'yes'
So schaut es aus:
Befehl zum Ausführen des Playbooks:
ansible-playbook ./playbooks/apt.yml -i ./inventory/hosts -u root
Und so das Playbook:
Und jetzt gleich einen großen Schritt weiter, ein GPT-4o-kreiertes Playbook, welches einen User ansible
erstellt, diesen einrichtet (passwordless sudo etc) und SSH-Keys für den Zugriff abspeichert:
---
- name: Ensure ansible user exists with SSH key, passwordless sudo, and a nice environment
hosts: debian
become: yes
tasks:
# Step 1: Ensure sudo is installed
- name: Ensure sudo is installed
ansible.builtin.package:
name: sudo
state: present
# Step 2: Ensure the ansible user is present
- name: Ensure the 'ansible' user exists
ansible.builtin.user:
name: ansible
state: present
shell: /bin/bash
# Step 3: Ensure the .ssh directory exists for the ansible user
- name: Ensure .ssh directory exists for ansible user
ansible.builtin.file:
path: /home/ansible/.ssh
state: directory
owner: ansible
group: ansible
mode: '0700'
# Step 4: Add SSH public key for ansible user (simple overwrite)
- name: Copy SSH public key for ansible user
ansible.builtin.copy:
src: /home/mf/.ssh/id_ed25519.pub
dest: /home/ansible/.ssh/authorized_keys
owner: ansible
group: ansible
mode: '0600'
# Step 5: Ensure passwordless sudo for ansible user
- name: Ensure ansible user has passwordless sudo access
ansible.builtin.copy:
dest: /etc/sudoers.d/ansible
content: |
ansible ALL=(ALL) NOPASSWD: ALL
owner: root
group: root
mode: '0440'
# Step 6: Ensure a nice default environment (.bashrc)
- name: Ensure a nice default .bashrc for ansible user
ansible.builtin.copy:
dest: /home/ansible/.bashrc
content: |
# ~/.bashrc file for ansible user
export PATH=$PATH:/usr/local/bin
alias ll='ls -la'
alias grep='grep --color=auto'
export EDITOR=vim
owner: ansible
group: ansible
mode: '0644'
# Step 7: Ensure enhanced shell environment and source .bashrc in .bash_profile
- name: Ensure enhanced shell environment for ansible user
ansible.builtin.copy:
dest: /home/ansible/.bash_profile
content: |
# ~/.bash_profile for ansible user
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
PS1='\u@\h:\w\$ '
HISTSIZE=1000
HISTFILESIZE=2000
owner: ansible
group: ansible
mode: '0644'
Und so führt man das Playbook aus:
ansible-playbook ./playbooks/user-setup.yml -i ./inventory/hosts -u root
Und das ist das Ergebnis:
und mit der Einrichtung von .bashrc
und der User Umgebung:
Playbook mit Update, Programmen und Zeit:
Damit es nicht so leer ist in den Containern ein paar zusätzliche Programme und Überprüfung, ob eh die Uhrzeit synchronisiert wird:
---
- hosts: all
become: yes
tasks:
- name: Update all packages
apt:
update_cache: yes
upgrade: dist
- name: Install common utilities
apt:
name:
- vim
- curl
- htop
- btop
state: present
- name: Ensure system time is synchronized
apt:
name: systemd-timesyncd
state: present
Befehl zum Ausführen:
ansible-playbook ./playbooks/program-setup.yml -i ./inventory/hosts -u ansible
Ergebnis:
Fazit
Ansible gefällt mir gut. Die Lernkurve ist nicht niedrig, aber auch nicht zu steil und man kommt schnell zu Ergebnissen. Vor allem die Aspekte der Reproduzierbarkeit sagen mir sehr zu. Das werde ich in Zukunft weiter verfolgen. Zum Beispiel im Folgebeitrag.