Инструменты пользователя

Инструменты сайта


linux:ansible:error

Это старая версия документа!


Действия в случае ошибки.

Рассмотрим 2 варианта:

  • Мы, в любом случае, хотим выполнить чать задачь, даже если сценарий прекратит работу из-за ошибки.
  • Мы хотим выполнить определенное действие, если сценарий прекратит работу из-за ошибки.
Это возможно реализовать с помощью block + rescue/always.

Примеры.

а) Выполнять задачу после rescue, если основной сценарий выполнился с ошибкой:

- name: Основной сценарий
  block:
    ...
  rescue:
    - name: Выполнить, если произошла ошибка
      debug:
        msg: 'Show error'

б) Выполнять задачу после always независимо от результата выполнения основного сценария:

- name: Основной сценарий
  block:
    ...
  always:
    - name: Выполнить в любом случае
      command: rm -f /tmp/test

в) И то и другое:

- name: Основной сценарий
  block:
    ...
  rescue:
    - name: Выполнить, если произошла ошибка
      debug:
        msg: 'Show error'
  always:
    - name: Выполнить в любом случае
      command: rm -f /tmp/test

* в данном примере мы отобразим текст Show error только при наличии ошибки, а также выполним команду rm -f /tmp/test независимо от исхода работы сценария.

any_errors_fatal

Чтобы при ошибке выполнения на одном из серверов прекратилось выполнение на всех, нужно добавить any_errors_fatal: true перед блоком задач

- name: test-playbook
  hosts: servers
  any_errors_fatal: true
  tasks:
    - name: Создание файла
      file:
        dest: /home/file.txt
        state: touch
        owner: root
        group: root
        mode: 0644

ignore_errors

market.yandex.ru РЕКЛАМА Главная DevOps Ansible Синтаксис playbook'ов Ansible

2022-06-15

1742 Синтаксис playbook'ов Ansible Описание Playbook — это сценарий, описывающий действия, которые нужно выполнить на управляемых хостах.

Особенности: Пишется на YAML; Действия выполняются последовательно в том порядке, в котором написаны; Идемпотентность - проверяется, достигнуто ли желаемое конечное состояние, и если это состояние достигнуто работа завершается без выполнения каких-либо действий, так что повторение задачи не изменяет конечное состояние; Начинается с трех тире (—), обозначающих начало документа; Комментарии обозначаются решеткой #; Отступ - 2 пробела. Запуск сценария осуществляется командой ansible-playbook main.yaml Структура файла playbook

— #Начинается всегда с трех тире - name: test-playbook #Имя playbook (любое)

hosts: servers        #Группа хостов, на которых будет происходить выполнение (своя группа, all, ungroupt, localhost)
become: true          #Запускать все задачи с правами суперпользователя (true или false, по умолчанию - false)
gather_facts: true    #Осуществлять или нет сбор фактов (данных об управляемых хостах) (true или false, по умолчанию - true)
vars:                 #Список переменных для этого сценария
  owner: root
  custom_var: 42
vars_files:           #Файлы с переменными
  - vars.yaml
tasks:                          #Список задач
  - name: block examples tasks  #Объединенный блок нескольких задач, для которого можно задать условие, теги и.т.д.
    block: 
      - name: Установка apache в centos
        yum:
          name: httpd
          update_cache: true
          state: present
  1. name: Запуск apache в centos

service:

          name: httpd
          state: started
          enabled: true
    tags: tag1, tag2                      #Теги
    when: ansible_os_family == "RedHat"   #Условие выполнения
  1. name: Создание файла #Имя задачи

file: #Модуль

      dest: /var/www/html/index.html  #Аргументы
      state: touch
      owner: "{{ owner }}"            #Использование переменной, всегда выделяется кавычками
      group: "{{ owner }}"
      mode: 0644
    tags: tag1, tag2
    notify: Restart httpd             #Вызывается handlers только если произошли изменения
handlers:
  - name: Restart httpd
    service:
      name: httpd
      state: restarted

