Struktura projektu Ansible – best practices

Struktura projektu Ansible – best practices

Organizacja projektu w Ansible ma kluczowe znaczenie dla jego czytelności, utrzymania i skalowalności. Dobrze zaprojektowana struktura katalogów pozwala na łatwiejsze rozwijanie, testowanie i ponowne wykorzystanie playbooków oraz ról w różnych środowiskach – od testowych po produkcyjne.

W tym artykule omówię najlepsze praktyki (best practices) dotyczące struktury projektu Ansible oraz sposób organizacji zasobów takich jak inventory, roles, vars i templates.


1. Ogólna struktura katalogów projektu Ansible

Standardowa struktura projektu Ansible powinna wyglądać następująco:

project/
├── ansible.cfg
├── inventory/
│   ├── dev
│   ├── stage
│   └── prod
├── group_vars/
│   ├── all.yml
│   └── webservers.yml
├── host_vars/
│   └── web01.yml
├── roles/
│   ├── nginx/
│   │   ├── tasks/
│   │   ├── templates/
│   │   ├── files/
│   │   ├── handlers/
│   │   ├── defaults/
│   │   └── meta/
│   └── mysql/
├── playbooks/
│   ├── deploy.yml
│   ├── update.yml
│   └── test.yml
└── requirements.yml

Takie podejście pozwala oddzielić konfigurację, logikę (zadania i role) oraz zmienne, dzięki czemu projekt pozostaje uporządkowany nawet przy setkach hostów i ról.


2. Plik konfiguracyjny ansible.cfg

Plik ansible.cfg definiuje ustawienia dla całego projektu – m.in. ścieżki do plików inventory, roles, cache oraz polityki SSH. Dzięki niemu nie trzeba podawać parametrów w każdym poleceniu ansible-playbook.

Przykład:

[defaults]
inventory = ./inventory/dev
roles_path = ./roles
host_key_checking = False
retry_files_enabled = False
forks = 10
timeout = 30

[privilege_escalation]
become = True
become_method = sudo
become_user = root

Dobrze jest trzymać ansible.cfg w katalogu projektu, dzięki czemu ustawienia nie kolidują z globalną konfiguracją systemową.


3. Inventory – zarządzanie hostami i środowiskami

Katalog inventory/ zawiera definicje hostów i grup. Najlepszą praktyką jest rozdzielenie środowisk (np. dev, stage, prod) do osobnych plików lub katalogów.

Przykład inventory dla środowiska produkcyjnego:

[webservers]
web01 ansible_host=10.0.0.11
web02 ansible_host=10.0.0.12

[dbservers]
db01 ansible_host=10.0.0.21

[all:vars]
ansible_user=ubuntu
ansible_python_interpreter=/usr/bin/python3

Można również stosować inventory dynamiczne – np. aws_ec2, docker, kubernetes – ale wtedy najlepiej trzymać konfigurację pluginów w osobnych plikach YAML.


4. Zmienne globalne i grupowe

Zmienne powinny być logicznie rozdzielone na dwie kategorie:

  • group_vars/ – zmienne wspólne dla grupy hostów,
  • host_vars/ – zmienne specyficzne dla pojedynczego hosta.

Przykład group_vars/webservers.yml:

nginx_port: 80
nginx_user: www-data
app_env: production

Przykład host_vars/web01.yml:

ansible_host: 10.0.0.11
nginx_port: 8080

5. Role – modularność i ponowne wykorzystanie

Role to najważniejszy element struktury projektu Ansible. Pozwalają zorganizować zadania w logiczne jednostki (np. nginx, mysql, users) i wykorzystywać je wielokrotnie w różnych playbookach.

Struktura roli:

roles/
└── nginx/
    ├── defaults/
    │   └── main.yml
    ├── files/
    ├── handlers/
    │   └── main.yml
    ├── meta/
    │   └── main.yml
    ├── tasks/
    │   └── main.yml
    ├── templates/
    │   └── nginx.conf.j2
    └── vars/
        └── main.yml

Przykład roli: roles/nginx/tasks/main.yml

- name: Install nginx
  ansible.builtin.package:
    name: nginx
    state: present

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

Handler:

- name: Restart nginx
  ansible.builtin.service:
    name: nginx
    state: restarted

Role można łatwo udostępniać i ponownie wykorzystywać w wielu projektach, np. za pomocą ansible-galaxy init lub requirements.yml.


6. Playbooki – logiczne łączenie ról

Playbooki definiują kolejność i logikę wykonywania ról, zadań oraz zmiennych. Najlepszą praktyką jest umieszczanie ich w katalogu playbooks/.

Przykład: playbooks/deploy.yml

- name: Deploy web application
  hosts: webservers
  become: yes
  vars_files:
    - ../group_vars/all.yml
  roles:
    - nginx
    - app

7. Plik requirements.yml – zarządzanie zewnętrznymi rolami i kolekcjami

Plik requirements.yml umożliwia deklaratywne zarządzanie zewnętrznymi rolami lub kolekcjami, np. z Ansible Galaxy.

Przykład:

roles:
  - name: geerlingguy.nginx
  - name: community.mysql

collections:
  - name: ansible.posix
  - name: community.general

Instalacja wszystkich zależności:

ansible-galaxy install -r requirements.yml

8. Najlepsze praktyki (Best Practices)

  • Stosowanie ról zamiast pojedynczych playbooków – ułatwia to ponowne wykorzystanie i utrzymanie.
  • Unikanie duplikacji zmiennych – trzymanie wspólnych danych w group_vars/all.yml.
  • Konwencje nazw – trzymanie się jednego stylu dla ról, plików i grup.
  • Stosowanie Ansible Vault dla danych wrażliwych (hasła, klucze, tokeny).
  • Rozdzielenie środowisk (dev, stage, prod) w katalogach inventory.
  • Testowanie ról z narzędziem molecule lub w kontenerach Docker.
  • Idempotentność – każdy playbook powinien być bezpieczny do wielokrotnego uruchomienia.

9. Podsumowanie

Przestrzeganie standardowej struktury projektu Ansible to klucz do sukcesu w automatyzacji infrastruktury. Pozwala uniknąć chaosu, zwiększa czytelność i ułatwia pracę w zespole DevOps.

W skrócie:

  • Konfiguracja w ansible.cfg i inventory,
  • Stosowanie ról do organizacji zadań,
  • Rozdzielenie zmiennych według grup i hostów,
  • Przechowywanie danych wrażliwych w Vault,
  • Wersjonowanie (Git) i automatyzacja testów.

Dzięki temu projekty Ansible są spójne, bezpieczne i łatwe w utrzymaniu – niezależnie od skali środowiska.

Przewijanie do góry