모니터링 시스템에서 Pull 또는 Push 동작 방식 비교 및 선택을 위한 리서치

 

 

1.  모니터링 시스템 유형

다양한 관점에서 여러 범주로 나눌 수 있는 수백 가지가 넘는 모니터링 시스템 존재

  • 모니터링 대상: 범용(대부분의 모니터링 대상에 적합한 일반적인 모니터링 방법), 전용(Java JMX 시스템, CPU 고온 보호 등 특정 기능에 맞게 사용자 지정)
  • 데이터 수집 방법: Pull(Prometheus, SNMP, JMX), Push(CollectD, Zabbix, InfluxDB)
  • 배포 모드: Coupled(결합형, 모니터링 시스템과 함께 배포), standalone(독립형, 단일 인스턴스 배포), distributed(분산형, 수평적 확장 가능), SaaS(배포가 필요 없음, 많은 상용 회사에서 제공).
  • 데이터 수집 방법: 인터페이스 유형(일부 API를 통해서만 데이터 수집), DSL(PromQL 및 GraphQL 등 포함), SQL(표준 SQL 등).
  • 상업적 속성: 오픈 소스 및 무료(ex: Prometheus 및 InfluxDB standalone 버전), 오픈 소스 상용 유형(ex: InfluxDB 클러스터 버전, Elastic Search X-Pack), closed-source 상용 유형(예: DataDog, Splunk 및 AWS Cloud Watch).
 
 

 

2. Pull or Push?

데이터 수집 방법에 따른 동작 방식 

Pull

모니터링이 필요한 오브젝트에 원격으로 접근해 지표를 능동적으로 획득. 모니터링이 필요한 개체에 원격으로 엑세스할 수 있는 기능 필요

 

Push

모니터링이 필요한 오브젝트가 적극적으로 지표 Push

 

 

모니터링 시스템의 구축 및 선택을 위해서는 이 두 가지 방법의 장단점을 미리 이해하고 구현에 적합한 계획을 선택해야 함

-> 모니터링 시스템의 안정성을 보장하기 위한 후속 유지 관리 비용과 배포 및 O&M 비용 증가 방지

 

 

 

3. Pull과 Push 방식 Overview

 

 

 

4.  원리 및 아키텍처 비교

 

Pull Model Architecture

Pull 모델 데이터 수집의 핵심: Prometheus와 같은 모니터링 백엔드와 함께 배포되는 Pull 모듈

  1. Service discovery system에 연결할 수 있는 기능이 있어야 함 (host service discovery(일반적으로 회사의 CMDB 시스템에 의존), application service discovery(ex: Consul), PaaS service discovery(예: Kubernetes))
  2. 일반적으로 공통 프로토콜을 사용하여 원격 끝(remote end)에서 데이터 가져오며, pull interval, timeout interval, metric filtering, rename 및 간단한 프로세스 기능 제공
  3. application-end SDK는 풀링 기능을 제공하기 위해 고정 포트에 대한 수신 대기 기능 지원
  4. 다양한 미들웨어 및 기타 시스템이 Pull 프로토콜과 호환되지 않으므로, 시스템의 메트릭 가져오기를 지원하고 표준 Pull 인터페이스를 제공하기 위해 Exporter에 해당하는 에이전트 개발 필요

 

Push Model Architecture

비교적 간단한 Push 모델

  1. Push Agent는 다양한 모니터링 대상의 메트릭 데이터 가져와 서버로 푸시하는 기능 지원. 모니터링 시스템과 결합된 방식으로 배포하거나 별도로 배포 가능
  2. ConfigCenter(옵션)는 모니터링 대상, 수집 간격, 메트릭 필터링, 메트릭 처리 및 원격 대상과 같은 중앙 집중식 동적 구성 기능 제공
  3. application-end SDK는 모니터링 백엔드 또는 로컬 에이전트로 데이터 전송 지원(일반적으로 로컬 에이전트는 일련의 백엔드 인터페이스도 구현)

 

요약

Pull 모델의 배포 방식은 미들웨어 및 기타 시스템을 모니터링하기에는 너무 복잡하고 유지 관리 비용 높음

Push 모드는 상대적으로 편리하지만, Metrics 포트를 제공하거나 사전에 배포를 푸시하는데 드는 애플리케이션의 비용 거의 동일

 

 

 

