Modul 10 — Infrastructure as Code

50. Ansible základy: inventáře, playbooky, moduly

Jak Ansible bez agenta konfiguruje vzdálené servery přes SSH — inventáře cílových strojů, playbooky s úkoly a vestavěné moduly.

Odhadovaná délka studia: 55 minut · Stav: nehotovo

Technologie: Ansible

Úvod a kontext

Terraform z předchozích lekcí vytváří samotnou infrastrukturu — virtuální
servery, sítě. Jakmile server existuje, je potřeba ho nakonfigurovat:
nainstalovat balíčky, nahrát konfigurační soubory, spustit služby.
Tuto vrstvu typicky řeší Ansible — open-source nástroj pro
konfigurační management a automatizaci, který na rozdíl od některých
konkurentů (Chef, Puppet) nevyžaduje instalaci žádného agenta na
spravovaném serveru, jen funkční SSH přístup.

Teorie

Bezagentová (agentless) architektura

Ansible se spouští z jednoho řídicího stroje (control node) — vašeho
počítače nebo CI runneru — a připojuje se ke spravovaným serverům přes
běžný SSH (u Windows přes WinRM). Na cílovém serveru nemusí běžet žádný
trvalý proces ani nainstalovaný agent — Ansible při běhu nahraje malý
Python skript, provede úkol a skript zase smaže. To zjednodušuje provoz
(o nic navíc se nemusí starat na spravovaných strojích) a snižuje
bezpečnostní plochu (žádný trvale běžící agent s vlastními právy).

Inventář

Inventář je seznam serverů, které Ansible spravuje, volitelně
seskupených do logických skupin. Nejjednodušší forma je statický
soubor INI:

# inventory.ini
[webservers]
web1.example.cz ansible_host=10.0.1.10
web2.example.cz ansible_host=10.0.1.11

[databases]
db1.example.cz ansible_host=10.0.2.10

[production:children]
webservers
databases

Stejný inventář lze zapsat i jako YAML, což se lépe kombinuje
s proměnnými:

# inventory.yml
all:
  children:
    webservers:
      hosts:
        web1.example.cz:
          ansible_host: 10.0.1.10
        web2.example.cz:
          ansible_host: 10.0.1.11
    databases:
      hosts:
        db1.example.cz:
          ansible_host: 10.0.2.10

V cloudovém prostředí se často používá dynamický inventář — skript
nebo plugin, který seznam serverů zjistí za běhu dotazem na cloudové API
(např. plugin amazon.aws.aws_ec2 vrátí všechny EC2 instance podle
tagů), takže inventář nemusí být ručně udržovaný soubor.

Ad-hoc příkazy

Pro jednorázové úkoly (bez psaní celého playbooku) slouží ad-hoc
příkazy:

# zjistit, zda jsou všechny servery dostupné
ansible webservers -i inventory.ini -m ping

# restartovat službu nginx na všech webserverech
ansible webservers -i inventory.ini -m service -a "name=nginx state=restarted" --become

-m volí modul (zde ping, resp. service), -a předává argumenty
modulu, --become požaduje eskalaci práv (obdoba sudo) na cílovém
serveru.

Playbooky

Playbook je YAML soubor popisující sadu úkolů (tasks), které se mají
provést na vybraných serverech — obdoba skriptu, ale deklarativní
(úkoly popisují požadovaný stav, ne přesné kroky):

# playbook.yml
---
- name: Nastavení webového serveru
  hosts: webservers
  become: true
  vars:
    nginx_port: 80

  tasks:
    - name: Nainstalovat balíček nginx
      apt:
        name: nginx
        state: present
        update_cache: true

    - name: Nahrát vlastní konfigurační soubor
      template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/sites-available/default
      notify: Restartovat nginx

    - name: Zajistit, že nginx běží a je povolený při startu
      service:
        name: nginx
        state: started
        enabled: true

  handlers:
    - name: Restartovat nginx
      service:
        name: nginx
        state: restarted

Spuštění:

ansible-playbook -i inventory.ini playbook.yml

Klíčové koncepty v playbooku

  • hosts — na kterou skupinu (nebo hosta) z inventáře se úkoly
    aplikují,
  • tasks — seznam úkolů, každý volá jeden modul (viz níže),
  • vars — proměnné dostupné uvnitř playbooku,
  • handlers — úkoly spouštěné jen jako reakce na notify z jiného
    tasku (typicky restart služby po změně konfigurace) — a jen pokud ten
    task skutečně provedl změnu, ne při každém běhu.

Moduly

Modul je jednotka funkčnosti, kterou task volá — Ansible jich má
v jádru i komunitních kolekcích tisíce, pro balíčky (apt, yum),
soubory (copy, template, file), služby (service, systemd),
cloudové zdroje, Docker, Kubernetes a další. Naprostá většina
oficiálních modulů je navržena jako idempotentní — modul nejdřív
zjistí aktuální stav a provede změnu jen tehdy, když se liší od
požadovaného (podrobněji v příští lekci).

Praktický příklad

Kompletní minimální projekt s inventářem a playbookem, který zajistí
běžící webový server:

projekt/
├── inventory.ini
├── playbook.yml
└── templates/
    └── nginx.conf.j2
# inventory.ini
[webservers]
web1.example.cz
{# templates/nginx.conf.j2 #}
server {
    listen {{ nginx_port }};
    server_name _;
    root /var/www/html;
}

Spuštění s ověřením před skutečnou změnou (tzv. dry-run):

# náhled, co by se změnilo, bez skutečného zásahu
ansible-playbook -i inventory.ini playbook.yml --check --diff

# skutečné spuštění
ansible-playbook -i inventory.ini playbook.yml

PLAY [Nastavení webového serveru] *************************************
TASK [Nainstalovat balíček nginx] ***************************************
changed: [web1.example.cz]
TASK [Nahrát vlastní konfigurační soubor] *******************************
changed: [web1.example.cz]
TASK [Zajistit, že nginx běží a je povolený při startu] ******************
ok: [web1.example.cz]
RUNNING HANDLER [Restartovat nginx] *************************************
changed: [web1.example.cz]

PLAY RECAP ****************************************************************
web1.example.cz : ok=4 changed=3 unreachable=0 failed=0

Řádek PLAY RECAP shrnuje, kolik úkolů proběhlo beze změny (ok) a
kolik skutečně něco změnilo (changed) — při opakovaném spuštění by
ideálně všechny úkoly skončily jako ok, protože server už je
v požadovaném stavu (viz idempotence v příští lekci).

Shrnutí

Ansible spravuje konfiguraci vzdálených serverů bez nutnosti agenta,
jen přes SSH. Inventář definuje, které servery spravuje a jak jsou
seskupené, playbook popisuje v YAML sadu úkolů (tasků), z nichž
každý volá konkrétní modul (např. apt, template, service).
handlers reagují na notify a spouští se jen při skutečné změně.
Volba --check --diff umožňuje bezpečný náhled před ostrým spuštěním.

Kontrolní otázky

  1. Jaký je zásadní architektonický rozdíl mezi Ansible a nástroji jako
    Chef nebo Puppet, které vyžadují agenta?
  2. K čemu slouží handlers a čím se liší od běžných tasks?
  3. Co dělá přepínač --check --diff u ansible-playbook a kdy byste
    ho použili?
  4. Mini cvičení: napište krátký task, který pomocí modulu copy
    nahraje soubor app.conf z lokálního adresáře files/ do
    /etc/app/app.conf na cílovém serveru.

Lekce na sebe nejsou zamčené — libovolnou lekci můžete otevřít i označit jako hotovou v jakémkoliv pořadí.