← Все гайды AI Release
EN Подписаться на @ai_release1

Как настроить ИИ-мониторинг расходов на облако: AWS, Azure и GCP

Обновлено: 22.10.2026 · AI Release · @ai_release1
AI Release

TL;DR

Идея схемы: нативные инструменты каждого облака собирают факты о расходах → складываем их в одно хранилище → LLM раз в сутки читает выгрузку и объясняет аномалии человеческим языком → алерт уходит в чат. ИИ здесь не заменяет биллинг, а интерпретирует его.

ОблакоБюджетыАномалииДетальная выгрузка
AWSAWS BudgetsCost Anomaly DetectionCost and Usage Report (CUR) → S3
AzureAzure Budgets (Cost Management)Cost Anomaly Alerts в Cost ManagementExports в Storage Account
GCPCloud Billing Budgetsоповещения бюджета по порогамBigQuery Billing Export

Требования и подготовка

Иллюстрация к разделу «Требования и подготовка»
Иллюстрация к разделу «Требования и подготовка»

Что сделать: проверить, что CLI видят нужные аккаунты.

Зачем: 80% ошибок настройки — работа не в том аккаунте/подписке, где лежат расходы.

Как проверить:

aws sts get-caller-identity
az account show --query "{name:name, id:id}" -o table
gcloud config list --format="value(core.account,core.project)"

Пример: aws sts get-caller-identity печатает "Account": "111122223333" — этот номер понадобится в --account-id. Если номер не тот, что в консоли Billing, переключите профиль: export AWS_PROFILE=<профиль>.

Чек-лист перед стартом:

Шаг 1. Включить нативные бюджеты и экспорты в AWS, Azure и GCP

Иллюстрация к разделу «Шаг 1. Включить нативные бюджеты и экспорты в AWS, Azure и GCP»
Иллюстрация к разделу «Шаг 1. Включить нативные бюджеты и экспорты в AWS, Azure и GCP»

Что сделать: создать по одному бюджету с порогами и включить детальные выгрузки.

Зачем: LLM не умеет опрашивать биллинг «напрямую» — ему нужны файлы с данными. Нативные бюджеты дают быстрый алерт, выгрузки — материал для анализа.

Как проверить: после каждого блока — команда list/describe возвращает созданный объект.

AWS: бюджет с двумя порогами (50% и 100% от суммы, которую вы задаёте сами).

cat > budget.json <<'JSON'
{
  "BudgetName": "monthly-guard",
  "BudgetLimit": {"Amount": "500", "Unit": "USD"},
  "TimeUnit": "MONTHLY",
  "BudgetType": "COST"
}
JSON

cat > notifications.json <<'JSON'
[
  {"Notification": {"NotificationType": "ACTUAL", "ComparisonOperator": "GREATER_THAN", "Threshold": 50, "ThresholdType": "PERCENTAGE"},
   "Subscribers": [{"SubscriptionType": "EMAIL", "Address": "<ваш-email>"}]},
  {"Notification": {"NotificationType": "ACTUAL", "ComparisonOperator": "GREATER_THAN", "Threshold": 100, "ThresholdType": "PERCENTAGE"},
   "Subscribers": [{"SubscriptionType": "EMAIL", "Address": "<ваш-email>"}]}
]
JSON

aws budgets create-budget --account-id 111122223333 \
  --budget file://budget.json \
  --notifications-with-subscribers file://notifications.json

Проверка: aws budgets describe-budgets --account-id 111122223333 — в выводе "BudgetName": "monthly-guard". Сумма 500 — пример, подставьте свой месячный лимит.

Детальная выгрузка AWS (CUR) в S3:

aws cur put-report-definition --report-definition '{
  "ReportName": "cur-daily",
  "TimeUnit": "DAILY",
  "Format": "Parquet",
  "Compression": "Parquet",
  "S3Bucket": "<ваш-бакет>",
  "S3Prefix": "cur",
  "S3Region": "eu-central-1",
  "AdditionalArtifacts": ["ATHENA"],
  "RefreshClosedReports": true,
  "ReportVersioning": "OVERWRITE_REPORT"
}'