5. Pull's Distributed Solution

 

 

확장성 측면에서 Push 데이터 수집은 기본적으로 분산되어 있고 모니터링 백엔드 기능이 지원되는 경우 제한 없이 수평적으로 확장 가능하나, Pull 확장성 방식은 더 번거로움

  1. Pull 모듈은 모니터링 백엔드에서 분리되어 있으며, Pull은 에이전트로서 별도 배포
  2. Pull 에이전트는 분산 협업을 실현해야 하며, 이를 위한 가장 간단한 방법은 샤딩(ex: service discovery system에서 모니터링되는 머신의 목록을 가져오고, 머신에서 해시 모듈로 작업을 수행한 다음, 샤딩을 통해 어떤 에이전트가 Pull을 담당할지 결정)
  3. Pull 에이전트를 관리하기 위한 configuration center 추가

 

이 분산 방식에 대한 문제점

  1. 단일 지점 병목 현상이 여전히 존재하며 모든 에이전트가 service discovery module 요청 필요
  2. 에이전트 확장 후 모니터링 대상 변경되어 데이터 중복 혹은 누락 가능
 

 

 

6.  모니터링 기능 비교

Monitoring Target Survivability

생존 가능성은 모니터링에 필요한 가장 기본적인 첫 번째 작업

 

Pull

목표 생존 가능성(target survivability) 모니터링이 비교적 간단

Pull 의 중앙에서 목표 지표의 요청 여부 확인 가능하며, 장애 발생 시 네트워크 시간 초과, 피어 연결 거부와 같은 간단한 오류에 대한 알림 수신

 

Push

푸시 모드는 더 번거로움

애플리케이션이 report하지 않을 시 애플리케이션 고장, 네트워크 문제 또는 애플리케이션이 다른 노드로 마이그레이션 가능성 있음

Pull 모듈은 실시간으로 service discovery와 필터 상호 작용을 수행할 수 있지만 Push 모드는 이를 수행할 수 없어 서버가 service discovery와 상호 작용한 후에야만 구체적인 장애 원인 파악 가능

 

Data Completeness Calculation

데이터 완전성의 개념은 대규모 모니터링 시스템에서 매우 중요

(ex:  1,000개의 사본이 있는 트랜잭션 애플리케이션의 QPS 모니터링 시 이 지표를 1,000개의 데이터와 결합 필요. 데이터가 완전하지 않은 경우, QPS가 2% 감소할 때 알람을 트리거하도록 구성되었다고 가정할 때, 20개 이상의 복사본에서 보고된 데이터가 네트워크 변동으로 인해 몇 초 지연되면 잘못된 알람 트리거됨. 따라서 알람을 구성할 때 데이터 완전성 고려 필요)

 

데이터 완전성 계산은 service discovery 모듈에 따라 달라짐

 

Pull

Pull 방식은 데이터를 한 라운드씩 차례로 가져오는 방식이므로, 한 라운드가 끝나면 데이터가 완성

일부 Pull이 실패하더라도 불완전한 데이터의 비율 파악 가능

 

Push

Push 모드에서는 각 에이전트와 애플리케이션이 능동적으로 푸시 수행

각 클라이언트의 푸시 간격과 네트워크 지연 시간은 달라 과거 상황에 따라 서버가 데이터 완전성을 계산해야 하므로 막대한 비용이 발생

 

 

Short Lifecycle/Serverless Application Monitoring

실제 시나리오에서는 short-lifecycle/serverless 애플리케이션이 많으며, 특히 비용 측면에서 많은 수의 작업, 탄력적 인스턴스, 서버리스 애플리케이션 사용 (ex: 렌더링 작업이 도착한 후 탄력적 컴퓨팅 인스턴스가 시작되고 완료되면 즉시 해제. 머신 러닝 학습 작업, 이벤트 기반 서버리스 워크플로우, 정기적으로 실행되는 작업(리소스 정리, 용량 확인, 보안 스캔 등))

 