Основными группами простого сценария являются: hosts — управляемые узлы или группы узлов, к которым нужно применить изменения, можно указать список; tasks — задачи описывающие состояние, в которое необходимо привести управляемый узел, могут быть выделены в роли; roles — объединение содержимого, такого как файлы, шаблоны, задачи и т.д. в одну роль для ее последующего вызова gather_facts — собирать или нет информацию об узлах перед выполнением задач, по умолчанию — да; vars — переменные, которые будут использованы при выполнении сценария; block — объединение нескольких задач в блок для которого можно указать условие и теги vars_files — список файлов с переменными pre_tasks — список задач, выполняемых перед другими задачами post_tasks — список задач, выполняемых после других задач handlers — список задач, выполняемых после вызова из другой задачи Задачи в блоке handlers называются обработчиками и выполняются в тех случаях, если в результате выполнения вызывающей их задачи произошли изменения. Обработчики выполняются только после завершения задач и только один раз. Обработчики выполняются в порядке следования в разделе handlers. В основном обработчики используются для перезапуска служб после изменения конфигурационных файлов.

Основными параметрами простого сценария являются: connection — можно указать метод соединения с узлами: pure ssh, paramiko, fireball, chroot, jail, local, accelerate (применимо также для выполнения отдельного модуля); sudo — после установления соединения выполнять задачу с привилегиями другого пользователя, по умолчанию другой пользователь — root; sudo_user — в сочетании с предыдущим параметром можно указать с привилегиями какого именно пользователя будет выполнена задача; vars_prompt — перед выполнением playbook'а Ansible в интерактивном режиме может уточнить указанные в этом разделе параметры; remote_user — имя пользователя для авторизации на удалённом узле; become — выполнить от имени привилегированного пользователя; become_user — имя привилегированного пользователя; when — условие выполнения; tags — теги, могут быть указаны при запуске playbook'а для выполнения конкретных задач; ignore_errors — игнорировать ошибки выполнения задачи и продолжать дальше. Debug и register Модуль debug имеет два возможных аргумента var — выводит значение переменной; msg — выводит текст, а также можно выводить значение переменной, в том числе встроенных в ansible, например owner. Все встроенные переменные можно посмотреть командой ansible group -m setup. Пример debug — - name: test-playbook

hosts: localhost
vars:
  msg1: 123
  msg2: 456
  path: /home/123
tasks:
  - debug:  
      var: path
  1. debug:

var: ansible_os_family #выводит семейство ос

  
  - debug:  
      msg: "string {{ owner }}"
  #Объединить переменные в новую переменную и вывести
  - set_fact: full_message="{{ msg1 }} {{ msg2 }} {{ owner }}"
  1. debug:

msg: full_message Модуль register сохраняет выходные данные команд, он регистрирует в отдельный словарь с информацией о задаче, которую можно использовать дальше, всякая задача, выполняемая при запуске, может сохранить результаты в переменной. Для вывода информации в консоль можно использовать модуль debug.

Пример register — - name: test-playbook

hosts: localhost
tasks:
  - shell: uptime
    register: results
  
  - debug:  
      var: results 
  1. debug:

var: results.stdout #выведет только вывод команды uptime Условия Для условия используется слово when

Пример when (true или false) — - name: test-playbook

hosts: localhost
vars:
  var1: true
  var2: false
tasks:
  - name: Установка apache в centos
    yum:
      name: httpd
      update_cache: true
      state: present
    when: var1
    
  - name: Установка nginx в centos
    yum:
      name: httpd
      update_cache: true
      state: present
    when: var2

Будет выполнена только первая задача. Пример when (сравнение переменной со значением) — - name: test-playbook

hosts: servers
tasks:
  - name: Установка apache в centos
    yum:
      name: httpd
      update_cache: true
      state: present
    when: ansible_os_family == "RedHat"   #ansible_os_family - встроенная переменная
  1. name: Установка apache в ubuntu

apt:

      name: apache2
      update_cache: true
      state: present
    when: ansible_os_family == "Debian"   #или when: ansible_os_family != "RedHat"
    
  - name: Запуск apache в centos
    service:
      name: httpd
      state: started
      enabled: true
    when: ansible_os_family == "RedHat"
  1. name: Запуск apache в ubuntu

service:

      name: apache2
      state: started
      enabled: true
    when: ansible_os_family == "Debian"   #или (when: ansible_os_family != "RedHat")

Можно сделать блоком предыдущий пример с использованием block — - name: test-playbook

