Data/Airflow

[Airflow] StatsD Exporter + Prometheus + Grafana On GKE

운호(Noah) 2023. 11. 17. 17:27

들어가기 앞서,

  • Airflow 운영에 있어서 Airflow 모니터링은 중요한 요소이며, 모니터링은 크게 두 가지 측면으로 구분할 수 있습니다.
    • 서비스 측면 (Airflow 컨테이너 동작 여부, DAG 정상 실행 여부 등)
    • 시스템 측면 (CPU, Memory 등)
  • 해당 포스팅에선 Airflow의 서비스 측면 모니터링을 위해, StatsD Exporter + Prometheus + Grafana를 구성하는 방법에 대해서 다뤄보겠습니다.
    • StatsD Exporter
      • StatsD는 애플리케이션에서 발생하는 이벤트 및 성능 지표를 수집하고, 이를 모니터링 시스템에 전송하는 데 사용되는 네트워크 데몬 및 프로토콜입니다.
      • Airflow 내부적으로 생성된 Metric은, StatsD를 통해 StatsD Exporter에 Push 됩니다.
      • StatsD Exporter는 StatsD에서 전송된 메트릭을 Prometheus가 이해할 수 있는 형식으로 변환하여 제공하는 중간자 역할입니다.
    • Prometheus
      • Prometheus는 모니터링 시스템 및 Timeseries 데이터용 데이터베이스입니다.
      • 오픈소스로, 메트릭 수집 및 대시보드를 구축하는데 Grafana와 함께 많이 사용합니다.
    • Grafana
      • Grafana는 대시보드 툴입니다.
      • 시계열 데이터에 대한 대시보드에 특화되어 있는 대시보드 툴이며 Graphite, InfluxDB, Prometheus 등을 지원합니다.

사전 구성 환경

StatsD Exporter + Prometheus + Grafana 구조

  • Airflow 내부적으로 생성된 Metric은, StatsD를 통해 StatsD Exporter에 Push 됩니다.
  • StatsD Exporter는 StatsD로부터 받은 Metric을 저장해둡니다.
  • Prometheus는 StatsD Exporter가 저장하고 있는 Airflow Metric을 주기적으로 Scrape(Pull) 합니다.
  • Grafana는 Prometheus에 저장된 Airflow Metric을 Pull 하여 대시보드를 구성합니다.

진행 순서

  • StatsD Exporter 사용을 위한 Airflow Helm Chart Value 설정
  • Prometheus 관련 자원 생성 및 StatsD Exporter Scrape 설정
    • Prometheus 자원 생성은 Terraform을 통해 진행하겠습니다.
  • Grafana의 Datasource로 Prometheus 추가

StatsD Exporter 사용을 위한 Airflow Helm Chart Value 설정

  • Airflow가 StatsD Exporter에 Metric을 보내도록 설정합니다.

      airflow:
        config:
          AIRFLOW__METRICS__STATSD_ON: 'true'
          AIRFLOW__METRICS__STATSD_HOST: 'localhost'
          AIRFLOW__METRICS__STATSD_PORT: '9125'
  • Airflow의 Webserver, Scheduler, Worker Pod에 StatsD Exporter가 extracontainer(sidecar)로 동작하도록 설정합니다.

      airflow:
        extraContainers:
          - name: prometheus-statsd-exporter
            image: prom/statsd-exporter:latest
            imagePullPolicy: Always
            args:
              - --web.listen-address=:9102
              - --statsd.listen-udp=:9125
            ports:
              - containerPort: 9102
                protocol: TCP
              - containerPort: 9125
                protocol: UDP
              - containerPort: 9125
                protocol: TCP
  • Prometheus는 StatsD Exporter의 URL 주소(K8S Service DNS)를 통해 Metric을 Scrape(Pull) 해야하므로, extramanifests를 사용해 Webserver, Scheduler, Worker의 StatsD Exporter 용 Service를 생성합니다.

      extraManifests:
        - apiVersion: v1
          kind: Service
          metadata:
            name: scheduler-statsd-exporter
          spec:
            selector:
              app: airflow
              component: scheduler
            ports:
              - port: 9102
                targetPort: 9102
    • Webserver와 Worker의 Service 생성 코드는 생략하겠습니다.
  • 이후, 생성한 StatsD Exporter의 Service DNS에 /metrics 경로를 추가하여, StatsD Exporter가 Airflow의 Metric을 잘 받아오고 있는지 확인할 수 있습니다.

  • Airflow Helm Chart Value는 아래 링크를 통해 참조하실 수 있습니다.