수명 주기가 짧은 애플리케이션을 관리하기 위해 순수 Pull 시스템은 애플리케이션의 사전 예방적 푸시를 수락한 다음 모니터링 시스템에 풀 포트를 제공하는 중간 계층(예: Prometheus Push Gateway)을 제공하나, 이는 추가적인 중간 계층의 관리 및 O&M 비용으로 이어짐

이 모드는 푸시를 시뮬레이션하는 Pull을 통해 이루어지기 때문에 보고 지연 시간이 길어지고, 즉시 사라지는 이러한 메트릭을 제때 정리해야 함

 

 

Flexibility and Coupling

Flexibility(유연성) 측면에서는 Pull 모드가 다소 유리

Pull 모듈에서 원하는 지표를 구성하고 지표에 대해 간단한 계산과 보조 처리를 할 수 있으나

Push SDK/에이전트에서도 이러한 파라미터를 구성할 수 있고 구성 센터의 도움으로 구성 관리가 간단

Coupling(결합성) 측면에서 Pull모델은 백엔드 간의 결합도가 낮고 백엔드가 이해할 수 있는 인터페이스만 제공하면 됨

어떤 백엔드가 연결되어 있고 백엔드에 어떤 지표가 필요한지 알 필요 없이 분업이 명확합

애플리케이션 개발자는 애플리케이션의 지표만 노출하면 되고, SRE는 이러한 지표 확인 가능 

Push 모델은 결합 정도가 더 높음

애플리케이션이 백엔드 주소와 인증 정보를 구성해야 함

그러나 로컬 push 에이전트에 의존하면 애플리케이션은 로컬 주소만 푸시하면 되므로 큰 비용이 들지 않음

 

 

 

7.  Resource 와 O&M 비용

Resource 비용

전체 비용 측면에서는 두 접근 방식 간에 약간의 차이가 있지만 비용 분포 고려 시

  • Pull 모드의 비용은 주로 모니터링 시스템 단에 집중. 애플리케이션 단에서는 비용 적음
  • Push 모드의 핵심 소비는 푸시 에이전트 단에 집중.  모니터링 시스템 단에서의 비용은 Pull보다 훨씬 적음

O&M 비용

Pull모드의 비용이 더 높음

  • Pull 모드의 O&M을 담당하는 구성 요소에는 다양한 exporters, service discovery, Pull Agent, 모니터링 백엔드 포함
  •  Push 모드는 Push 에이전트, 모니터링 백엔드, configuration center(선택 사항, 일반적으로 모니터링 백엔드와 함께 배포 완료됨)에 대한 O&M만 수행

 

한 가지 주의할 점 - Pull 모드에서는 서버가 클라이언트에 대한 요청을 능동적으로 시작하기 때문에 네트워크에서 애플리케이션 측의 클러스터 간 연결 및 네트워크 보호 ACL을 고려해야 함. Push 모드에 비해 네트워크 연결은 간단하며, 서버가 각 노드가 액세스할 수 있는 도메인 이름/VIP만 제공하면 됨

 

 

 

8.  Pull or Push 선택

Pull 패턴의 대표적인 오픈소스 솔루션: Prometheus 패밀리 솔루션. (Prometheus 확장성이 제한적이기 때문에 패밀리라고 지칭. Prometheus에는 Thanos, VicoriaMetrics, Cortex 등 기술 커뮤니티에 분산된 솔루션이 많이 있음)

Push 패턴의 대표적 솔루션: InfluxDB의 TICK(Telegraf, InfluxDB, Chronograf, Kapacitor)

 

두 솔루션 모두 장단점 존재

클라우드 네이티브라는 배경에서 Prometheus는 CNCF와 Kubernetes의 인기와 함께 번성하기 시작하여 이미 많은 오픈 소스 소프트웨어가 Prometheus 모드에서 Pull 포트를 제공

그러나 많은 시스템이 설계 초기부터 Pull 포트를 제공하는 데 어려움을 겪어왔습니다. 이러한 시스템을 모니터링하는 데는 Push 에이전트 방식이 더 적합

 

사내 실제 시나리오를 기반으로 Pull, Push 방식 선택 필요

ex: 사내 네트워크 클러스터가 매우 복잡하거나 수명주기가 짧은 애플리케이션 사용 시 Push 선택. 모바일 애플리케이션의 경우 Push만 사용 가능. 시스템 자체는 service discovery위해 Consul을 사용하고 Pull 포트 export해 쉽게 구현 가능

 