hosts: servers
tasks:
  - block:
      - name: Установка apache в centos
        yum:
          name: httpd
          update_cache: true
          state: present
  1. name: Запуск apache в centos

service:

          name: httpd
          state: started
          enabled: true
    when: ansible_os_family == "RedHat"
  1. block:
    1. name: Установка apache в ubuntu

apt:

          name: apache2
          update_cache: true
          state: present
  1. name: Запуск apache в ubuntu

service:

          name: apache2
          state: started
          enabled: true
    when: ansible_os_family == "Debian"

Шаблоны Jinja2 Шаблоны позволяют задавать переменные в файлах, которые будут скопированы на хосты. При копировании переменная заменяется значением.

Например есть файл template1.j2 со следующим содержимым Hostname: ansible_hostname #встроенные переменные OS family: ansible_os_faminy IP: ansible_default_ipv4.address my_var: my_var #своя переменная Тогда playbook будет следующим — - name: test-playbook

hosts: servers
vars:                               #своя переменная
  my_var: example1
tasks:
  - name: Копирование файла с подстановкой переменных
    template:
      src: /home/test1/template1.j2
      dest: /home/test2/file1.txt   #из шаблона получается файл с именем file1.txt с подставленными переменными
      mode: 0644

Циклы Есть несколько вариантов цикла loop - цикл по количеству элементов списка; with_fileglob - цикл использующий файлы, которые соответствуют регулярному выражению; until - цикл с условием выхода. Цикл имеет зарезервированную переменную item, значение которой меняется каждую итерацию цикла.

Пример loop — - name: test-playbook

hosts: servers
tasks:
  - name: Вывод 4 строк с цифрами
    debug:  
      msg: "string {{ item }}"  #item - это зарезервированное для цикла слово
      loop:
        - "1"
        - "2"
        - "3"
        - "4"
      loop_control:
        pause: 3                #пауза в 3 секунды между итерациями цикла, можно не указывать
  1. name: Копирование нескольких файлов

copy:

      src: "/home/test1/{{ my_files }}"
      dest: /home/test2
      mode: 0644
    loop:
      - "file1.txt"
      - "file5.txt"
      - "file6.txt"
    loop_control:
      loop_var: my_files  #замена стандартной переменной item на свою

Пример with_fileglob — - name: test-playbook

hosts: servers
tasks:
  - name: Копирование файлов по регулярному выражению
    copy:
      src: "/home/test1/{{ item }}"
      dest: /home/test2
      mode: 0644
    with_fileglob: "*.txt"
  1. name: Копирование файлов по регулярному выражению

copy:

      src: "{{ item }}"
      dest: /home/test2
      mode: 0644
    with_fileglob: "/home/test1/*.txt"

Эти две задачи выполнят одно и тоже. Пример until — - name: test-playbook

hosts: servers
tasks:
  - name: Второй вариант
    shell: echo -n "123-" >> file1.txt && cat file1.txt     #запись строки в файл и вывод в консоль
    register: output                                        #вывод предыдущей команды записывается в переменную output
    delay: 2                                                #задержка 2 секунды между итерациями цикла, необязательно
    retries: 10                                             #максимальное количество итераций цикла, необязательно, по умолчанию 3
    until: output.stdout.find("123-123-123-") == false      #условие выхода из цикла
  1. name: Вывод output

debug:

      var: output.stdout

Import и include Для разделения playbook'а используются import и include. Они позволяют в отдельном файле написать задачи на определенную тему, затем импортировать их в основной файл.

При использовании import - ansible берет текст файла перед запуском и проверяет на ошибки.

При использовании include содержимое файла берется только в момент прохода по этой команде, поэтому если используются переменные взятые из фактов нужно использовать include.

Например файл task_create.yaml содержит — - name: create file

file:
  dest: /home/file.txt
  state: touch
  owner: root
  group: root
  mode: 0644

А основной файл —

  1. name: test-playbook

hosts: servers

  tasks:
    include: task_create.yaml   #вместо include можно использовать import
      myvar: "string"           #можно передавать переменные в подключаемый файл

Роли Роли позволяют автоматически загружать связанные переменные, файлы, задачи, обработчики и другие артефакты Ansible на основе известной файловой структуры.

