Ansible Pull: от cron к systemd и мониторингу — расширенное руководство
Пошаговое руководство по переходу от cron к systemd для Ansible Pull с добавлением observability через Prometheus и alerting.
Ansible Pull: от cron к systemd и мониторингу
Введение
Ansible Pull — это режим работы, при котором узлы самостоятельно инициируют получение и применение конфигураций из Git-репозитория. В отличие от классической схемы с управляющим узлом (control node), здесь каждый хост сам по расписанию забирает плейбуки и исполняет их. Это особенно полезно для edge-устройств, временных окружений и сценариев, где централизованный push нежелателен или невозможен.
Архитектура и сравнение подходов
| Параметр | Ansible Pull | Классический Ansible (Push) |
|---|---|---|
| Инициатор | Узел (по расписанию) | Управляющий узел |
| Требования к узлу | Python, git, ansible | Минимальные (только Python) |
| Отказоустойчивость | Высокая (узлы автономны) | Зависит от доступности control node |
| Масштабируемость | Линейная | Ограничена производительностью control node |
Шаг 1. Запуск через cron (базовый сценарий)
Самый простой способ — поставить в cron задачу, которая раз в N минут выполняет:
*/5 * * * * /usr/bin/ansible-pull -U https://git.example.com/infra.git main.yml
Плюсы: простота, работает везде, где есть cron.
Минусы: логи cron скудны, сложно отслеживать длительность, нет встроенного мониторинга статуса.
Шаг 2. Переход на systemd — таймеры и сервисы
Systemd даёт три ключевых преимущества: структурированные логи (journald), зависимости между юнитами и встроенный мониторинг.
Юнит сервиса /etc/systemd/system/ansible-pull.service
[Unit]
Description=Ansible Pull — применение конфигурации
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/bin/ansible-pull -U https://git.example.com/infra.git main.yml --purge
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
Юнит таймера /etc/systemd/system/ansible-pull.timer
[Unit]
Description=Запуск Ansible Pull каждые 5 минут
[Timer]
OnBootSec=2min
OnUnitActiveSec=5min
Persistent=true
[Install]
WantedBy=timers.target
Активация:
systemctl daemon-reload
systemctl enable --now ansible-pull.timer
Что это даёт:
journalctl -u ansible-pull.service— полные логи с метаданнымиsystemctl status ansible-pull.timer— состояние расписанияsystemd-analyze calendar '*-*-* *:*:00/300'— проверка синтаксиса
Шаг 3. Мониторинг и observability
Экспортер для Prometheus
Создайте простой скрипт, который проверяет время последнего успешного запуска и экспортирует метрики:
#!/usr/bin/env python3
# /usr/local/bin/ansible-pull-exporter.py
from http.server import HTTPServer, BaseHTTPRequestHandler
import subprocess
import time
import os
LAST_RUN_FILE = '/var/lib/ansible-pull/last_success'
class MetricsHandler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path != '/metrics':
self.send_response(404)
return
last_success = 0
if os.path.exists(LAST_RUN_FILE):
with open(LAST_RUN_FILE) as f:
try:
last_success = float(f.read().strip())
except:
pass
# Проверяем, есть ли активные задачи
try:
result = subprocess.run(['systemctl', 'is-active', 'ansible-pull.service'],
capture_output=True, text=True)
active = 1 if result.stdout.strip() == 'active' expanded' else 0
except:
active = 0
response = (
f'# HELP ansible_pull_last_success_timestamp Unix timestamp последнего успеха\n'
f'# TYPE ansible_pull_last_success_timestamp gauge\n'
f'ansible_pull_last_success_timestamp {last_success}\n'
f'# HELP ansible_pull_service_active 1 если сервис активен\n'
f'# TYPE ansible_pull_service_active gauge\n'
f'ansible_pull_service_active {active}\n'
)
self.send_response(200)
self.send_header('Content-type', 'text/plain; version=0.0.4')
self.end_headers()
self.wfile.write(response.encode())
if __name__ == '__main__':
HTTPServer(('127.0.0.1', 9123), MetricsHandler).serve_forever()
Systemd service для экспортера
[Unit]
Description=Ansible Pull Prometheus Exporter
After=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 /usr/local/bin/ansible-pull-exporter.py
Restart=on-failure
[Install]
WantedBy=multi-user.target
В Prometheus добавляем job:
scrape_configs:
- job_name: 'ansible-pull'
static_configs:
- targets: ['node1:9123', 'node2:9123']
Alerting rules
groups:
- name: ansible-pull.rules
rules:
- alert: AnsiblePullNotRunning
expr: ansible_pull_service_active == 0
for: 10m
labels:
severity: warning
annotations:
summary: "Ansible Pull не активен на {{ $labels.instance }}"
description: "Сервис ansible-pull.service не в статусе active более 10 минут."
- alert: AnsiblePullStale
expr: time() - ansible_pull_last_success_timestamp > 900
for: 5m
labels:
severity: critical
annotations:
summary: "Ansible Pull устарел на {{ $labels.instance }}"
description: "Последний успешный запуск был более 15 минут назад."
Шаг 4. Безопасность и production-ready практики
-
SSH-less подход: используйте HTTPS с deploy key или token. Для token лучше использовать секреты в systemd:
systemctl edit ansible-pull.serviceДобавьте:
[Service] Environment="GIT_TOKEN=your_token_here" ExecStart=/usr/bin/ansible-pull -U https://%GIT_TOKEN%@git.example.com/infra.git main.yml -
Идемпотентность: плейбуки должны быть идемпотентными. Используйте
--checkи--diffв preflight:ExecStartPre=/usr/bin/ansible-pull -U https://git.example.com/infra.git main.yml --check --diff -
Логирование: направляйте stdout/stderr в journal, но для детального аудита настройте callback plugin в Ansible, который пишет в структурированный лог (JSON) в
/var/log/ansible-pull/. -
Ротация логов: добавьте файл в
/etc/logrotate.d/ansible-pull:/var/log/ansible-pull/*.log { weekly rotate 12 compress delaycompress missingok notifempty create 0640 root adm }
Заключение
Переход от cron к systemd для Ansible Pull — это не просто смена планировщика. Это переход к enterprise-уровню observability и надёжности. Systemd даёт:
- Единый источник истины для логов (journalctl)
- Зависимости и ordering
- Интеграцию с мониторингом
- Возможность декларативного управления через таймеры
Добавление Prometheus-экспортера и алертов превращает автономные узлы в наблюдаемую, контролируемую инфраструктуру, где отклонения детектируются автоматически.
Чек-лист production-ready
- Юниты systemd с правильными зависимостями (network-online)
- Persistent=true в таймере для компенсации пропущенных запусков
- Preflight с --check и --diff
- Prometheus-экспортер с метриками статуса и свежести
- Alerting rules для downtime и stale
- Структурированное логирование
- Ротация логов
- Управление секретами через systemd Environment или Vault
- Тестирование на staging перед rollout
Дата: 2026-10-12 | Категории: Автоматизация / Ansible, Системное администрирование | Теги: ansible, ansible-pull, cron, monitoring, production, pull, scalability, systemd