Blog JSystems - uwalniamy wiedzę!

Szukaj
Animacja: Ansible z jednego węzła sterującego konfiguruje wiele serwerów przez SSH, bez agenta
Ansible w pigułce: jeden węzeł sterujący wypycha konfigurację na wiele serwerów naraz, a na tych serwerach nie instalujesz żadnego dodatkowego oprogramowania.

Wyobraź sobie, że masz postawić dziesięć identycznych serwerów WWW. Logujesz się przez SSH na pierwszy, instalujesz nginx, wgrywasz konfigurację, zakładasz konto, uruchamiasz usługę. Potem to samo na drugim. I na trzecim. Po piątym mylisz się w jednym poleceniu i nagle serwery przestają być identyczne. Właśnie ten problem rozwiązuje Ansible.

W tym artykule wyjaśnimy od zera, czym Ansible jest i jak działa. Nie na slajdach, tylko na działającym labie: postawiliśmy węzeł sterujący i cztery serwery, a wszystkie zrzuty poniżej to prawdziwe wyjścia poleceń z tego środowiska. Zobaczysz playbook w akcji, zrozumiesz idempotencję i dowiesz się, dlaczego model bez agenta zrobił z Ansible ulubione narzędzie administratorów.

Czym jest Ansible

Ansible to narzędzie do automatyzacji konfiguracji serwerów i wdrożeń. Zamiast ręcznie klikać i wpisywać polecenia na każdej maszynie z osobna, opisujesz stan docelowy w czytelnym pliku tekstowym, a Ansible sam doprowadza do niego wszystkie wskazane serwery. Powiesz mu: „na tych dziesięciu hostach ma być zainstalowany nginx, ma działać i ma mieć taką konfigurację”, a on wykona to na wszystkich naraz.

Ansible powstał w 2012 roku, dziś rozwija go Red Hat i jest jednym z najpopularniejszych narzędzi w świecie DevOps. Jego siła bierze się z prostoty: konfigurację zapisujesz w formacie YAML, który czyta się niemal jak zwykłą listę kroków po polsku, a do działania nie potrzebujesz niczego poza SSH i Pythonem.

Infografika sześciu elementów Ansible: inventory, moduły, playbook, zmienne i Jinja2, role, Vault
Cały Ansible opiera się na kilku prostych pojęciach. Przejdziemy przez nie po kolei, pokazując każde na żywym przykładzie.

Problem, który rozwiązuje

Ręczna administracja nie skaluje się. Trzy serwery jeszcze ogarniesz, ale przy trzydziestu pojawiają się dwa problemy. Po pierwsze czas: ta sama czynność powtórzona trzydzieści razy to godziny pracy. Po drugie rozjazd konfiguracji: prędzej czy później któryś serwer dostanie inną wersję pakietu albo inny wpis w konfiguracji, i zaczyna zachowywać się inaczej niż reszta. Ansible zamyka opis serwera w pliku, który trzymasz w repozytorium razem z kodem - dzięki temu konfiguracja jest powtarzalna, wersjonowana i taka sama na każdej maszynie. Skoro konfiguracja żyje w repozytorium, warto znać podstawy kontroli wersji - jeśli dopiero zaczynasz, zajrzyj do przewodnika czym jest Git i jak z niego korzystać. Ansible często łączy się też z narzędziami do zarządzania infrastrukturą jako kodem, takimi jak Terraform, i z podejściem GitOps - pokazaliśmy taki tandem w artykule o agencie AI, który stawia maszyny Terraformem i pilnuje GitOps.

Agentless, czyli bez agenta na serwerach

Najważniejsza cecha Ansible kryje się w słowie agentless (bez agenta). Na zarządzanych serwerach nie instalujesz żadnego oprogramowania Ansible - żadnej usługi, żadnego demona działającego w tle. Ansible siedzi tylko na jednej maszynie, tak zwanym węźle sterującym (może nim być Twój laptop), i łączy się z serwerami przez zwykłe SSH. Wykorzystuje to, co i tak jest na każdym Linuksie: połączenie SSH i interpreter Pythona.

Porównanie Ansible (agentless, model push) z Puppet i Chef (agent na hoście, model pull)
Ansible wypycha konfigurację z węzła sterującego (model push). Starsze narzędzia, jak Puppet i Chef, wymagają agenta na każdym hoście, który sam odpytuje serwer centralny (model pull).

