В чем основной минус использования shell-модуля (command, shell) в Ansible?

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

Ответ

Главный и самый критичный минус — нарушение принципа идемпотентности. Ansible построен на идее, что плейбук можно запускать многократно, приводя систему к одному и тому же желаемому состоянию. Модули shell и command этого не гарантируют.

Они просто выполняют заданную команду в оболочке, не анализируя текущее состояние системы. Это приводит к побочным эффектам.

Плохой пример (неидемпотентный):

- name: Add entry to config file
  ansible.builtin.shell: "echo 'ServerName localhost' >> /etc/apache2/apache2.conf"

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

Хорошая практика (идемпотентный модуль):

- name: Ensure entry exists in config file
  ansible.builtin.lineinfile:
    path: /etc/apache2/apache2.conf
    line: 'ServerName localhost'
    state: present

Модуль lineinfile проверит наличие строки и добавит её только если её нет.

Другие недостатки shell/command:

  • Сложность обработки вывода: Вывод — простой текст, для его парсинга нужны фильтры register и stdout_lines. Специализированные модули возвращают удобный JSON.
  • Потенциальные проблемы с безопасностью: Необходимо вручную экранировать переменные с помощью фильтра quote, чтобы избежать инъекций.
  • Меньшая переносимость: Команда, работающая в bash, может не сработать в sh или другой оболочке. Специализированные модули абстрагируют это.

Я использую shell/command только в крайних случаях, когда нет подходящего идемпотентного модуля, и всегда оборачиваю логику в проверки creates, removes или changed_when для имитации идемпотентности.