회사 내 모니터링 시스템의 경우 Pull과 Push 기능을 모두 갖춘 것이 최적의 솔루션

  1. 호스트, 프로세스, 미들웨어 모니터링은 Push 에이전트 사용
  2. Kubernetes 및 기타 직접 노출(exposed)된 Pull 포트는 Pull 모드를 사용
  3. 애플리케이션은 실제 시나리오에 따라 Pull 또는 Push 선택

'기타' 카테고리의 다른 글

Airflow  (0) 2023.11.24

Airflow


Apache Airflow는 초기 에어비엔비(Airfbnb) 엔지니어링 팀에서 개발한 워크플로우(workflow) 오픈 소스 플랫폼

프로그래밍 방식으로 워크플로우를 작성, 스케줄링 및 모니터링

https://airflow.apache.org/

 

Home

Platform created by the community to programmatically author, schedule and monitor workflows.

airflow.apache.org

 

 

 

Airflow 아키텍처

Airflow의 구성요소

Webserver

Airflow의 로그, Scheduler에 의해 생성된 DAG 목록, Task 상태 등을 시각화(UI)

 

Scheduler

할당된 work들을 스케줄링. 예약된 워크플로우들을 실행(트리거링)하기 위해 executor에게 task 제공 

 

Executor

실행중인 task 핸들링. default로는 scheduler에 할당된 모든 task 실행시키지만, production 수준에서는 실행할 task worker에 push

 

Workers

실제 task 실행하는 주체

 

Metadata Database

DAG, Task 등의 metadata 저장 및 관리

 

DAG Directory 

DAG 저장

 

 

 

 

 

Airflow 주요 개념

DAG(Directed Acyclic Graph)

  • 비순환 그래프(사이클x)로써, 노드와 노드가 단방향으로 연결.
  • Airflow에서는 DAG 이용해 워크플로우를 구성하고 어떤 순서로 task를 실행시킬 것인지, dependency를 어떻게 표현할지 결정 
  • 순차적으로 task실행되며, 논리적 오류 발생 시 교착상태(deadlock) 발생

  • 일반적으로 python 코드로 정의하며 $AIRFLOW_HOME/dags에 위치
    • dags 폴더의 .py 이름에 'airflow', 'dag' 단어 포함 시 Web UI에 표시
  • $AIRFLOW_HOME/airflow.cfg 파일에서 변경

 

 

Operator

  • DAG 동작 시 실제로 실행되는 task 결정(정의)
  • Operator Type
    • Action Operator
    • Transfer Operator
      • 하나의 시스템에서 다른 시스템으로 옮김(ex. 데이터를 Source에서 Destination으로 전송)
    • Sensor Operator
      • 조건 만족할 때까지 기다리다가 충족 시 다음 task 실행

 

Task & Task Instance

  • Task: 데이터 파이프라인에 존재하는 Operator 의미
    • Operator 실행 시 task됨
  • Task Instance: 데이터 파이프라인 trigger되어 실행 시 생성된 task
  • task 실행 순서 정의
    • 각 task는 ">>", "<<", "[]" 이용해 task의 의존성 정의하며 dag 그림

 

 

Task와 Operator

  • 사용자 관점에서 두 용어는 같은 의미지만 task는 작업의 올바른 실행을 보장하기 위한 manager
  • 사용자는 operator 사용해서 수행할 작업에 집중하며, airflow는 task를 통해 작업 올바르게 실행
    • 사용자는 각 환경별 작업이 잘 이루어지는지 확인하기 위해 operator 내 코드 구성에 집중
    • airflow는 각 operator 내의 구성 요소들이 전부 잘 맞아야 작업이 이루어지는 형태

 

 

 

 

 

