И почему самое дешёвое решение не всегда правильное - но правильное решение должно хотя бы пережить человека, который его заказал.
Контекст
Стартап пришёл к нам с типичным запросом: продукт работает, клиенты есть, пора делать всё по-человечески. IaC, безопасность, автоматизация, воспроизводимость.
Стандартный стек: несколько Lambda-функций, пара EC2, RDS, с десяток S3-бакетов, Cognito, DynamoDB, Glue, Amplify, API Gateway. Ничего экзотического.
Мы сделали Terraform, GitHub Actions пайплайны, чистое разделение окружений. Всё развернули в dev, проверили, выглядит хорошо.
Потом дошли до метрик.
“Нам нужна Grafana”
У них были стандартные Lambda-метрики в CloudWatch - invocations, duration, errors, throttles, стандартный набор из документации AWS. Никаких кастомных метрик, ничего необычного.
Мы начали строить CloudWatch-дашборды. Разумный выбор: данные уже там, никакой лишней инфраструктуры, нативная интеграция с AWS.
Потом на созвоне:
«Нам нужна Grafana. Я привык к Grafana, мне там удобнее, давайте сделаем в Grafana.»
Это сказал проджект-менеджер.
Ну… окей. Раз уж это так важно…
Что значит “просто Grafana” на ECS
Дело в том, что запустить Grafana-стек на AWS ECS - это не “просто Grafana”. Нужна вся экосистема.
В итоге получилось:
- Victoria Metrics - TSDB для хранения метрик, Prometheus-совместимая, отличное сжатие
- VMAlert - движок алертинга поверх Victoria Metrics
- Loki - агрегация логов, данные хранятся в S3, индексируются только лейблы
- Grafana - визуализация, подключается к Victoria Metrics и Loki
- Blackbox Exporter - probe-мониторинг HTTP/TCP эндпоинтов
- Yet Another CloudWatch Exporter (YACE) - про него отдельно
Почему YACE, а не нативный CloudWatch datasource?
У Grafana есть встроенный плагин для CloudWatch, но он не подошёл. Нативный плагин делает запросы в CloudWatch при каждом обновлении дашборда - то есть API-затраты и задержки при каждой загрузке панели. И главное - он возвращает метрики в формате CloudWatch, без лейблов, нужных для нормальных Prometheus-стиль дашбордов.
YACE решает это правильно: собирает метрики CloudWatch по расписанию, обогащает нужными лейблами (имя функции, окружение, сервис - что угодно), и пушит всё в Victoria Metrics. Оттуда Grafana запрашивает PromQL, как с любым другим Prometheus-источником. Чисто, быстро, консистентно.
Пайплайн приёма логов
Для логов нужны два отдельных пайплайна:
CloudWatch Logs: Мы прикрепили subscription filter к каждой лог-группе. Это триггерит Lambda при каждом обновлении логов - без поллинга, без API-вызовов по расписанию. Terraform-код не самый элегантный (for_each по каждой лог-группе с Lambda permission и subscription filter на каждую группу), но надёжно и экономично.
CloudTrail: CloudTrail пишет в S3, поэтому мы использовали S3 bucket notifications для триггера отдельной Lambda, которая парсит и шлёт события в Loki.
Обе Lambda распаковывают, парсят, обогащают лейблами и форвардят в Loki. Разделённый подход сохранял чистоту и не заставлял одну Lambda обрабатывать два совершенно разных формата данных и типа триггеров.
Вспомогательная инфраструктура:
- 3x EFS-тома (дашборды/плагины Grafana, индексы Loki, данные Victoria Metrics)
- 2x S3-бакета (хранение логов Loki, источник CloudTrail)
- ECR (кастомные Docker-образы - подробнее ниже)
- GitHub Actions пайплайны для сборки образов
- S3 VPC endpoint (трафик Loki в S3 НЕ должен идти через NAT Gateway)
- Service discovery, SSM Parameter Store для секретов
Проблема ConfigMap в ECS
Kubernetes позволяет монтировать конфиг-файлы как ConfigMaps прямо в контейнеры. В ECS такого понятия нет - поэтому любое изменение конфига означает пересборку и перезапуск.
Любое изменение конфига - datasource Grafana, политика ретеншена Loki, правило VMAlert - требует:
- Обновить конфиг
- Пересобрать Docker-образ
- Запушить в ECR
- Обновить task definition в ECS
- Передеплоить сервис и ждать, пока задачи перезапустятся
Альтернативы есть. Можно монтировать конфиги через EFS - но чтобы положить файлы на EFS, нужно поднять EC2-инстанс в нужном VPC с правильными security groups и IAM. Работает, но автоматизировать это на удивление сложно, особенно в IaC-first подходе. Мы пробовали вариант с S3-at-startup (entrypoint-скрипт тянет конфиг при старте контейнера), но это добавляет IAM-разрешения и движущихся частей. В итоге конфиги, зашитые в образ, с циклом пересборки оказались наиболее предсказуемым вариантом - пусть и не самым изящным.
Итого времени на сборку, настройку и “чтобы красиво”: примерно месяц инженерной работы.
Хотя красиво получилось.
Бонус: страница статуса
Заодно попросили сделать статус-страницу.
Мы написали Python Lambda, которая каждые 5 минут берёт предрасчитанные метрики из Victoria Metrics, генерирует HTML-страницу и загружает её в S3 за CloudFront. Просто, надёжно, стоит почти ничего - при условии, что Victoria Metrics уже работает.
Это последнее условие станет важным позже.
Шесть месяцев спустя
PM, которому “нужна была Grafana”, ушёл из проекта.
На очередном ревью стоимости кто-то заметил строчку: примерно $2 000 в год только за инфраструктуру стека мониторинга. Не считая месяца работы на его создание. Не считая сопровождения и изменений конфигов через пересборку образов.
Решение было очевидным: мигрировать обратно на CloudWatch-дашборды.
А та Lambda статус-страницы, которая тянула данные из Victoria Metrics? Поскольку Victoria Metrics уходила, её тоже надо было переписать - под CloudWatch. Ещё одна вещь для миграции, следствие плотной связности.
В итоге статус-страницу заменили бесплатным внешним сервисом. Проще.
Чисто. Готово. $2k в год сэкономлено.
Но это провал?
Вот где история становится интереснее, чем просто “дорогая ошибка, урок извлечён”.
Это не был провал.
За те шесть месяцев с нормальными дашбордами, алертами и агрегацией логов команда нашла узкие места, о которых не знала. Проблемы с холодными стартами Lambda. Неэффективные запросы. Функции, работающие дольше, чем надо.
Исправили. Быстрее Lambda - дешевле Lambda. Улучшения производительности почти наверняка отбили больше $2 000 в год на compute-затратах.
Но - и это главное - те же самые выводы были доступны в CloudWatch всё это время.
Узкие места не требовали Grafana для обнаружения. Они требовали смотреть, а смотреть начали, потому что появились дашборды. CloudWatch-дашборды дали бы тот же импульс к расследованию.
Реальное сравнение стоимостей
Давайте поставим реальные цифры для похожего стека: 50 Lambda-функций, 2 EC2, 1 RDS, 10 S3-бакетов, 1 EFS. Регион: us-east-1.
CloudWatch: ~$35–40 в месяц
- Lambda-метрики (стандартные): $0 (бесплатно)
- EC2 detailed monitoring: ~$5
- RDS + S3 метрики: ~$3
- Lambda-логи (~20 ГБ/мес): ~$8
- EC2 + RDS логи (~10 ГБ/мес): ~$3
- CloudTrail ingestion: ~$2
- Алерты (40 alarms): ~$4
- Дашборды (2 дополнительных): ~$6
- Хранение/архив логов: ~$1
Grafana на ECS: ~$105–145 в месяц
- Lambda-метрики: $0 (через YACE)
- EC2 + RDS + S3 метрики: $0
- Lambda-логи (~20 ГБ/мес): ~$1 (S3 через Loki)
- EC2 + RDS логи (~10 ГБ/мес): ~$0.3 (S3)
- CloudTrail ingestion: ~$1 (Lambda + S3)
- Алерты: $0 (VMAlert)
- Дашборды: $0
- Хранение/архив логов: ~$0.7 (S3)
- Инфраструктура ECS: ~$80–120
- EFS-тома: ~$15
- ECR-хранилище: ~$2
- API-вызовы YACE в CloudWatch: ~$1
Grafana Cloud: ~$31–35 в месяц
- Lambda-метрики (стандартные): $0 (включено)
- EC2 + RDS + S3 метрики: $0
- Lambda-логи (~20 ГБ/мес): ~$6
- EC2 + RDS логи (~10 ГБ/мес): $0 (в бесплатном тире)
- CloudTrail ingestion: ~$2 (Lambda + S3)
- Алерты: $0 (Grafana Alerting)
- Дашборды: $0
- Хранение логов: включено
- Pro-план: $19/мес
- YACE / CloudWatch plugin: ~$1–5
Несколько важных нюансов:
Затраты на CloudWatch обманчиво переменчивы. Оценка $35–40 предполагает, что вы не используете кастомные метрики активно. Включите Container Insights на ECS - и получите ~150 кастомных метрик на кластер, это $45/мес, добавленных незаметно. Используете Lambda EMF в масштабе - легко получить тысячи кастомных метрик до того, как осознаете. По $0.30/метрика/мес это накапливается быстро.
Grafana на ECS имеет фиксированный нижний порог стоимости, который не растёт с объёмом данных. Если вы генерируете 400+ кастомных метрик, математика переворачивается - $120/мес только на кастомные метрики CloudWatch против той же инфраструктурной стоимости ECS вне зависимости от количества метрик.
Grafana Cloud выигрывает по цене для этого масштаба - но стоимость растёт линейно, как только превысите 10k активных серий или 50 ГБ логов/мес. Для стартапа такого размера это, вероятно, наиболее экономичный управляемый вариант.
Data transfer в основном не проблема, если планировать заранее. У S3 есть бесплатный Gateway VPC Endpoint. С ним трафик Loki в S3 не стоит ничего дополнительно. YACE обращается к CloudWatch API через NAT Gateway (у CloudWatch нет Gateway Endpoint), но фактический объём данных небольшой - если NAT Gateway уже существует по другим причинам, это фактически бесплатно.
“Я хочу X” - и что с этим делать
В инфраструктурном консалтинге часто слышишь: “нам нужна Grafana”, “надо переходить на Kubernetes”, “давайте всё разобьём на микросервисы”.
Эти запросы приходят из разных мест. Иногда реальные технические требования. Иногда личное знакомство с инструментом. Иногда статья, которую кто-то прочитал на прошлой неделе.
Работа не в том, чтобы говорить нет. Работа в том, чтобы спросить:
Какую проблему мы на самом деле решаем? В данном случае: видимость производительности приложения. И CloudWatch, и Grafana решают это. Разница - в стоимости, времени настройки и операционной сложности.
Кто владеет этим долгосрочно? Система, построенная вокруг предпочтений одного человека - это риск, когда этот человек уходит. Это не критика кого-либо - просто реальный фактор в совокупной стоимости владения, который редко попадает в архитектурное обсуждение.
Какой самый простой путь к результату? Иногда скучное решение - правильное решение. Иногда заплатить больше за что-то лучшее абсолютно оправдано - лучший UX ведёт к лучшим привычкам наблюдаемости, что ведёт к реальным улучшениям производительности. Хитрость в том, чтобы знать, какая ситуация до того, как провести месяц за созданием.
В данном случае Grafana-стек не был неправильным. Он принёс реальную ценность. Просто был оптимизирован под неправильное ограничение.
Скрытые затраты
$2 000 в год на инфраструктуру были видны в AWS-счёте. Что не было видно:
- Месяц инженерного времени на создание изначального стека
- Постоянное обслуживание: изменения конфигов требовали пересборки образов и передеплоя
- Lambda статус-страницы, которую пришлось переписывать при уходе Victoria Metrics - тесная связность, которая не была очевидна до момента миграции
- Институциональные знания, которые ушли вместе с PM и инженером, который это строил
Ни одно из этого не отображается строчкой. Все они - реальные затраты.
Перед следующим инфраструктурным решением
Самые дорогие инфраструктурные ошибки, которые я вижу - не очевидные. Не случайно оставленный большой EC2-инстанс, не забытые lifecycle-политики S3, не включённый Container Insights в CloudWatch, который неожиданно генерирует сотни кастомных метрик.
Дорогие ошибки - архитектурные: системы, построенные под предпочтения одного человека, сложность добавленная без чёткого анализа затрат и выгод, решения, которые работают отлично пока не уходит человек, который их создал.
Аудит инфраструктуры - посмотреть что реально работает, сколько стоит, кто от этого зависит, и выполняет ли это свою изначальную задачу - одно из самых высокодоходных вложений для растущего стартапа.
Иногда находишь Grafana-налог $2 000 в год.
Иногда находишь что-то значительно дороже.
Помогаю командам аудировать и оптимизировать AWS-инфраструктуру: затраты, пробелы в безопасности, архитектурный долг и системы, пережившие свою изначальную цель. Если эта история звучит знакомо - поговорим.
