Задача — иметь перед глазами график в Grafana, который будет отображать расходы на AWS.
Есть два варианта — использовать експортер от Prometheus — prom/cloudwatch-exporter, или самописный от nachomillangarcia — prometheus_aws_cost_exporter.
Первый собирает метрики от AWS CloudWatch, в которые данные по биллингу поступают только на следующий день.
Второй написан на Python, ходит к AWS API, получает оттуда данные, и позволяет видеть расходы за сегодняшний день.
Сначала поднимем prometheus_aws_cost_exporter, который будет нам отображать данные по каждому сервису (EC2, RDS, S3, etc) за месяц, а потом добавим prom/cloudwatch-exporter, который будет отображать общий расход денег за сегодня.
Содержание
Запуск prometheus_aws_cost_exporter
Для проверки запускаем в Docker:
Ага — нет прав на выполнение API запроса GetCostAndUsage
.
Используем ЕС2 IAM profiles, см. пост AWS: ротация ключей IAM пользователей, EC2 IAM Roles и Jenkins и документацию тут>>>.
EC2 instance IAM profile
Переходим к ЕС2 с сервером мониторинга, правой кнопкой — Instance Settings > Attach/Replace IAM Role:
Копируем имя роли:
Переходим в IAM, находим её:
И подключенную к ней политику:
Копируем содержимое CloudWatchAgentServerPolicy, и создаём новую политику с правом на выполнение вызова ce:GetCostAndUsage
для ресурсов arn:aws:ce:*:*:/GetCostAndUsage
:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "cloudwatch:PutMetricData", "ec2:DescribeVolumes", "ec2:DescribeTags", "logs:PutLogEvents", "logs:DescribeLogStreams", "logs:DescribeLogGroups", "logs:CreateLogStream", "logs:CreateLogGroup", "ce:GetCostAndUsage" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "ssm:GetParameter" ], "Resource": [ "arn:aws:ssm:*:*:parameter/AmazonCloudWatch-*", "arn:aws:ce:*:*:/GetCostAndUsage" ] } ] }
Назовём её monitoring-cloudwatch-access-policy:
Переходим в Roles, создаём новую роль, назовём её monitoring-cloudwatch-access-role, и к ней подключаем созданную политику:
Возвращаемся к инстансу, подключаем новую роль в качеcтве EC2 IAM профиля:
Перезапускаем контейнер с експортером:
В последней строке сказано «Running on http://127.0.0.1:5000/» — значит доступен только из контейнера.
Запускаем с опцией --host 0.0.0.0
:
И проверяем метрики:
Окей — работает.
Docker Compose и Prometheus
Наш стек мониторинга запускается из Docker Compose файла:
И експортер хочется добавить сюда же.
Но есть проблема: стек мониторинга работает в сети prometehus:
version: '2.4' networks: prometheus: services: prometheus-server: image: prom/prometheus:v2.8.0 networks: - prometheus ports: - 9090:9090 ...
Експортер запускается на 127.0.0.1:
Но как из Prometehus достучаться к екпортеру?
Если внутри сети prometheus из контейнера с prometheus-сервером мы обратимся на 127.0.0.1:5000 — мы попадём в контейнер Prometheus, а не експортера.
А что бы попасть на контейнер с екпортером — нам надо в конфиге Prometheus использовать имя типа aws-exporter, как оно задано в Compose файле — тогда Docker сам выполнит разрешение имени aws-exporter в IP контейнера, и зароутит трафик.
Но внутри контейнера приложение-то всё-равно слушает 127.0.0.1 — и даже через внешний IP мы к нему доступ не получим.
Зная из документации експортера, что у нас там Flask — гуглим его переменные, и находим тут>>>:
Click is configured to load default values for command options from environment variables. The variables use the pattern FLASK_COMMAND_OPTION. For example, to set the port for the run command, instead of flask run —port 8000
Пробуем — добавляем в Compose файл переменную FLASK_RUN_HOST
:
... aws-exporter: image: nachomillangarcia/prometheus_aws_cost_exporter networks: - prometheus ports: - 5000:5000 environment: - METRIC_TODAY_DAILY_COSTS=yes - FLASK_RUN_HOST=0.0.0.0 restart: unless-stopped ...
В конфиге Prometheus добавляем новый таргет, используя aws-exporter, как имя хоста, что бы зарезолвить через Docker и его сеть:
... - job_name: 'aws-billing' metrics_path: '/metrics' static_configs: - targets: ['aws-exporter:5000'] ...
Перезапускаем стек, проверяем:
Проверяем метрику aws_today_daily_costs
— данные пошли:
CloudWatch exporter
Запуск екпортера уже описывался:
Prometheus: CloudWatch exporter — сбор метрик из AWS и графики в Grafana
Так что тут просто быстрый пример добавления сборов метрик биллинга.
Запускаем в us-east-1, N. Virgina, т.к. метрики биллинга CloudFormation собирает там (вообще это самый первый регион AWS).
У нас настройки харнятся в файле /etc/prometheus/prometheus-cloudwatch-exporter-us-east-1.yml
, добавляем в него AWS/Billing
:
set_timestamp: false delay_seconds: 60 metrics: - aws_namespace: "AWS/Billing" aws_dimensions: [Currency,ServiceName] aws_dimensions_select: Currency: [USD] aws_metric_name: EstimatedCharges aws_statistics: [Average] range_seconds: 86400 - aws_namespace: AWS/RDS aws_metric_name: FreeStorageSpace aws_dimensions: [DBInstanceIdentifier] ...
Перезапускаем, и проверяем метрику aws_billing_estimated_charges_average
:
Получаем значение по каждому сервису — на сколько денег сервис наработал с начала месяца.
Потом собираем всё в Grafana примерно так:
Можно выбрать только нужные метрики с регуляркой типа aws_billing_estimated_charges_average{service_name =~ "AmazonS3|AmazonRoute53"}
.
Готово.