
Сервер заводится в Terraform. DNS-запись — в Terraform. База данных, сеть, права доступа — тоже. А монитор для этого же сервера почему-то заводится руками, через веб-форму, в отдельной вкладке, отдельным человеком, который вспомнил об этом на следующий день после релиза. Разрыв не архитектурный, а организационный — но именно он оставляет прод без наблюдения в первые часы после раскатки. Мы закрыли его официальным Terraform-провайдером: pingvera/pingvera опубликован в Terraform Registry, и монитор заводится тем же terraform apply, что и сама инфраструктура.
Провайдер зарегистрирован в публичном Terraform Registry под адресом pingvera/pingvera — ставить его в проект так же, как любой провайдер AWS или Cloudflare: указать source в required_providers, и Terraform сам скачает нужную платформу и проверит GPG-подпись релиза при terraform init. Никаких dev_overrides и локальной сборки — это готовый к использованию плагин, а не внутренний прототип.
terraform {
required_providers {
pingvera = {
source = "pingvera/pingvera"
version = "~> 0.1"
}
}
}
provider "pingvera" {
# endpoint по умолчанию https://app.pingvera.ru (RU-инстанс)
# для EN-инстанса: endpoint = "https://app.pingvera.com"
}
Токен передаётся через переменную окружения PINGVERA_TOKEN — атрибут token в конфигурации можно не указывать вовсе, и тогда в .tf-файлах секрета просто нет:
export PINGVERA_TOKEN=pv_...
terraform apply
Провайдер сознательно устроен просто: это клиент уже существующего write-API хаба (/api/v1/monitors, /api/v1/status-pages), а не отдельный слой бизнес-правил. Квоты тарифа, валидация полей, лимиты на количество сайтов — всё это по-прежнему считает сервер, провайдер лишь передаёт запрос и синхронизирует состояние.
pingvera_monitor — монитор любого из типов, что есть в дашборде: http, tcp, dns, tls, wp, domain, links, heartbeat. Обязательные поля — type и target, они неизменяемы после создания (правка требует пересоздания ресурса, как замена диска в облаке): нельзя молча превратить HTTP-монитор в TCP тем же id. Остальное — интервал, порог срабатывания, латентность деградации, теги, а для типов со своими настройками (например, wp) — сырой JSON в поле config.
resource "pingvera_monitor" "site" {
type = "http"
name = "Основной сайт"
target = "https://example.com"
interval_s = 60
fail_threshold = 2
degraded_latency_ms = 800
tags = ["prod", "website"]
config = jsonencode({
fail_on_4xx = true
})
}
resource "pingvera_monitor" "db" {
type = "tcp"
name = "PostgreSQL"
target = "db.example.com:5432"
}
pingvera_status_page — публичная статус-страница: слаг, заголовок, тема (в том числе тёмная), список привязанных мониторов, брендирование под свой цвет и текст в подвале. Список мониторов — это ссылки на другие ресурсы в том же конфиге, поэтому связь «статус-страница показывает вот эти три монитора» тоже становится кодом, а не ручным чекбоксом в дашборде:
resource "pingvera_status_page" "public" {
slug = "example"
title = "Статус example.com"
theme = "dark"
monitors = [
pingvera_monitor.site.id,
pingvera_monitor.db.id,
]
brand_color = "#4f46e5"
footer_md = "Вопросы — support@example.com"
}
Ценность IaC-подхода к мониторингу не в том, что HCL красивее веб-формы. Она в том, что монитор перестаёт быть отдельным действием, про которое можно забыть, и становится частью того же ревью, того же plan, того же apply, что и остальная инфраструктура. Заводите новый сервис в проекте — в том же пул-реквесте, рядом с ресурсом сервера или DNS-записью, добавляете pingvera_monitor на его health-check. Ревьюер видит оба изменения одним диффом: «добавили сервис» и «добавили за ним присмотр» — это одна логическая единица, а не два действия, разнесённые по разным интерфейсам и людям.
Для агентства, ведущего инфраструктуру нескольких клиентов через Terraform-модули, это ещё и способ не плодить расхождения между окружениями. Модуль «типовой WordPress-сайт клиента» может сразу включать нужный набор мониторов и статус-страницу — применили модуль к новому клиенту, получили не только сервер, но и наблюдение за ним, с одинаковыми порогами и одинаковой конвенцией именования для всех.
Самое частое возражение против IaC для существующей системы — «а у меня уже двадцать мониторов настроены руками, не пересоздавать же их». Не нужно: в CLI есть команда pingvera terraform generate, которая читает read-API кабинета и печатает готовый .tf с блоками resource "pingvera_monitor" и resource "pingvera_status_page" — и сразу с import-блоками на каждый ресурс (config-driven import, доступен с Terraform 1.5+), включая уже расставленные ссылки между статус-страницами и их мониторами.
export PINGVERA_TOKEN=pv_...
pingvera terraform generate --out pingvera.tf
terraform init
terraform apply # применит import-блоки, свяжет state с существующими ресурсами
terraform plan # ноль изменений — это и есть цель generate
После этого terraform plan должен не показать вообще никакого дрейфа — сгенерированный код описывает ровно то, что уже стоит в кабинете. Это не приближение и не «почти совпадает»: цель команды — получить состояние Terraform, которое с первого же прогона синхронно с реальностью, без ручной подгонки атрибутов после генерации.
Провайдер использует Terraform Plugin Framework и протокол 6.0 — подходит любой Terraform CLI версии 1.0 и новее. Для terraform import-блоков, которые печатает pingvera terraform generate, нужен Terraform 1.5+ (более ранние версии умеют импортировать только командой terraform import вручную, по одному ресурсу). Аутентификация — Bearer-токен из дашборда с нужными скоупами: write:monitors для управления мониторами, write:status-pages — для статус-страниц. Организация определяется самим токеном и нигде отдельно не передаётся.
Провайдер намеренно не тянет на себя то, что уже решено на уровне сервиса. Тарифные лимиты, проверку прав, антифрод — всё это делает хаб при обработке запроса, а не Terraform-схема; провайдер вернёт ровно ту ошибку API, что прислал сервер. Каналы уведомлений (Telegram, email, вебхуки) пока в схему не входят — сегодня это ресурсы для мониторов и статус-страниц, расширение на остальные сущности кабинета возможно позже, но не обещано датой.
Terraform-провайдер не меняет то, как работает мониторинг Pingvera — он меняет то, где живёт решение его завести. Вместо отдельного шага «не забыть поставить монитор после деплоя» — строчка в том же файле, что описывает сам сервис, под тем же ревью и с той же историей изменений в git. А если мониторинг уже настроен через дашборд — pingvera terraform generate заберёт его под управление кодом за одну команду, без переписывания вручную и без риска расхождения между тем, что реально стоит, и тем, что описано в конфигурации.
Два ресурса: pingvera_monitor (тип http/tcp/dns/tls/wp/domain/links/heartbeat, цель, интервал, пороги, теги, произвольный JSON-конфиг типа) и pingvera_status_page (slug, заголовок, тема, список привязанных мониторов, брендирование). Провайдер — чистый клиент write-API хаба, без своей бизнес-логики: квоты и тарифы проверяет сервер.
Командой pingvera terraform generate из CLI: она читает read-API кабинета и печатает готовый .tf с resource-блоками и import-блоками (Terraform 1.5+) на каждый монитор и статус-страницу, уже со связями между ними. После terraform apply состояние привязывается к существующим ресурсам, и первый terraform plan показывает ноль изменений.
В дашборде: Настройки → API-токены. Токену нужны скоупы write:monitors и/или write:status-pages в зависимости от того, какими ресурсами управляет конфигурация. Токен передаётся через переменную окружения PINGVERA_TOKEN — в .tf его хранить не стоит.
Provider pingvera/pingvera уже в Terraform Registry: ресурсы для мониторов всех типов и статус-страниц, аутентификация по API-токену со скоупами. Если мониторинг уже настроен в дашборде — pingvera terraform generate выгрузит его в HCL с import-блоками за одну команду.
Читайте также: API управления мониторингом: заводим сайты клиентов без рук в дашборде и Подписанные вебхуки: откуда получатель знает, что это правда Pingvera.