To ogromne uproszczenie. W modelu z agentem (jak w starszych Puppet czy Chef) na każdym serwerze musisz zainstalować i utrzymywać program, który cyklicznie pyta serwer centralny o konfigurację. To kolejna rzecz do zainstalowania, zabezpieczenia i naprawiania, gdy się zepsuje. Ansible tego nie potrzebuje: model push oznacza, że to węzeł sterujący sam wypycha zmiany na serwery wtedy, kiedy Ty o to poprosisz. Start jest banalny - o czym za chwilę.

Pierwszy kontakt: instalacja, inventory i polecenia ad-hoc

Instalacja sprowadza się do jednego polecenia. Ansible to paczka Pythona, więc instalujemy go menedżerem pakietów pip:

python3 -m pip install ansible
ansible --version
Zrzut terminala z wynikiem polecenia ansible --version pokazujący Ansible core w wersji 2.17
Po instalacji sprawdzamy wersję. To całe przygotowanie węzła sterującego - reszta to już praca.

Inventory - lista serwerów

Ansible musi wiedzieć, czym ma zarządzać. Tę listę nazywamy inventory. To zwykły plik tekstowy, w którym grupujemy serwery - na przykład osobno serwery WWW, osobno bazy danych. Grupy pozwalają potem powiedzieć „zrób to tylko na serwerach WWW”:

# inventory.ini - lista zarzadzanych hostow
[web]
web1
web2
web3

[db]
db1

[serwery:children]
web
db
Zrzut terminala z drzewem inventory Ansible: grupa serwery z podgrupami web i db oraz hostami
Polecenie ansible-inventory --graph pokazuje inventory jako drzewo grup. Widać grupę serwery z podgrupami web (web1, web2, web3) i db (db1).

Polecenia ad-hoc - szybkie zadania bez pliku

Zanim napiszemy pełny scenariusz, możemy odpalać pojedyncze zadania jednym poleceniem. Nazywamy je ad-hoc (doraźnymi). Klasyczny pierwszy kontakt to ping - sprawdzenie, czy Ansible dogada się ze wszystkimi hostami:

ansible serwery -m ping
Zrzut terminala z wynikiem ansible -m ping: wszystkie hosty odpowiadają SUCCESS i pong
Każdy host odpowiada zielonym SUCCESS i „pong”. To potwierdza, że węzeł sterujący ma połączenie SSH i Pythona na wszystkich serwerach.

Tak samo uruchomimy dowolne polecenie systemowe na całej grupie naraz. Tu pytamy serwery WWW o czas działania, a przy okazji sprawdzamy, że nginx jeszcze nie jest zainstalowany - zaraz to zmienimy playbookiem:

ansible web -m command -a "uptime"
Zrzut terminala z poleceniami ad-hoc Ansible: uptime na serwerach web oraz nieudane nginx -v przed instalacją
Polecenia ad-hoc wykonują się na wszystkich serwerach WWW jednocześnie. Widać, że nginx jeszcze nie istnieje (błąd na czerwono) - to nasz punkt wyjścia.

Polecenia ad-hoc i inventory to dopiero rozgrzewka. Jeśli chcesz nauczyć się pisać kompletne playbooki, składać z nich role wielokrotnego użytku i wdrażać całe środowiska od zera, pokażemy Ci to na praktycznych warsztatach. Szkolenie Ansible: automatyzacja zadań w praktyce ma terminy gwarantowane.

Playbook - serce Ansible

Polecenia ad-hoc są wygodne do drobiazgów, ale prawdziwa moc Ansible to playbook: plik YAML, w którym opisujemy cały scenariusz konfiguracji. Playbook to lista zadań (tasks), wykonywanych po kolei na wskazanych hostach. Każde zadanie używa jakiegoś modułu - gotowego klocka, który wie, jak coś zrobić. Modułowi mówisz, jaki ma być efekt („nginx ma być zainstalowany”), a on martwi się, jak to osiągnąć na danym systemie.

Oto kompletny playbook, który stawia serwer WWW na wszystkich hostach z grupy web - instaluje nginx, zakłada konto, wgrywa stronę z szablonu, poprawia wpis w konfiguracji, uruchamia usługę i sprawdza, czy odpowiada:

