Как изменить Ansible Playbook, чтобы он выполнялся только на определенных серверах?

«Как изменить Ansible Playbook, чтобы он выполнялся только на определенных серверах?» — вопрос из категории Ansible, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В инфраструктурных проектах я постоянно работаю с целевым выполнением плейбуков. Вот основные практики, которые использую.

1. Определение целей в инвентари (inventory) — основной метод. Группирую хосты в inventory/production.ini:

[webservers]
web01.example.com ansible_user=deploy
web02.example.com

[databases]
db01.example.com

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

Затем в плейбуке указываю группу:

- name: Configure Nginx on web servers
  hosts: webservers  # Выполнится ТОЛЬКО на этой группе
  tasks: ...

2. Динамическое ограничение с помощью --limit: Запускаю плейбук для подмножества хостов из группы, например, для одного сервера из webservers:

ansible-playbook site.yml --limit "web01.example.com"
# Или по шаблону:
ansible-playbook site.yml --limit "*.example.com"

3. Использование тегов (tags): Позволяет выполнять не весь плейбук, а только задачи с определенными тегами на любой группе хостов.

- name: Deploy application
  hosts: all
  tasks:
    - name: Copy configs
      copy: src=app.conf dest=/etc/
      tags: config

    - name: Restart service
      systemd: name=app state=restarted
      tags: deploy

Запуск: ansible-playbook deploy.yml --tags "deploy" --limit "webservers"

4. Динамические группы и переменные извне: Часто в CI/CD нужно передать целевые хосты динамически. Использую переменную hosts:

- name: Run ad-hoc update
  hosts: "{{ target_hosts | default('all') }}"
  tasks: ...

Запуск с передачей хостов через переменную окружения или аргумент:

export TARGET_HOSTS="web01,db01"
ansible-playbook update.yml -e "target_hosts=$TARGET_HOSTS"

Для сложной логики (например, выполнить задачу только если сервер в определенном дата-центре) использую условие when с фактами Ansible: when: ansible_facts['datacenter'] == 'ams1'.