Роль Ansible имеет определенную структуру каталогов с восемью основными стандартными каталогами. Эту структуру можно сгенерировать командой ansible-galaxy init или создать каталоги самостоятельно Части playbook'а переносятся в соответствующие каталоги, затем в главной файле вызывается роль.

Список каталогов роли и их назначение tasks — задачи; handlers — задачи handlers; templates — шаблоны j2; files — файлы для копирования; vars — переменные, связанные с этой ролью; defaults — переменные по умолчанию, имеют самый низкий приоритет; meta — метаданные для роли, включая зависимости от роли; library — пользовательские модули; module_utils — пользовательские module_utils; lookup_plugins — дополнительные плагины. Основной файл — - name: test-playbook

hosts: servers
roles: 
  - role_name_1
  - role_name_2

Внешние переменные Переменные, переданные в playbook через extra-var имеют наивысший приоритет. Передача значения переменной в playbook осуществляется с помощью ключа -e или –extra-var, например -e «message1=Hello».

Например, чтобы указывать на какой группе хостов запускать playbook, можно написать следующее — - name: test-playbook

hosts: "{{ hosts_run }}"
tasks:
  - name: Создание файла
    file:
      dest: /home/file.txt
      state: touch
      owner: "{{ owner }}"
      group: "{{ owner }}"
      mode: 0644

И при запуске указывать значение переменной ansible-playbook main.yaml –extra-var «hosts_run=servers owner=root» Теги Ansible позволяет применять теги для выполнения определенных сценариев или задач к которым они привязаны. Для указания тегов при запуске playbook'а необходимо использовать ключ tags, за которым следует список нужных тегов.

ansible-playbook main.yaml –tags=test запуск сценария с передачей тега ansible-playbook main.yaml –skip-tags=test пропустить задачи с определенным тегом ansible-playbook main.yaml –list-tags проверить доступные теги Ansible имеет специальные теги: always - задача, помеченная этим тегом, всегда будет выполняться, даже если она не соответствует списку тегов, переданных в опции –tags. Единственное исключение ― когда он явно пропускается с помощью опции –skip-tags=always. never - задача, помеченная этим тегом, не выполняется, за исключением случая, когда выполняется набор сценариев с опцией –tags, в которой указано значение never или один из тегов, связанных с задачей. tagged - запускает любую задачу с явным тегом untagged - запускает любую задачу не имеющую явного тега all - включает все задачи в сценарии независимо от того, есть у них теги или нет. Это поведение Ansible по умолчанию. Выполнение задачи только на одном сервере Нужно написать у задачи delegate_to: server1 тогда задача выполнится только на указанном сервере.

Пример — - name: test-playbook

hosts: servers
tasks:
  - name: Создание файла
    file:
      dest: /home/file.txt
      state: touch
      owner: root
      group: root
      mode: 0644
    delegate_to: server1

С помощью этого можно сделать так, чтобы сервера направили некоторые свои данные на другой сервер, например — - name: test-playbook

hosts: servers
tasks:
  - name: text
    shell: echo "Server {{ inventory_hostname }} - node name {{ ansible_nodename }}" >> /home/log.txt
    delegate_to: localhost

При выполнении на мастере создаться файл в который будут записаны значения переменных с других серверов. Если нужно запустить задачу только на одном сервере, но не важно на каком, нужно поставить флаг run_once: true, например — - name: test-playbook

hosts: servers
tasks:
  - name: Создание файла
    file:
      dest: /home/file.txt
      state: touch
      owner: root
      group: root
      mode: 0644
    run_once: true

Перехват и контроль ошибок При запуске playbook, если на одном из серверов какая-либо задаче не выполнилась, то все последующие задачи на этом сервере не будут выполнены, чтобы этого не произошло нужно добавить флаг ignore_errors: yes, тогда если в этой задаче произойдет ошибка последующие все равно будут выполняться.

---
- name: test-playbook
  hosts: servers
  tasks:
    - name: Создание файла
      file:
        dest: /home/file.txt
        state: touch
        owner: root
        group: root
        mode: 0644
      ignore_errors: yes
linux/ansible/error.1701115440.txt.gz · Последние изменения: 2023/11/27 23:04 — werwolf