---
# site.yml - postaw serwer WWW nginx na wszystkich hostach z grupy [web]
- name: Konfiguracja serwerow WWW
  hosts: web
  gather_facts: true
  vars:
    powitanie: "Ta strona zostala postawiona przez Ansible"
    admin_user: deploy

  tasks:
    - name: Zainstaluj serwer nginx
      ansible.builtin.apt:
        name: nginx
        state: present
        update_cache: true

    - name: Zaloz konto administracyjne
      ansible.builtin.user:
        name: "{{ admin_user }}"
        groups: sudo
        shell: /bin/bash
        state: present

    - name: Wgraj strone startowa z szablonu Jinja2
      ansible.builtin.template:
        src: templates/index.html.j2
        dest: /var/www/html/index.html
        owner: www-data
        mode: "0644"

    - name: Ustaw liczbe procesow roboczych nginx
      ansible.builtin.lineinfile:
        path: /etc/nginx/nginx.conf
        regexp: "^worker_processes"
        line: "worker_processes auto;"

    - name: Uruchom serwer nginx
      ansible.builtin.command: nginx
      args:
        creates: /run/nginx.pid

    - name: Sprawdz odpowiedz serwera WWW
      ansible.builtin.uri:
        url: http://localhost
        return_content: false
      register: odpowiedz

    - name: Pokaz kod odpowiedzi HTTP
      ansible.builtin.debug:
        msg: "Serwer {{ inventory_hostname }} odpowiada kodem HTTP {{ odpowiedz.status }}"

Zwróć uwagę, jak czyta się ten plik: to niemal lista kroków po ludzku. hosts: web mówi „rób to na serwerach WWW”, a każdy - name: to jeden opisany krok. Uruchamiamy całość jednym poleceniem:

ansible-playbook site.yml
Zrzut terminala z pierwszym uruchomieniem playbooka Ansible: zadania changed, PLAY RECAP z changed=4 na trzech serwerach
Playbook w akcji. Ansible wykonuje zadania na trzech serwerach jednocześnie. Na żółto zadania, które coś zmieniły (changed), na zielono te, które już były w porządku (ok). Na dole PLAY RECAP: changed=4 na każdym hoście.

W kolorach kryje się cała logika Ansible. Żółte „changed” to zadania, które faktycznie coś zmieniły na serwerze. Zielone „ok” oznacza, że stan już się zgadzał i nie trzeba było nic robić. Podsumowanie PLAY RECAP na dole zbiera statystyki z każdego hosta - ile zadań się wykonało i ile z nich coś zmieniło.

Efekt jest namacalny. Zadanie z modułem template wygenerowało stronę startową, podstawiając do szablonu prawdziwe dane każdego serwera (nazwę hosta, wersję systemu, adres IP). Podejrzyjmy gotowy plik prosto na serwerze web1 poleceniem cat:

Zrzut terminala z poleceniem cat na pliku index.html serwera web1 - HTML z podstawionymi przez szablon Jinja2 nazwą hosta web1, systemem Debian 12 i adresem IP
Gotowy plik index.html na serwerze web1, podejrzany poleceniem cat. Nazwa hosta, system i adres IP nie są wpisane na sztywno - szablon Jinja2 podstawił je automatycznie z faktów o serwerze.

Widziałeś, jak jeden plik konfiguruje całą flotę serwerów naraz - to codzienność administratora pracującego z Ansible. Chcesz opanować playbooki, zmienne i szablony na tyle, by automatyzować własną infrastrukturę bez zaglądania do dokumentacji co chwilę? Szkolenie Ansible: automatyzacja infrastruktury dla administratorów ma terminy gwarantowane.

Idempotencja - uruchom raz albo sto razy

Dochodzimy do pojęcia, które odróżnia Ansible od zwykłego skryptu. Idempotencja oznacza, że wielokrotne uruchomienie tego samego playbooka daje ten sam efekt co jedno uruchomienie. Ansible najpierw sprawdza stan serwera i zmienia tylko to, co odbiega od opisanego celu. Jeśli wszystko już się zgadza - nie robi nic.

Infografika idempotencji Ansible: pierwsze uruchomienie changed=4, drugie changed=0
Ta sama konfiguracja, dwa uruchomienia. Za pierwszym razem Ansible doprowadza serwer do stanu docelowego (changed=4). Za drugim nie ma już nic do zrobienia (changed=0).

Zobaczmy to na żywo. Uruchamiamy dokładnie to samo polecenie drugi raz, bez żadnych zmian:

ansible-playbook site.yml     # to samo, drugi raz
Zrzut terminala z drugim uruchomieniem playbooka Ansible: wszystkie zadania ok, PLAY RECAP z changed=0
Drugie uruchomienie: wszystkie zadania na zielono (ok), PLAY RECAP pokazuje changed=0. Nginx jest już zainstalowany, strona wgrana, usługa działa - Ansible niczego nie rusza.

To potężna właściwość w praktyce. Playbook możesz odpalać bez obaw ile razy chcesz - jako sposób na sprawdzenie, czy serwery nadal są w prawidłowym stanie, albo po dodaniu jednego nowego zadania. Ansible dołoży tylko brakującą różnicę i nie zepsuje tego, co już działa. Zwykły skrypt shellowy tak nie potrafi - próba drugiej instalacji czy dopisania tej samej linijki zwykle kończy się błędem albo duplikatem.

Animacja ścieżki uruchomienia Ansible: inventory, playbook, moduły, SSH, serwery, PLAY RECAP
Co dzieje się przy jednym uruchomieniu: Ansible bierze inventory i playbook, moduły łączą się przez SSH z serwerami, doprowadzają je do stanu docelowego i zwracają raport zmian.

Fakty, szablony, role i sekrety

Powyższe wystarczy, żeby zrozumieć, czym jest Ansible. Warto jednak poznać jeszcze cztery pojęcia, które spotkasz od razu przy realnej pracy.

Fakty (facts) - Ansible sam bada serwer

Zanim wykona zadania, Ansible zbiera fakty o każdym serwerze: system operacyjny, adresy IP, ilość pamięci, zamontowane dyski i setki innych informacji. Możesz się do nich odwoływać w playbookach - na przykład zainstalować inny pakiet na Debianie, a inny na systemie z rodziny Red Hat. Podejrzyjmy fakty o dystrybucji jednego z serwerów:

ansible web1 -m setup -a "filter=ansible_distribution*"
Zrzut terminala z faktami Ansible o hoście web1: dystrybucja Debian w wersji 12
Fakty o serwerze web1. Ansible sam wykrył, że to Debian 12. Tych danych używamy potem w playbookach i szablonach, żeby jedna konfiguracja działała na różnych systemach.

Szablony Jinja2 - jedna konfiguracja, wiele serwerów

Widziałeś już moduł template w playbooku. Korzysta on z Jinja2 - systemu szablonów, w którym w plik konfiguracyjny wstawiasz miejsca do wypełnienia w podwójnych nawiasach klamrowych. Ansible podstawia tam wartości zmiennych i faktów osobno dla każdego serwera. Dzięki temu jeden szablon obsługuje całą flotę, a każdy host dostaje swoją, właściwą wersję pliku - jak strona z poprzedniego przykładu, gdzie nazwa hosta i adres IP były podstawione automatycznie.

Tak dokładnie wygląda szablon index.html.j2, który wgrywaliśmy w playbooku. Wszystko, co stoi w podwójnych nawiasach klamrowych (podświetlone), to miejsce do wypełnienia - Ansible wstawi tam realną wartość osobno dla każdego serwera:

<!DOCTYPE html>
<html lang="pl">
<head><meta charset="utf-8"><title>{{ inventory_hostname }}</title></head>
<body>
  <h1>{{ powitanie }}</h1>
  <p>Host: {{ inventory_hostname }}</p>
  <p>System: {{ ansible_distribution }} {{ ansible_distribution_version }}</p>
  <p>Adres IP: {{ ansible_default_ipv4.address | default('n/d') }}</p>
</body>
</html>

Widać to od razu, gdy zestawimy szablon z wynikiem z poprzedniej sekcji: {{ inventory_hostname }} zamieniło się w web1, a {{ ansible_default_ipv4.address }} w konkretny adres IP tego serwera. Najlepszy dowód, że dzieje się to osobno dla każdego hosta, to pobrać gotową stronę wprost z innego serwera. Odpytajmy przez HTTP maszynę web2:

Zrzut terminala z pobraniem strony przez curl po HTTP z serwera web2 - HTML z hostem web2 i adresem IP 172.19.0.2 podstawionymi przez ten sam szablon Jinja2
Ta sama konfiguracja, inny serwer. Strona pobrana przez HTTP z web2 ma w treści web2 i jego własny adres IP (172.19.0.2) - a powstała z dokładnie tego samego szablonu Jinja2 co strona web1. To właśnie znaczy „jedna konfiguracja, wiele serwerów”.