Airflow 기본 동작 원리

  1. 유저가 DAG 작성
    • dags 폴더 아래에 py파일 배치
  2. Webserver와 Scheduler가 DAG 읽어옴
  3. Scheduler가 Metastore 이용해 DagRun 오브젝트 생성
    • DagRun은 사용자가 작성한 DAG인스턴스 (DagRun Status: Running)
  4. Scheduler는 DagRun 오브젝트의 인스턴스인 Task Instance Object 스케줄링
  5. 트리거의 조건이 맞으면 Scheduler가 Task Instance를 Executor로 보냄
  6. Executor는 Task Instance 실행
  7. 작업 완료 후 Metastore에 보고
    • 완료 Task Instance는 DagRun에 업데이트됨
    • Scheduler는 DAG 실행 완료 여부를 Metastore 통해 확인 후 DagRun 상태 바꿈(DagRun Status: Completed)
  8. Metastore가 Webserver에 업데이트하여 사용자도 확인

 

 

 

 

 

DAG 코드 구조

Python 코드로 정의하는 DAG 구조

 

라이브러리 임포트

DAG와 워크플로우 구성에 필요한 라이브러리 선언

 

공통 변수 정의

DAG 구성에 사용하기 위해 공통으로 사용하는 변수 정의. 변경 자주 발생 시 Variable 기능 활용

 

DAG 공통 속성값 정의

DAG 정의 시 필요한 공통 속성 값 정의

 

DAG 정의

DAG 선언하고 공통 속성값 전달

 

Task 정의

DAG에 포함될 각 작업(task) 정의. Operator, Sensor, Hook 등 사용

 

Task 배열

각 작업(Task)들의 순서 나열. '<<', '>>' 같은 Shift 연산자 사용. set_upstream, set_downstream 함수도 사용 가능 

 

ex.

# dags/branch_without_trigger.py
import pendulum

from airflow.decorators import task
from airflow.models import DAG
from airflow.operators.empty import EmptyOperator

dag = DAG(
    dag_id="branch_without_trigger",
    schedule="@once",
    start_date=pendulum.datetime(2019, 2, 28, tz="UTC"),
)

run_this_first = EmptyOperator(task_id="run_this_first", dag=dag)


@task.branch(task_id="branching")
def do_branching():
    return "branch_a"


branching = do_branching()

branch_a = EmptyOperator(task_id="branch_a", dag=dag)
follow_branch_a = EmptyOperator(task_id="follow_branch_a", dag=dag)

branch_false = EmptyOperator(task_id="branch_false", dag=dag)

join = EmptyOperator(task_id="join", dag=dag)

run_this_first >> branching
branching >> branch_a >> follow_branch_a >> join
branching >> branch_false >> join

 

 

 

 

 

 

 

Airflow 장단점

장점

  • Python 코드를 이용해 파이프라인 구현하므로 Python에서 구현할 수 있는 대부분의 방법 사용하여 복잡한 파이프라인 생성 가능
    • Python 기반으로 쉽게 확장 가능하며 다양한 시스템과 통합 가능 (다양한 유형의 DB, Cloud Service 통합 가능)
  • 데이터 인프라 관리, 데이터 웨어하우스 구축, 머신러닝/분석/실험에 사용할 데이터 환경 구성에 유용
  • 스케줄링 기능으로 DAG에 정의된 특정 시점에 트리거 가능하며 최종 시점과 다음 스케줄 주기 상세히 알려줌
  • 백필 기능 사용하면 과거 데이터 손쉽게 재처리 가능하여 코드 변경 후 재생성 필요한 데이터 재처리 가능

단점

  • Python에 익숙하지 않으면 DAG 구성 어려움
  • 초기 설치는 간단해보여도 작은 환경 변화에 오류 발생하는 경우 있어 롤백 잦음

주의사항

  • Data Streaming Solution 적용에 부적합
    • 초단위(그 이하) 데이터 처리 필요한 경우 사용에 부적합
    • airflow는 반복적이거나 배치 테스크를 실행하는 기능에 초점 맞춰져 있음
  • Data Processing Framework (Flink, Spark, Hadoop 등) 로 사용 부적절
    • 데이터 프로세싱 작업에는 최적화 되어있지 않아 매우 느림
    • 경우에 따라 메모리 부족 발생
      • SparkSubmitOperator와 같은 operator 이용하여 데이터 프로세싱은 Spark와 같은 외부 Framework로 처리
  • 파이프라인 규모 커질 시 Python코드 복잡해질 수 있음 -> 초기 사용 시점에 엄격한 관리 필요

'기타' 카테고리의 다른 글

Monitoring - Pull vs Push  (1) 2023.12.02

+ Recent posts