Проверка: aws cur describe-report-definitions — статус отчёта. Первая выгрузка появляется не мгновенно; точный SLA и текст bucket policy для бакета сверьте с документацией AWS.

Azure: бюджет на подписке.

az consumption budget create \
  --budget-name monthly-guard \
  --amount 500 \
  --time-grain Monthly \
  --start-date 2025-01-01 --end-date 2026-01-01 \
  --category Cost

Проверка: az consumption budget list -o table — строка monthly-guard. Набор флагов в разных версиях Azure CLI отличается — при ошибке разбора аргументов сверьтесь с az consumption budget create -h.

GCP: бюджет с порогами и публикацией в Pub/Sub (топик нужен, чтобы алерт можно было обработать кодом, а не только письмом).

gcloud pubsub topics create budget-alerts
gcloud billing budgets create \
  --billing-account=<BILLING_ACCOUNT_ID> \
  --display-name=monthly-guard \
  --budget-amount=500USD \
  --threshold-rule=percent=0.5 \
  --threshold-rule=percent=1.0 \
  --pubsub-topic=projects/<ваш-проект>/topics/budget-alerts

Проверка: gcloud billing budgets list --billing-account=<BILLING_ACCOUNT_ID> — бюджет в списке. Почему это работает: бюджеты — это правила на стороне биллинга, они срабатывают независимо от вашего кода, поэтому не «замолчат», если упадёт скрипт.

Шаг 2. Свести данные в BigQuery и подключить ИИ-разбор

Что сделать: включить экспорт биллинга GCP в BigQuery, а сводку по трём облакам раз в сутки отправлять в LLM.

Зачем: BigQuery — самый простой «общий стол» для агрегатов; из AWS и Azure забираем уже готовые итоги по сервисам и складываем их туда же или в локальный JSON.

Как проверить: таблица в BigQuery существует и по ней проходит запрос за вчера.

В консоли GCP: Billing → Billing export → BigQuery export → выбрать датасет. После включения появится таблица вида <проект>.<датасет>.gcp_billing_export_v1_<BILLING_ACCOUNT_ID>.

bq query --use_legacy_sql=false '
SELECT service.description AS service, ROUND(SUM(cost), 2) AS cost_usd
FROM `<проект>.<датасет>.gcp_billing_export_v1_<BILLING_ACCOUNT_ID>`
WHERE invoice.month = FORMAT_DATE("%Y%m", CURRENT_DATE())
GROUP BY service
ORDER BY cost_usd DESC
LIMIT 10'

Пример вывода: строки Compute Engine | 214.37, Cloud Storage | 31.02 — это топ сервисов за текущий месяц.

Теперь сборщик сводки. Он берёт AWS-итоги через Cost Explorer, Azure — через CLI, GCP — через bq, склеивает в один JSON и отправляет в LLM:

import json, os, subprocess, urllib.request

def aws_totals():
    out = subprocess.check_output([
        "aws", "ce", "get-cost-and-usage",
        "--time-period", "Start=2025-01-01,End=2025-02-01",
        "--granularity", "MONTHLY",
        "--metrics", "UnblendedCost",
        "--group-by", "Type=DIMENSION,Key=SERVICE"], text=True)
    return json.loads(out)

def azure_totals():
    out = subprocess.check_output([
        "az", "consumption", "usage", "list", "--top", "50", "-o", "json"], text=True)
    return json.loads(out)

payload = {"aws": aws_totals(), "azure": azure_totals()}
prompt = ("Ты аналитик облачных расходов. Найди в данных три самых дорогих сервиса, "
          "укажи долю каждого в процентах и одну гипотезу причины роста. "
          "Если данных для вывода не хватает — так и напиши. Данные: "
          + json.dumps(payload)[:20000])

req = urllib.request.Request(
    os.environ["LLM_API_URL"],
    data=json.dumps({"model": os.environ["LLM_MODEL"],
                     "messages": [{"role": "user", "content": prompt}]}).encode(),
    headers={"Content-Type": "application/json",
             "Authorization": "Bearer " + os.environ["LLM_API_KEY"]})