Role i Ansible Galaxy - porządek w większych projektach

Gdy playbooków i zadań przybywa, jeden wielki plik YAML robi się nieczytelny. Wtedy dzielimy konfigurację na role. Rola to samodzielny, gotowy do wielokrotnego użytku kawałek automatyzacji - na przykład „postaw serwer WWW” albo „skonfiguruj bazę danych” - w którym zadania, szablony, pliki i zmienne leżą w z góry ustalonych katalogach. Dzięki tej stałej strukturze Ansible sam wie, gdzie czego szukać, a Ty raz napisaną rolę wpinasz potem do dowolnego playbooka jednym wpisem.

Roli nie musisz pisać od zera. Służy do tego osobne narzędzie ansible-galaxy, a stoi za nim Ansible Galaxy - publiczny katalog ról i kolekcji współdzielonych przez społeczność. Tym samym poleceniem pobierzesz gotową rolę z internetu (ansible-galaxy role install autor.nazwa_roli) albo wygenerujesz pusty szkielet własnej:

ansible-galaxy role init webserver

To polecenie niczego nie pobiera z sieci - tworzy lokalnie kompletny szkielet katalogów nowej roli o nazwie webserver, z pustymi plikami main.yml w każdym miejscu, którego Ansible się spodziewa. Zamiast ręcznie zakładać kilkanaście folderów, dostajesz je od razu gotowe do wypełnienia:

Zrzut terminala z poleceniem ansible-galaxy role init webserver i wygenerowaną strukturą katalogów roli: tasks, handlers, templates, files, defaults, vars, meta oraz tests
Polecenie ansible-galaxy role init tworzy gotowy szkielet roli webserver - komplet standardowych katalogów, każdy z pustym plikiem main.yml do wypełnienia.

Każdy katalog w tym szkielecie ma z góry przypisane zadanie:

  • tasks/main.yml - główna lista zadań roli, ta sama, którą wcześniej wpisywaliśmy wprost w playbooku (tu trafiłyby zadania instalujące i konfigurujące nginx).
  • handlers/main.yml - procedury (handlers) uruchamiane tylko wtedy, gdy coś faktycznie się zmieniło, na przykład „przeładuj nginx po zmianie konfiguracji”.
  • templates/ - szablony Jinja2 (pliki .j2), dokładnie takie jak nasz index.html.j2.
  • files/ - gotowe pliki statyczne kopiowane na serwery bez żadnych zmian.
  • defaults/main.yml oraz vars/main.yml - zmienne roli. W defaults trzymasz wartości domyślne, łatwe do nadpisania, a w vars te ważniejsze, o wyższym priorytecie.
  • meta/main.yml - metadane roli i lista innych ról, od których ona zależy.
  • tests/ oraz README.md - przykładowy playbook testowy z własnym inventory i miejsce na dokumentację roli.

Gotową rolę wpinasz do playbooka jednym wpisem roles:, a Ansible sam sięgnie po jej tasks/main.yml:

---
# site.yml - ten sam efekt co wczesniej, ale zadania siedza w roli
- name: Konfiguracja serwerow WWW
  hosts: web
  roles:
    - webserver

Odwrotny scenariusz jest jeszcze wygodniejszy: zamiast pisać rolę samodzielnie, pobierasz gotową i sprawdzoną z Ansible Galaxy. Weźmy popularną rolę geerlingguy.nginx, która potrafi postawić i skonfigurować nginx za nas. Pobieramy ją jednym poleceniem:

ansible-galaxy role install geerlingguy.nginx
Zrzut terminala z pobraniem roli geerlingguy.nginx z Ansible Galaxy - rola ściągnięta z GitHuba i rozpakowana do katalogu ~/.ansible/roles
Ansible Galaxy pobiera rolę geerlingguy.nginx wprost z GitHuba i rozpakowuje ją lokalnie do ~/.ansible/roles. Od tej chwili możesz jej używać w swoich playbookach.

Teraz wystarczy krótki playbook, który stosuje pobraną rolę - bez pisania własnych zadań instalujących nginx:

---
# nginx-galaxy.yml - uzyj gotowej roli pobranej z Ansible Galaxy
- name: Postaw serwer WWW rola z Galaxy
  hosts: web2
  become: true
  roles:
    - geerlingguy.nginx

