Обо всем и не только
Архитектура Ansible
Цепочка следующая:
graph TD
A[Control node]
--> B[Inventory]
B --> C[Playbook]
C --> D[Role]
D --> E[Tasks]
E --> F[Modules]
F --> G[Managed hosts]
В типичном Linux сценарии:
-
agentless
-
подключается по SSH
-
выполняет модули на целевых машинах
-
стремится привести систему к описанному состоянию
-
использует inventory для определения хостов и групп.
Пример:
hosts: web берется из inventory
become - повышение привилегий
основная логика вынесена в роль
inventory
не только:
а группы, переменные и разные окруженияinventories/
├── prod/
│ ├── hosts.yml
│ ├── group_vars/
│ └── host_vars/
└── stage/
├── hosts.yml
├── group_vars/
└── host_vars/
например:
запуск
нужно знать:
-
group_vars
-
host_vars
-
группы
-
вложенные группы
-
inventory variables
-
static/dynamic inventory - хотя бы концептуально
-
--limit
Переменные и predence
например
использование:
в шаблоне:
нужно понимать назначение:
defaults/main.yml
vars/main.yml
group_vars/
host_vars/
vars_files
register
set_fact
-e / --extra-vars
и самое главное - variable predence
Idempotency
это одна из центральных концепций Ansible
плохо:
Лучше:
Первый запуск выдаст changed=5 а второй changed=0
Modules вместо shell/command
плохо: ``yaml shell: systemctl restart nginx
Совет
Ещё лучше — если рестарт вообще требуется только после изменения конфигурации — handler.
Предупреждение
command и shell использовать можно. Важно понимать когда без них действительно разумнее, и контролировать changed_when, failed_when, creates, removes и т. п.
Handlers
- name: Deploy nginx config
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: Reload nginx
Handler:
Если конфиг не изменился то changed=false и handler не вызывается.
Если изменился, то changed=true, ansible уведомляет handler.
совет
Также стоит знать listen:
Важно понимать, что handlers обычно выполняются в конце соответствующей части play, а при необходимости существует - meta: flush_handlers
Jinja2
Простой шаблон:
Условия:
Циклы:
Фильтры:
Нужно понимать:
-
{{ }}
-
{% %}
-
условия;
-
циклы;
-
filters;
-
default;
-
работу с list/dict;
-
шаблонизацию конфигов
Conditions
например:
- name: Install nginx
ansible.builtin.apt:
name: nginx
state: present
when: ansible_facts['os_family'] == 'Debian'
и:
совет
Нужно понимать boolean, is defined, is not defined, сравнения, проверки результатов зарегистрированных задач.
Loops
- name: Install packages
ansible.builtin.apt:
name: "{{ item }}"
state: present
loop:
- nginx
- curl
- vim
иногда лучше передать модулю сразу список:
также:
Register
Очень важно для реальных сценариев:
- name: Check application
ansible.builtin.command:
cmd: systemctl is-active myapp
register: app_status
changed_when: false
После этого:
и:
Нужно понимать основные поля результата:
-
stdout
-
stderr
-
rc
-
changed
-
failed
chandeg_when и failed_when
Например:
- name: Check nginx configuration
ansible.builtin.command:
cmd: nginx -t
register: nginx_test
changed_when: false
Проверка ничего не изменила, поэтому ansible не должен показывать changed
можно управлять ошибками:
block/rescue/always
например:
- block:
- name: Deploy application
ansible.builtin.copy:
src: app
dest: /opt/app
rescue:
- name: Rollback
ansible.builtin.command:
cmd: /opt/rollback.sh
always:
- name: Write deployment status
ansible.builtin.debug:
msg: "Deployment finished"
по смыслу:
Очень полезный инструмент для деплоев.
Roles
Важно понимать назначение каталогов
также:
И хотя бы понимать разницу dynamic include vs static import.
Collections и Galaxy
FQCN:
вместо простого copy
Dependencies:
и
Vault
важно знать команды:
ansible-vault create
ansible-vault edit
ansible-vault view
ansible-vault encrypt
ansible-vault decrypt
ansible-vault rekey
Например:
и:
Плюс vault-id
Предупреждение
В CI секрет должен приходить из защищённого механизма секретов/CI variables или внешнего secret manager.
Facts
Ansible собирает информацию о машине.
можно делать:
иногда оправдано выключить сбор инфы:
Delegation и run_once
например у тебя 200 серверов а миграцию БД нужно выполнить один раз
а выполнить задачу на другой машине:
например:
- name: Run migration
ansible.builtin.command:
cmd: /opt/app/migrate
run_once: true
delegate_to: db01
Здесь уже важно понимать нюансы выбора хоста и контекста переменных, а не воспринимать run_once как магическую кнопку «глобально ровно один раз при любых условиях».
Tags
например:
запуск:
и:
Check mode и diff
Перед продом:
и:
--check — попытка показать, что Ansible собирается изменить, без фактического применения там, где модуль поддерживает check mode.
--diff помогает увидеть изменения содержимого.
Особенности
check mode не является гарантией безопасного выполнения.
Не все модули/команды одинаково хорошо его поддерживают.
Безопасная раскатка
Плохо:
Хорошо:
lint
↓
syntax-check
↓
Molecule
↓
stage
↓
check/diff
↓
canary
↓
batch deployment
↓
verification
↓
full deployment
Например:
Ansible будет обрабатывать хосты партиями
можно использовать:
чтобы контролировать допустимые ошибки во время batch deployment
Molecule
нужно понимать цикл:
verify должен реально проверить результат:
Совет
То есть тестируем не: Ansible завершился без ошибки.
А: Система действительно оказалась в требуемом состоянии.
ansible-lint + syntax-check
минимум:
и:
Описание
syntax-check проверяет корректность синтаксиса/структуры playbook.
ansible-lint проверяет гораздо больше правил качества и best practices.
CI/CD
Концепция:
Lint:
Tests:
Prod:
-
кто может запускать prod;
-
откуда приходят SSH credentials;
-
откуда Vault password;
-
protected branches/environments;
-
артефакты и версии;
-
что делать при partial failure;
-
можно ли безопасно повторить job;
-
как избежать одновременных конфликтующих deployment.
Troubleshooting
Например:
думаешь:
получаешь:
Проверяешь:
получаешь:
ищешь:
Получаешь падение только:
Сначала:
Что общего у этих 30?
Какая ОС?
Какая версия пакета?
Какая группа inventory?
Доступность репозитория?
Свободное место?
Права?
Состояние сервиса?
Какая именно task упала?
Произодительность и масштабирование
например:
-
parallelism;
-
forks;
-
serial;
-
throttle;
-
strategy;
-
timeout;
-
почему нельзя бездумно увеличивать concurrency.
Error handling
Знать:
плохой подход везде ставить:
лучше определить ожидаемое состояние
или нормально обработать ситуацию через
Привилегии
Обязательно:
и:
Конфиги нужно валидировать ДО применения
недостаточно:
лучше использовать возможности модуля для предварительной валидации, где они подходят:
- name: Deploy nginx configuration
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
validate: "nginx -t -c %s"
notify: Reload nginx
идея: