Prometheus: yet-another-cloudwatch-exporter — сбор метрик AWS CloudWatch

Автор: | 07/21/2020
 

Сейчас в Prometehus мы собираем метрики из AWS CLoudWatch с помощью CloudWatch exporter от самого AWS, см. Prometheus: CloudWatch exporter — сбор метрик из AWS и графики в Grafana, однако, у него есть несколько недостатков:

  • написан на 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:

[default]
aws_region = us-east-2
aws_access_key_id = AKI***D4Q
aws_secret_access_key = QUC***BTI

Либо можно использовать AWS EC2 Instance Profile, но в его политику надо добавить разрешения на выполенние таких вызовов:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "CloudWatchExporterPolicy",
            "Effect": "Allow",
            "Action": [
                "tag:GetResources",
                "cloudwatch:ListTagsForResource",
                "cloudwatch:GetMetricData",
                "cloudwatch:ListMetrics"
            ],
            "Resource": "*"
        }
    ]
}

Создаём файл настроек самого експортёра:

discovery:
  jobs:
  - regions:
      - us-east-2
    type: elb
    enableMetricData: true
    metrics:
      - name: ActiveConnectionCount
        statistics:
        - Sum
        period: 300
        length: 600

Запускаем его:

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"}

И пробуем метрики:

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.

Например — оставим только теги:

discovery:
  exportedTagsOnMetrics:
    alb:
      - Name
      - kubernetes.io/service-name
      - ingress.k8s.aws/cluster
      - kubernetes.io/namespace
...

SeacrhTags

Также, можно граничить список ресурсов, с которых будем собирать метрики (аналог tag_selections в експортёре от AWS).

Например, ограничим выбор кластером «bttrm-eks-prod-1» — приводим файл к виду:

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

Проверяем:

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 — добавляем туда новый ексопртёр:

...
  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 — добавляем новый таргет:

...
scrape_configs:

  - job_name: 'yace-clouwatch-exporter'
    metrics_path: '/metrics'
    static_configs:
      - targets: ['yace-clouwatch-exporter:5000']
...

Проверяем таргет:

И метрики:

Графики в Grafana

И теперь можем использовать эти метрики в Grafana с выборкой по, например, окружению — dev, stage, prod (см. Grafana: создание dashboard):

А $env формируется из нашей лейблы ekscluster, которая добавляется ко всем ресурсам во время создания кластера из CloudFormation (см. AWS Elastic Kubernetes Service: автоматизация создания кластера, часть 1 — CloudFormation):

Готово.

Ссылки по теме