Uruchamiamy go dokładnie tak samo jak każdy inny playbook:

ansible-playbook nginx-galaxy.yml
Zrzut terminala z uruchomieniem playbooka wykorzystującego rolę geerlingguy.nginx - Ansible instaluje i konfiguruje nginx, PLAY RECAP pokazuje ok=11 changed=3 failed=0
Rola z Galaxy robi całą robotę: instaluje nginx, wgrywa konfigurację i uruchamia usługę. Część jej zadań dotyczy innych systemów niż Debian, więc Ansible je pomija - stąd liczba w polu skipped w podsumowaniu.

Ansible Vault - sekrety w repozytorium

Playbooki i pliki ze zmiennymi trzymasz w repozytorium Git razem z resztą kodu - i słusznie, bo masz wtedy pełną historię zmian. Kłopot w tym, że część danych to sekrety: hasła do baz, klucze API, tokeny. Gdyby leżały w repozytorium otwartym tekstem, zobaczyłby je każdy, kto ma do niego dostęp, a po wycieku repozytorium - praktycznie każdy. Ansible Vault rozwiązuje to, szyfrując sekrety algorytmem AES256 hasłem, które znasz tylko Ty (i Twój serwer automatyzacji). Zaszyfrowane dane spokojnie commitujesz, a Ansible odszyfruje je w pamięci dopiero w chwili uruchomienia playbooka. Przejdźmy przez to krok po kroku.

Krok 1: zaszyfruj pojedynczą wartość

Najczęstszy przypadek to jeden sekret, na przykład hasło do bazy. Zamieniasz go w zaszyfrowany blok poleceniem encrypt_string:

ansible-vault encrypt_string --stdin-name db_password

Co oznaczają poszczególne części polecenia:

  • encrypt_string - tryb szyfrowania pojedynczej wartości, a nie całego pliku.
  • --stdin-name db_password - nazwa zmiennej, pod jaką zapiszesz sekret. Samą wartość sekretu Ansible czyta ze standardowego wejścia - wpisujesz ją w terminalu i kończysz skrótem Ctrl+D.

Po uruchomieniu Ansible poprosi najpierw o hasło Vaulta (dwa razy, drugi raz dla potwierdzenia), potem o samą wartość sekretu, a na końcu wypisze gotowy blok:

Zrzut interaktywnej sesji ansible-vault encrypt_string: dwa pytania o hasło Vaulta (New Vault password i Confirm), wpisana wartość sekretu i wygenerowany zaszyfrowany blok !vault z nagłówkiem ANSIBLE_VAULT AES256
Ansible pyta dwa razy o hasło Vaulta (drugi raz dla potwierdzenia), prosi o wartość sekretu, a potem wypisuje blok !vault. Wklejasz go wprost do pliku ze zmiennymi jako wartość zmiennej db_password i spokojnie commitujesz - bez hasła Vaulta to bezużyteczny ciąg znaków.

Krok 2: albo zaszyfruj cały plik

Gdy sekretów jest więcej, wygodniej trzymać je w jednym pliku i zaszyfrować go w całości. Tworzysz zwykły plik YAML (na przykład sekrety.yml z kluczami db_password i api_key), a potem uruchamiasz:

ansible-vault encrypt sekrety.yml

Polecenie encrypt <plik> szyfruje plik w miejscu - po podaniu hasła cała czytelna treść zamienia się w nagłówek $ANSIBLE_VAULT;1.1;AES256 i blok szesnastkowy. Żeby zajrzeć do środka bez odszyfrowywania pliku na dysk, używasz ansible-vault view:

Zrzut terminala z ansible-vault encrypt i view: zaszyfrowany plik sekrety.yml jako blok AES256 oraz jego odszyfrowany podgląd z db_password i api_key
U góry zaszyfrowany plik sekrety.yml (nieczytelny blok), a pod spodem podgląd poleceniem ansible-vault view - odszyfrowana treść pojawia się dopiero po podaniu hasła i tylko na ekranie.

Krok 3: podglądaj, edytuj i zmieniaj hasło

