Thank you for reading this post, don't forget to subscribe!
Сейчас в Prometehus мы собираем метрики из AWS CLoudWatch с помощью CloudWatch exporter от самого AWS, однако, у него есть несколько недостатков:
- написан на Java, тяжёлый – грузит хост мониторнига
- не подтягивает теги
- использует
GetMetricStatistics
для получения метрик - умеет собирать метрики только из одного региона – для нескольких регионов потребутеся запускать несколько експортёров
Что бы избавиться от этих проблем – используем вместо него yet-another-cloudwatch-exporter
.
AWS CloudWatch – недостатки
Tags
Первое, что крайне неудобно – это отсутствие тегов в метриках, собираемых дефолтным експортёром.
Например, Application Load Balancer возвращается в таком виде:
Тогда как у самого ALB тегов намного больше:
И сейчас в Grafana нет никакой возможности эти теги использовать для выборки.
GetMetricStatistics
vs GetMetricData
Второй нюанс – это то, как експортер собирает метрики, т.к. он использует AWS API GetMetricStatistics
.
Два года тому была открыта issue Reduce cost of api operations by using GetMetricData API instead of GetMetricStatistics API – но воз и ныне там.
Проблема заключается в том, что при GetMetricStatistics
на каждую метрику выполняется отдельный API-запрос.
Т.е., если у вас 100 ЕС2-инстансов, и у каждого 10 метрик – то cloudwatch-exporter
будет выполнять 1000 запросов каждые 60 секунд, что в результате выливается в приличные деньги:
В отличии от AWS cloudwatch-exporter
, в yet-another-cloudwatch-exporter
используется запрос GetMetricData
, который позволяет получить до 500 метрик при выполнении единого запроса.
Запуск yet-another-cloudwatch-exporter
Попробуем получить данные.
Создаём файл с данными доступа к AWS, назовём его alb-cred:
1 2 3 4 |
[default] aws_region = us-east-2 aws_access_key_id = AKI***D4Q aws_secret_access_key = QUC***BTI |
Либо можно использовать AWS EC2 Instance Profile, но в его политику надо добавить разрешения на выполенние таких вызовов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
{ "Version": "2012-10-17", "Statement": [ { "Sid": "CloudWatchExporterPolicy", "Effect": "Allow", "Action": [ "tag:GetResources", "cloudwatch:ListTagsForResource", "cloudwatch:GetMetricData", "cloudwatch:ListMetrics" ], "Resource": "*" } ] } |
Создаём файл настроек самого експортёра:
1 2 3 4 5 6 7 8 9 10 11 12 |
discovery: jobs: - regions: - us-east-2 type: elb enableMetricData: true metrics: - name: ActiveConnectionCount statistics: - Sum period: 300 length: 600 |
Запускаем его:
1 2 3 |
docker run -ti -p 5000:5000 -v /home/setevoy/Temp/alb-cred:/exporter/.aws/credentials -v /home/setevoy/Temp/config.yaml:/tmp/config.yml quay.io/invisionag/yet-another-cloudwatch-exporter:v0.19.1-alpha {"level":"info","msg":"Parse config..","time":"2020-07-21T10:59:49Z"} {"level":"info","msg":"Startup completed","time":"2020-07-21T10:59:49Z"} |
И пробуем метрики:
1 2 3 4 5 6 7 8 |
curl localhost:5000/metrics HELP aws_elb_info Help is not implemented yet. TYPE aws_elb_info gauge aws_elb_info{name="arn:aws:elasticloadbalancing:us-east-2:534***385:loadbalancer/app/fea06ba9-eksstage1mealplan-a584/***",tag_Env="",tag_Name="",tag_Stack="",tag_ingress_k8s_aws_cluster="bttrm-eks-stage-1",tag_ingress_k8s_ aws_resource="LoadBalancer",tag_ingress_k8s_aws_stack="eks-stage-1-mealplan-api-ns/mealplan-api-ingress",tag_kubernetes_io_cluster_bttrm_eks_dev_0="",tag_kubernetes_io_cluster_bttrm_eks_dev_1="",tag_kubernetes_io_cluster_bttrm_eks_prod_0= "",tag_kubernetes_io_cluster_bttrm_eks_prod_1="",tag_kubernetes_io_cluster_bttrm_eks_stage_1="owned",tag_kubernetes_io_cluster_eksctl_bttrm_eks_production_1="",tag_kubernetes_io_ingress_name="mealplan-api-ingress",tag_kubernetes_io_namesp ace="eks-stage-1-mealplan-api-ns",tag_kubernetes_io_service_name=""} 0 ... |
Теперь видим все теги.
Настройка yet-another-cloudwatch-exporter
exportedTagsOnMetrics
Список тегов, которые експортер будет получать вместе с метриками может быть ограничен exportedTagsOnMetrics
.
Например – оставим только теги:
1 2 3 4 5 6 7 8 |
discovery: exportedTagsOnMetrics: alb: - Name - kubernetes.io/service-name - ingress.k8s.aws/cluster - kubernetes.io/namespace ... |
SeacrhTags
Также, можно граничить список ресурсов, с которых будем собирать метрики (аналог tag_selections
в експортёре от AWS).
Например, ограничим выбор кластером “bttrm-eks-prod-1” – приводим файл к виду:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
discovery: exportedTagsOnMetrics: alb: - Name - kubernetes.io/service-name - ingress.k8s.aws/cluster - kubernetes.io/namespace jobs: - type: alb regions: - us-east-2 searchTags: - Key: ingress.k8s.aws/cluster Value: bttrm-eks-prod-1 metrics: - name: UnHealthyHostCount statistics: [Maximum] period: 60 length: 600 - name: ActiveConnectionCount statistics: [Sum] period: 300 length: 600 |
Проверяем
1 2 3 4 5 6 7 |
curl localhost:5000/metrics HELP aws_alb_active_connection_count_sum Help is not implemented yet. TYPE aws_alb_active_connection_count_sum gauge aws_alb_active_connection_count_sum{dimension_LoadBalancer="app/bcf678a9-eksprod1bttrmapps-447a/***",name="arn:aws:elasticloadbalancing:us-east-2:534***385:loadbalancer/app/bcf678a9-eksprod1bttrmapps-***",region="us-east-2",tag_Name="",tag_ingress_k8s_aws_cluster="bttrm-eks-prod-1",tag_kubernetes_io_namespace="eks-prod-1-bttrm-apps-ns",tag_kubernetes_io_service_name=""} 112 ... aws_alb_tg_un_healthy_host_count_maximum{dimension_LoadBalancer="app/bcf678a9-eksprod1bttrmapps-447a/***",dimension_TargetGroup="targetgroup/bcf678a9-9b32ce4accea2525b4d/e0f341421a33a453",name="arn:aws:elasticloadbalancing:us-east-2:534***385:targetgroup/bcf678a9-9b32ce4accea2525b4d/e0f341421a33a453",region="us-east-2",tag_Name="",tag_ingress_k8s_aws_cluster="bttrm-eks-prod-1",tag_kubernetes_io_namespace="eks-prod-1-bttrm-apps-ns",tag_kubernetes_io_service_name="bttrm-apps-backend-svc"} 0 ... |
Теперь получаем метрики только с одного кластера, и только нужными нам тегами.
Запуск в Prometheus
У нас весь стек мониторинга запускается из Docker Compose – добавляем туда новый ексопртёр:
1 2 3 4 5 6 7 8 9 10 |
... yace-clouwatch-exporter: image: quay.io/invisionag/yet-another-cloudwatch-exporter:v0.19.1-alpha networks: - prometheus ports: - 5000:5000 volumes: - /etc/prometheus/prometheus-yace-cloudwatch-exporter.yaml:/tmp/config.yml:ro restart: unless-stopped |
Обновляем конфиг самого Prometheus – добавляем новый таргет:
1 2 3 4 5 6 7 8 |
... scrape_configs: - job_name: 'yace-clouwatch-exporter' metrics_path: '/metrics' static_configs: - targets: ['yace-clouwatch-exporter:5000'] ... |
Проверяем таргет:
И метрики:
Графики в Grafana
И теперь можем использовать эти метрики в Grafana с выборкой по, например, окружению – dev, stage, prod
А $env
формируется из нашей лейблы ekscluster
, которая добавляется ко всем ресурсам во время создания кластера из CloudFormation :
Готово