Bloki, rescue i always – obsługa błędów w playbookach

Bloki, rescue i always – obsługa błędów w playbookach

Automatyzacja zadań administracyjnych w Ansible zakłada nie tylko poprawne wykonanie działań, ale także odpowiednią reakcję w przypadku błędów. W środowiskach produkcyjnych każdy etap wdrożenia powinien być kontrolowany i bezpieczny. W tym artykule omówię mechanizmy block, rescue i always, które pozwalają na obsługę wyjątków i błędów w playbookach Ansible.


1. Czym są bloki w Ansible

Mechanizm block umożliwia grupowanie zadań w logiczne sekcje. Każdy blok może zawierać zestaw zadań głównych, sekcję rescue (obsługa błędów) oraz always (działania wykonywane zawsze, niezależnie od wyniku).

Struktura ogólna:

– block:
  – name: Zadania główne
    …
  rescue:
  – name: Zadania w razie błędu
    …
  always:
  – name: Zadania wykonywane zawsze
    …

Dzięki temu można kontrolować przepływ zadań nawet w przypadku niepowodzenia jednego z nich.


2. Użycie block w praktyce

Instrukcja block przydaje się szczególnie tam, gdzie kilka zadań musi być wykonanych razem — np. przygotowanie środowiska, instalacja oprogramowania lub wdrożenie plików. Jeśli jedno z zadań w bloku zakończy się błędem, pozostałe z tego bloku nie zostaną wykonane, a sterowanie przechodzi do sekcji rescue.

Przykład:

– name: Install and configure web service
  hosts: webservers
  become: yes
  tasks:
    – block:
      – name: Install nginx
        ansible.builtin.package:
          name: nginx
          state: present

      – name: Deploy configuration
        ansible.builtin.template:
          src: nginx.conf.j2
          dest: /etc/nginx/nginx.conf
        notify: Restart nginx

      – name: Start nginx service
        ansible.builtin.service:
          name: nginx
          state: started

      rescue:
      – name: Rollback on failure
        ansible.builtin.service:
          name: nginx
          state: stopped

      – name: Notify administrator
        ansible.builtin.debug:
          msg: „Deployment failed – nginx stopped.”

      always:
      – name: Log completion of task
        ansible.builtin.debug:
          msg: „Playbook finished (success or error).”

W tym przykładzie, jeśli instalacja lub konfiguracja nginx zakończy się błędem, Ansible zatrzyma usługę i wyświetli komunikat ostrzegawczy, po czym zawsze wykona logowanie zakończenia pracy.


3. Sekcja rescue – reakcja na błąd

Sekcja rescue jest wykonywana tylko wtedy, gdy jedno z zadań w sekcji block zakończy się błędem. Zazwyczaj zawiera zadania przywracające poprzedni stan systemu, np. cofanie zmian, restart usług lub wysyłanie powiadomień.

Przykład: automatyczne przywrócenie poprzedniej konfiguracji

– block:
  – name: Deploy new configuration
    ansible.builtin.copy:
      src: new.conf
      dest: /etc/app/app.conf
      backup: yes

  rescue:
  – name: Restore previous configuration
    ansible.builtin.command: cp /etc/app/app.conf.backup /etc/app/app.conf
    ignore_errors: yes

Dzięki sekcji rescue można automatycznie przywrócić system do poprzedniego, działającego stanu bez ręcznej interwencji.


4. Sekcja always – działania końcowe

Sekcja always wykonywana jest zawsze – niezależnie od tego, czy zadania w bloku zakończyły się sukcesem czy błędem. Najczęściej używana jest do logowania, czyszczenia plików tymczasowych lub informowania o zakończeniu procesu.

Przykład:

– block:
  – name: Try to deploy
    ansible.builtin.shell: ./deploy.sh

  rescue:
  – name: Deployment failed
    ansible.builtin.debug:
      msg: „Deployment failed.”

  always:
  – name: Clean temporary files
    ansible.builtin.file:
      path: /tmp/deploy.lock
      state: absent

Nawet jeśli skrypt wdrożeniowy się nie powiedzie, plik tymczasowy zostanie usunięty.


5. Kontrola błędów a idempotentność

Bloki nie naruszają zasady idempotentności – jeśli zadania w bloku nie wprowadzają zmian, kolejne uruchomienia playbooka nie wykonują ich ponownie. Natomiast dzięki sekcji rescue i always można bezpiecznie reagować na błędy bez przerywania całego procesu automatyzacji.


6. Dobre praktyki w obsłudze błędów

  • grupowanie zadań krytycznych w bloki,
  • stosowanie rescue do przywracania stanu lub powiadomień,
  • używanie always do czyszczenia środowiska,
  • unikanie nadmiernego ignorowania błędów (ignore_errors: yes tylko w uzasadnionych przypadkach),
  • łączenie bloków z handlerami i warunkami dla pełnej kontroli przepływu.

Podsumowanie

Mechanizmy block, rescue i always umożliwiają tworzenie odpornych na błędy i przewidywalnych playbooków. Dzięki nim można skutecznie zarządzać wyjątkami, minimalizować ryzyko awarii i zapewnić ciągłość działania systemów. Świadome wykorzystanie tych narzędzi jest kluczowe w profesjonalnych środowiskach DevOps i produkcyjnych automatyzacjach.

Przewijanie do góry