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
moleculelub 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.cfgi 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.