Шаблоны file.managed

Тема дорожной карты · SaltStack

file.managed — самый используемый state-модуль Salt: он приводит файл на миньоне к нужному содержимому, правам и владельцу. С опцией template: jinja он превращается в полноценный механизм доставки конфигов: исходник лежит на файловом сервере мастера как Jinja-шаблон, а на каждом миньоне рендерится в свой вариант — с локальными IP, портами из pillar, путями под конкретный дистрибутив. Это второй большой дом Jinja в Salt после SLS-файлов: шаблоны конфигов, как и SLS, рендерятся на миньоне и видят его grains, pillar и execution-модули. Один шаблон nginx.conf.jinja вместо парка почти одинаковых файлов — типовой первый выигрыш от внедрения Salt.

Как это работает

Базовый пример:

nginx_config:
  file.managed:
    - name: /etc/nginx/nginx.conf
    - source: salt://nginx/files/nginx.conf.jinja
    - template: jinja
    - user: root
    - mode: '0644'
    - context:
        worker_connections: {{ salt['pillar.get']('nginx:workers', 1024) }}
    - defaults:
        worker_connections: 512

source указывает на файл в file_roots через протокол salt://. Внутри шаблона доступны grains, pillar, salt — например, worker_processes {{ grains['num_cpus'] }}; — плюс переменные, переданные через context. Словарь defaults задаёт значения на случай, когда context их не переопределил: так один шаблон вызывается из разных состояний с разными параметрами. Миньон рендерит шаблон, сравнивает результат с текущим файлом по хешу и переписывает его только при отличии — поэтому состояние идемпотентно, а state.apply nginx test=True показывает дифф будущих изменений, не трогая файл. В связке с watch у service.running изменение отрендеренного конфига автоматически перезапускает сервис.

Когда применять

template: jinja нужен, как только в файле появляется хоть одно значение, зависящее от миньона или окружения: порт из pillar, адрес из grains, путь, различающийся между дистрибутивами. Передавайте значения через context тогда, когда один шаблон используется несколькими состояниями с разными параметрами — например, шаблон виртуального хоста, вызываемый в цикле для каждого сайта: context с именем сайта делает шаблон чистой функцией от параметров. Если же файл полностью статичен, шаблонизация не нужна: обычный file.managed с source без template дешевле и предсказуемее. Для очень больших файлов, где меняется одна строка, рассмотрите file.replace или file.blockreplace вместо шаблона на весь файл — меньше риска затереть чужие правки.

Типичные ошибки

Частая ошибка — конфликт синтаксиса: сам конфиг использует фигурные скобки (шаблоны Nginx-переменных, Go-шаблоны, форматные строки), и Jinja пытается их интерпретировать. Лечится обёрткой {% raw %} ... {% endraw %} вокруг проблемных блоков. Вторая — тяжёлая логика в шаблоне конфига: условия и вычисления лучше выполнить в SLS и передать готовые значения через context, иначе шаблон нечитаем и его нельзя переиспользовать. Третья — забытая пара defaults при необязательном context: шаблон падает с ошибкой неопределённой переменной на миньонах, где параметр не передали. Четвёртая — ручные правки файла на сервере: следующий state.apply молча их перезапишет; всё, что должно жить, обязано жить в шаблоне или pillar.

Связанные понятия

Полезные ресурсы

Проверить знания (2)

Загрузка вопросов…