Na zaszyfrowanym pliku pracujesz kilkoma poleceniami, bez ręcznego odszyfrowywania go na dysk:

  • ansible-vault view sekrety.yml - pokazuje odszyfrowaną treść na ekranie (po podaniu hasła), nigdzie jej nie zapisując.
  • ansible-vault edit sekrety.yml - otwiera plik w edytorze już odszyfrowany, a po zapisaniu automatycznie szyfruje go z powrotem.
  • ansible-vault rekey sekrety.yml - zmienia hasło Vaulta, przydaje się przy rotacji haseł w zespole.
  • ansible-vault decrypt sekrety.yml - trwale odszyfrowuje plik. Używaj wyjątkowo, bo zdejmuje ochronę.

Krok 4: użyj sekretu przy uruchomieniu playbooka

To najważniejszy krok, bo sam zaszyfrowany plik nic nie robi, dopóki nie sięgniesz po niego w playbooku. Sekret podpinasz jak każdą inną zmienną - na przykład wpisem vars_files: [sekrety.yml] - i odwołujesz się do niego jako {{ db_password }}. Jedyna różnica jest przy uruchamianiu: musisz podać hasło Vaulta. Interaktywnie robisz to tak:

ansible-playbook use-secret.yml --ask-vault-pass

A w automatyzacji (CI/CD) podajesz hasło z pliku, który trzymasz poza repozytorium:

ansible-playbook use-secret.yml --vault-password-file ~/.vault_pass

Znaczenie parametrów:

  • --ask-vault-pass - Ansible zapyta o hasło interaktywnie, wygodne przy pracy z konsoli.
  • --vault-password-file <plik> - hasło czytane z pliku, na potrzeby potoków CI/CD. Ten plik NIGDY nie trafia do repozytorium (trzymasz go w sekretach pipeline'u albo lokalnie, poza projektem).

Jeśli uruchomisz playbook bez hasła, Ansible w ogóle nie wystartuje i zgłosi błąd. Dopiero z hasłem sekret zostaje odszyfrowany w pamięci na czas działania i nigdzie nie jest zapisywany:

Zrzut terminala: uruchomienie playbooka bez hasła Vaulta kończy się błędem, a z parametrem --vault-password-file sekret zostaje odszyfrowany i playbook wykonuje się poprawnie
Pierwsze uruchomienie bez hasła kończy się błędem „Attempting to decrypt but no vault secrets found”. Drugie, z parametrem --vault-password-file, odszyfrowuje sekret w pamięci i playbook wykonuje się poprawnie (PLAY RECAP: ok=1, failed=0).

Tak domyka się bezpieczny obieg sekretu: zaszyfrowany leży w repozytorium, a odszyfrowuje się wyłącznie w pamięci i wyłącznie w chwili, gdy jest naprawdę potrzebny.

Podsumowanie

Ansible to narzędzie, które zamienia ręczną, powtarzalną administrację w jeden opisany plik. Zapamiętaj kilka rzeczy:

  • Opisujesz stan docelowy, nie kolejne komendy - a Ansible sam doprowadza do niego serwery.
  • Agentless - na serwerach nie instalujesz niczego, wystarczy SSH i Python.
  • Playbook w YAML czyta się jak listę kroków i trzymasz go w repozytorium razem z kodem.
  • Idempotencja pozwala uruchamiać playbook bez obaw, ile razy chcesz - zmienia się tylko to, co trzeba.
  • Role, szablony i Vault dają porządek i bezpieczeństwo, gdy projekt rośnie.

Dobry sposób na naukę to zrobić dokładnie to, co my w tym artykule: postawić kilka maszyn (choćby w kontenerach) i napisać własny, pierwszy playbook. Ansible odwdzięcza się szybko - już pierwszy scenariusz, który konfiguruje kilka serwerów naraz, pokazuje, ile czasu oszczędza.

Baner szkolenia Automatyzacja zadań z Ansible w JSystems z terminem gwarantowanym

Szkolenie Ansible -->

Jeśli chcesz przejść od pierwszego playbooka do biegłej automatyzacji całej infrastruktury - ról, Vault, dynamicznego inventory i wdrożeń - nasze szkolenie Automatyzacja zadań z Ansible prowadzi przez to krok po kroku, na praktycznych warsztatach. Kurs ma termin gwarantowany.

To szkolenie może być dofinansowane dla Ciebie z KFS lub BUR.

★★★★★Średnia ocena naszych szkoleń w Google: 5/5

Komentarze (0)

Musisz być zalogowany by móc dodać komentarz. Zaloguj się przez Google

Brak komentarzy...