print(json.loads(urllib.request.urlopen(req).read())["choices"][0]["message"]["content"])

Формат тела запроса у разных провайдеров отличается — поля messages/choices сверьте с документацией. Обрезка [:20000] символов нужна, чтобы не упереться в лимит контекста и не платить за мегабайты JSON.

Почему это работает: LLM не считает деньги — она получает уже посчитанные суммы и ищет в них закономерности. Если суммы неверны, ответ тоже будет неверным, поэтому проверка из Шага 3 обязательна.

Шаг 3. Проверка работы и финальный результат

Иллюстрация к разделу «Шаг 3. Проверка работы и финальный результат»
Иллюстрация к разделу «Шаг 3. Проверка работы и финальный результат»

Что сделать: прогнать сборщик и убедиться, что алерт доходит до чата.

Зачем: «настроено» и «работает» — разные вещи; нужен наблюдаемый результат.

Как проверить:

python collect.py > report.json 2>err.log
head -c 400 report.json

Успех выглядит так: в report.json три строки с суммами по облакам и абзац текста от модели, где названы самые дорогие сервисы. err.log пуст.

Дальше проверяем путь алерта. Простейший способ доставки в Telegram — бот, тот же приём, что в гайде как настроить мониторинг VPS через Telegram-бота с Mini App.

curl -s -X POST "https://api.telegram.org/bot<ТОКЕН>/sendMessage" \
  -d chat_id=<CHAT_ID> \
  --data-urlencode text="$(python -c 'import json;print(json.load(open("report.json"))["summary"])')"

Проверка: сообщение появилось в чате в течение нескольких секунд. Если появилось — цепочка «выгрузка → сводка → LLM → чат» замкнута.

Финальный результат: раз в сутки приходит сообщение с тремя самыми дорогими сервисами и гипотезой роста, а при превышении 50% и 100% бюджета срабатывает нативный алерт облака. Расписание ставим через cron:

0 7 * * * cd /opt/costbot && /usr/bin/python3 collect.py >> run.log 2>&1

Возможные проблемы и решения

Проблема. Бюджет AWS не создаётся

aws iam attach-user-policy --user-name bot \
  --policy-arn arn:aws:iam::aws:policy/AWSBudgetsActionsWithAWSResourceControlAccess

Точный список действий, если нужна своя политика, сверьте с документацией AWS.

Проблема. Azure отклоняет создание бюджета

az role assignment create --assignee <object-id> \
  --role "Cost Management Contributor" \
  --scope /subscriptions/<SUBSCRIPTION_ID>

Проблема. GCP не принимает бюджет с Pub/Sub

gcloud auth list
gcloud billing accounts list

Резюме и следующие шаги

Нативные бюджеты и выгрузки трёх облаков дают проверяемые цифры, а LLM превращает их в короткое объяснение раз в сутки. Дальше стоит связать ИИ-разбор с лимитами на сам API и добавить в отчёт разбивку по тегам проектов, чтобы аномалия сразу указывала на команду.

FAQ

Чем AWS Budgets отличается от Cost Anomaly Detection?

Budgets сравнивает фактические расходы с заданным вами порогом, а Cost Anomaly Detection ищет отклонения от обычного поведения без ручного порога. Обычно включают оба: бюджет ловит общий перерасход, детектор — локальный всплеск по сервису. Точные настройки детектора сверьте с документацией AWS.

Нужен ли отдельный платный сервис для ИИ-мониторинга облака?

Нет. Схема из гайда собирается из нативных бюджетов, экспортов и обычного вызова LLM API. Платите только за токены и за хранение выгрузок.

Можно ли получать алерты в Telegram, а не на email?

Да. Нативные уведомления оставляем как страховку, а текст от модели отправляем ботом через sendMessage. Готовый рецепт бота — в связанном гайде по мониторингу VPS.

Как часто обновляются данные о расходах?

Зависит от облака и типа выгрузки: экспорт GCP в BigQuery и CUR в AWS обновляются не мгновенно, у Azure Exports тоже есть задержка. Для суточного отчёта это не критично, но точный интервал сверьте с документацией каждого провайдера.

🤖 Кратко для ИИ