Prometheus 관련 자원 생성 및 StatsD Exporter Scrape 설정

  • kubernetes_config_map 생성

      resource "kubernetes_config_map" "prometheus_config" {
        metadata {
          name = "prometheus-config"
        }
    
        data = {
          "prometheus.yml" = <<EOF
      global:
        scrape_interval: 30s
        evaluation_interval: 30s
        scrape_timeout: 10s
    
      scrape_configs:
        - job_name: 'airflow-scheduler-metric'
          static_configs:
            - targets: ['scheduler-statsd-exporter.default.svc.cluster.local:9102']
      EOF
        }
      }
    • Deployment를 통해 Prometheus Container가 시작될 때,
    • Prometheus가 기본 설정 파일(prometheus.yml)을 Container 내부에서 찾아서 실행될 수 있도록,
    • Prometheus Container 내부에 마운트할 파일을 kubernetes_config_map을 통해 정의합니다.
    • Prometheus 기본 설정 파일(prometheus.yml) 작성 방법은 아래 링크를 참조하실 수 있습니다.
    • 위 예제의 scrape_configs에는 Scheduler의 StatsD Exporter만 scrape하도록 설정되어있으며,
    • Webserver와 Worker의 StatsD Exporter를 Scrape하는 코드는 생략하겠습니다.
  • Prometheus Deployment 생성

      resource "kubernetes_deployment" "prometheus" {
        metadata {
          name = "prometheus"
        }
        spec {
          replicas = 1
          selector {
            match_labels = {
              app = "prometheus"
            }
          }
          template {
            metadata {
              labels = {
                app = "prometheus"
              }
            }
            spec {
              container {
                image = "prom/prometheus"
                name  = "prometheus"
                args = [
                  "--config.file=/etc/prometheus/prometheus.yml"
                ]
                port {
                  container_port = 9090
                }
                volume_mount {
                  mount_path = "/etc/prometheus/"
                  name       = "prometheus-config-volume"
                }
              }
              volume {
                name = "prometheus-config-volume"
                config_map {
                  name = kubernetes_config_map.prometheus_config.metadata[0].name
                }
              }
            }
          }
        }
      }
    • kubernetes_config_map이 Prometheus Container 내부로 volume mount 될 수 있도록 설정한 뒤,
    • Prometheus가 기본 설정 파일을 Container 내부에서 찾아 실행될 수 있도록,
    • Prometheus Container 실행 인자로 기본 설정 파일의 경로를 넣어줍니다.
  • Prometheus Service 생성

      resource "kubernetes_service" "prometheus" {
    
        metadata {
          name = "prometheus"
        }
        spec {
          type = "ClusterIP"
          selector = {
            app = "prometheus"
          }
          port {
            port        = 9090
            target_port = 9090
          }
          session_affinity = "None"
        }
      }
    • Grafana가 Prometheus의 Service DNS 주소를 통해 Prometheus를 Datasource로 등록할 수 있도록 Prometheus 용 Service를 생성합니다.

Grafana의 Datasource로 Prometheus 추가

  • Grafana 대시보드 접근 → 좌측 톱니바퀴 클릭

  • Data sources 카테고리에서 “Add new data source” 클릭 → “Prometheus” 선택

  • Prometheus Data source의 Name을 지정

  • HTTP URL에 Prometheus의 Service DNS를 삽입

  • Save & test 클릭

  • 이후, 대시보드를 생성한 뒤 Data source를 Prometheus로 지정하고 원하는 패널을 만들면 됩니다.

참고