[튜토리얼] kt cloud SDK와 Grafana로 Load Balancer 실시간 모니터링 구축하기

Tech Story/Cloud Architecture

[튜토리얼] kt cloud SDK와 Grafana로 Load Balancer 실시간 모니터링 구축하기

 

 
[ kt cloud Cloud컨설팅팀 김휘집 님 ]

📋 요약

kt cloud SDK와 Grafana를 활용하여 Load Balancer의 실시간 모니터링 대시보드를 구축하는 방법을 소개합니다.

Custom Exporter를 통해 안정적인 데이터 수집과 시각화를 구현하는 실무 가이드입니다.

#LoadBalancer #Grafana #모니터링 #SDK #대시보드

 


들어가며

[튜토리얼] kt cloud SDK와 Grafana로 Load Balancer 실시간 모니터링 구축하기

클라우드 환경에서 Load Balancer(LB)는 트래픽을 분산하여 서비스의 안정성과 성능을 보장하는 핵심 구성 요소입니다. 하지만 여러 개의 LB를 운영하다 보면 각각의 상태와 성능을 실시간으로 파악하기 어려워집니다. “이벤트 기간동안 LB에서 수집되는 데이터가 얼마나될까?”, “LB는 직접 모니터링 할 수 없을까?”, “특정 LB에 연결된 서버들의 응답 시간은 얼마나 될까?” 같은 질문에 즉시 답하기 힘든 상황이 발생합니다. 물론, kt cloud TechCenter를 통해서 문의를 통한 답변으로 얻을 수 있는 정보도 있지만 여러가지 제한적인 정보만 취합할 수 있는 한계점이 있습니다.

 

이 글에서는 kt cloud SDK와 Python기반의 Custom Exporter를 통하여 오픈소스 모니터링 도구인 Grafana를 활용해 Load Balancer의 상태와 성능을 한눈에 볼 수 있는 모니터링 대시보드를 구축하는 방법을 소개해드리겠습니다.

구성 개요

  • kt cloud SDK를 활용하여 Load Balancer 관련 지표 수집
  • Custom Exporter를 통하여 Prometheus에서 활용 가능한 형태로 변환
  • 수집된 데이터를 기반으로 Prometheus에 적재 및 Grafana를 통해 시각화 대시보드 구현

구현 내용

SDK를 통해 LB의 실시간 상태 및 성능 데이터를 API호출로 수집하게 되며, 수집주기 및 메트릭 정규화 설정을 통해 Prometheus에 적합한 형태로 변환하여 Grafana에 표현하게 됩니다. Grafana 대시보드에 구성해볼 항목은 아래와 같습니다.

  • LB 현황(전체LB 리스트, 정상LB/다운LB 정보, LB상세정보 등)
  • LB별 백엔드 서버현황
  • 백엔드 서버별 트래픽 추이(TTFB, Connection, Requests 등)

kt cloud SDK를 활용한 데이터 수집

1️⃣ 시스템 개요

로드밸런서 모니터링 시스템은 다음과 같은 요소들로 구성됩니다.

[튜토리얼] kt cloud SDK와 Grafana로 Load Balancer 실시간 모니터링 구축하기

Loadbalancer라는 원천데이터를 kt cloud에서 제공하는 SDK를 활용해서 내 계정의 Loadbalancer정보를 수집하게 되며, Custom Exporter를 통해서 Prometheus에 적합한 데이터로 변환하게 됩니다. Prometheus에서는 수집된 데이터를 저장하고, Grafana가 Prometheus에 저장된 데이터를 시각화하여 사용자에게 제공하게 됩니다.

 

각 요소별 역할 및 기능은 아래와 같습니다.

요소 역할 기능
SDK/API • 복잡한 REST API 호출을 간단한 Python 함수로 추상화 • 자동 인증 및 토큰 관리
• LB 상태, 서버 성능 메트릭 실시간 수집
• API 응답 데이터 파싱 및 정규화
Custom Exporter • 로드밸런서 메트릭을 Prometheus 형식으로 변환 • SDK를 통해 로드밸런서 데이터 수집
• Prometheus 메트릭 형식으로 데이터 변환
Prometheus • 시계열 데이터베이스 및 메트릭 수집기 • Exporter로부터 주기적으로 메트릭 수집
• 알람 규칙 처리
Grafana • 데이터 시각화 및 대시보드 제공 • Prometheus 데이터소스 연결
• 대시보드를 통한 시각적 모니터링
 

수집 가능 메트릭

kt cloud Load balancer에서 수집 가능한 메트릭은 아래 링크를 참고 하시면 됩니다.

https://cloud.kt.com/docs/open-api-guide/d/network/load-balancer


2️⃣ 기본 설정

SDK를 활용하기 전 기본적으로 설정해야 하는 부분들이 있습니다.

  1. SDK 파일 경로 설정
  2. Python 필수 모듈 설치
  3. .env파일 생성(보안성 강화)

설정이 완료되었으면, 3가지 테스트를 진행해보고 정상적으로 API호출이 되는지 테스트를 진행하시면 됩니다.

  1. SDK 연결 테스트
  2. 토큰 발급 테스트
  3. Loadbalancer 정보 수집 테스트

SDK 파일 기본 경로

1. SDK 모듈 파일을 적절한 디렉토리에 저장합니다.

/path/to/site-packages/ktcloud/
├── __init__.py
├── .env
├── kcldx.py
├── kclutil.py
└── kclinstance.py

 

2. __init__.py는 비어있어도 됩니다.

3. PYTHONPATH 환경 변수에 해당 디렉토리 경로를 추가합니다.

 

🔹Linux/Mac

export PYTHONPATH=$PYTHONPATH:/path/to/site-packages/ktcloud/
* 예를들어 /home/ubuntu/ktcloud 에 SDK파일을 업로드 하였으면
export PYTHONPATH=$PYTHONPATH:/home/ubuntu/ktcloud

 

🔹 Windows

set PYTHONPATH=%PYTHONPATH%;C:\path\to\site-packages\ktcloud

 

4.영구적으로 설정하려면 .bashrc 또는 .profile 파일(Linux/Mac) 또는 시스템 환경 변수(Windows)에 추가합니다.

vi ~ubuntu/.bashrc
export PYTHONPATH=$PYTHONPATH:/path/to/site-packages/ktcloud/
* 예를들어 /home/ubuntu/ktcloud 에 SDK파일을 업로드 하였으면
vi ~ubuntu/.bashrc 
export PYTHONPATH=$PYTHONPATH:/home/ubuntu/ktcloud

 

Python 필수 모듈 설치

sudo apt install python3-dotenv python3-yaml python3-requests python3-xmltodict python

 

.env 파일 생성(기본)

파이썬을 실행하려는 디렉토리에 .env 파일을 생성하고 다음과 같이 내용을 작성합니다.

단, home 디렉토리에 .env를 생성 할 경우 보안에 취약해질 수 있습니다.

cd ~ubuntu
vi .env
CLOUD_ID=your_kt_cloud_id (포털로그인 아이디)
CLOUD_PASSWORD=your_kt_cloud_password (포털 로그인 패스워드)
CLOUD_ZONE=DX-M1 (사용존)

만약 .env 파일이 다른 경로에 있다면, python 코드의 load_dotenv() 함수에 경로를 명시적으로 지정할 수 있습니다. 경로 설정시 반드시 “ “ 로 묶어줘야 합니다.

# 특정 경로의 .env 파일 로드
load_dotenv("/다른/경로/.env")
# ex
load_dotenv("/path/to/site-packages/ktcloud/.env")

 

※ 지원되는 API-END-POINT 내 Zone 별 약어는 아래와 같습니다.

Zone Zone 단축어
DX-M1 d1
DX-Central d2
DX-DCN-CJ d3
DX-G gd1
DX-G-YS gd4

 

연결 테스트

설치가 완료되면 다음 test_ktcloud.py 코드를 생성하여 테스트할 수 있습니다.

from kcldx import ZoneManager

try:
    # 연결 테스트 (실제 인증 정보 사용)
    zone_mgr = ZoneManager("test_id", "test_password", "DX-M1")
    # test_id, test_password, DX-M1은 알맞게 수정
    print("모듈이 성공적으로 가져와졌습니다!")
except ImportError as e:
    print(f"오류: {e}")
except Exception as e:
    print(f"인증 오류 (예상된 결과): {e}")
    print("모듈이 성공적으로 가져와졌습니다!")

 

테스트 실행 결과

# 계정/패스워드가 틀렸을 경우 인증 오류가 발생 
ubuntu@test-api01:~/path/to/site-packages/ktcloud/$ python3 test_ktcloud.py
인증 오류 (예상된 결과): Authentication error
모듈이 성공적으로 가져와졌습니다!

# 인증오류가 없을 경우 
ubuntu@test-api01:~/path/to/site-packages/ktcloud/$ python3 test_ktcloud.py
모듈이 성공적으로 가져와졌습니다!

 

토큰 발급 테스트

토큰 발급 Python 코드 : token_get.py

먼저 kt cloud의 Load Balancer 정보를 수집하기 위해 SDK를 설정해야 합니다. 환경 변수를 통해 인증 정보를 관리하는 것이 보안상 안전합니다.(.env파일에 저장된 ID/PW/Zone의 정보 수집)

파일명을 token.py 로 만들 경우 아래와 같은 에러가 발생. 이는 순환참조 에러로 SDK내부의 모듈 이름과 동일하기 때문에 발생하며, 아래와 같은 에러나 나온다면 파일명 변경이 필요합니다.

ImportError: cannot import name 'load_dotenv' from partially initialized module 'dotenv' (most likely due to a circular import) (/usr/lib/python3/dist-packages/dotenv/init.py). Did you mean: 'find_dotenv'?
import os
from dotenv import load_dotenv
import kcldx as kcl
import json
# .env 파일 로드
load_dotenv()
# 환경 변수에서 정보 읽기
cloud_id = os.getenv("CLOUD_ID")
cloud_password = os.getenv("CLOUD_PASSWORD") 
cloud_zone = os.getenv("CLOUD_ZONE")
# ZoneManager 객체 생성 및 자동 토큰 발급
try:
    print("kt cloud에 연결 중...")
    d1 = kcl.ZoneManager(cloud_id, cloud_password, cloud_zone)
    # 토큰 정보 출력
    print("\n토큰 정보:")
    print(f"토큰값: {d1._token}")
    print(f"만료시간: {d1._token_expire}")
    print(f"프로젝트 ID: {d1._project_id}")
    # compute, storage, network 리소스 객체 생성
    compute = d1.compute_resource()
    storage = d1.storage_resource()
    network = d1.network_resource()
    print("\n연결 성공! 리소스 객체가 생성되었습니다.")
except Exception as e:
    print(f"연결 실패: {e}")

 

실행 방법

python3 token_get.py

 

예상 결과

kt cloud에 연결 중...
토큰 정보:
토큰값: gAAAAABl2I...
만료시간: 2025-03-11 17:35:42.123456
프로젝트 ID: a1b2c3d4e5f6g7h8i9j0
연결 성공! 리소스 객체가 생성되었습니다.

여기까지 하셨으면 기본적으로 SDK를 활용해서 API로 데이터가 수집 되는 것을 확인하실 수 있으실텐데요, 다음은 Load balancer의 정보를 수집해 보겠습니다.

 

Load Balancer 정보 수집 테스트

kt cloud SDK를 사용하면 Load Balancer의 다양한 정보를 쉽게 사용할 수 있습니다.

# LB 목록 조회
lb_list = network.list_lb_info()

# 각 LB별 연결된 서버 정보 수집
for lb in lb_list:
    lb_id = lb['lb_id']
    servers = network.list_lb_server(lb_id)
    
    # 서버별 성능 메트릭 처리
    for server in servers:
        connections = server.get('cursrvrconnections', 0)
        throughput = server.get('throughputrate', 0)
        response_time = server.get('avgsvrttfb', 0)

 

SDK를 통해 수집할 수 있는 주요 정보는 다음과 같습니다.

  • LB 기본 정보: 이름, 상태, 서비스 IP/포트, 서비스 타입
  • LB 설정: 로드밸런싱 옵션, 헬스체크 타입
  • 연결된 서버 정보: 서버 IP/포트, 상태, 성능 메트릭

3️⃣Custom Exporter 제작

kt cloud Load Balancer를 효과적으로 모니터링하기 위해서는 kt cloud API와 Prometheus 사이의 다리 역할을 하는 Exporter가 필요합니다. API호출을 하는 즉시 메트릭을 업데이트 하는 방식으로 구성하게 되면 Prometheus 스크랩 시 데이터가 불일치하는 문제가 있습니다. 이번 섹션에서는 실제 운영 환경에서 안정적으로 동작하는 Custom Exporter 구현 방법을 소개합니다.

핵심 아키텍처: 원자적 업데이트 패턴

Prometheus는 스크랩 기반 수집 방식이기 때문에, 메트릭이 업데이트되는 찰나에도 스냅샷을 가져갈 수 있습니다. 만약 이 순간 데이터가 절반만 갱신됐다면?


“이전 호출한 데이터와 현재 호출한 데이터가 섞인 이상한 상태”가 됩니다.

이런 불일치를 해결하기 위한 해법이 바로 다음의 구조입니다.

 

2단계 분리 아키텍처

pythonclass AtomicKTCloudLBExporter:
    def collect_metrics(self):
        # 1단계: 데이터 수집 (메트릭 업데이트 없음)
        temp_data = self.collect_data_to_temp()
        
        # 2단계: 원자적 메트릭 업데이트
        self.atomic_update_metrics(temp_data)

 

이 패턴의 강점은?

  • 데이터 일관성 보장: 스크랩 중간에도 끊김 없는 메트릭 제공
  • 🚀 성능 향상: 느린 API 호출과 빠른 업데이트의 역할을 분리
  • 🔒 안정성 확보: 스레드 충돌 없이 깔끔한 처리

❗ 일반적인 Custom Exporter는 아래와 같이 동작합니다.

python# 기존 방식 (문제가 있는 방식)
def collect_metrics(self):
    lb_list = self.network.list_lb_info()  # API 호출
    for lb in lb_list:
        # 즉시 메트릭 업데이트
        self.lb_info.labels(lb_id=lb['lb_id']).set(1)  
        
        servers = self.network.list_lb_server(lb['lb_id'])  # 추가 API 호출
        for server in servers:
            # 즉시 메트릭 업데이트
            self.server_state.labels(server_ip=server['ip']).set(1)

 

동작방식
🪜 API 호출 → 즉시 메트릭 업데이트 → API 호출 → 즉시 메트릭 업데이트 반복

⚠️ 주요 문제

  • 메트릭 업데이트 중 Prometheus 스크랩 시 데이터 불일치
  • 일부는 새 데이터, 일부는 이전 데이터가 혼재
  • 모니터링 결과의 신뢰성 저하
  • 대규모 환경에서 문제 심화

Prometheus가 스크랩하는 도중 일부 메트릭은 새로, 일부는 이전 데이터를 보고 있을 수 있습니다. 특히 대규모 환경에서 이런 상황은 지표 해석을 왜곡시키고, 알람이 엉뚱하게 작동하는 원인이 되기도 합니다.

 

단계별 구현 상세

1단계: 임시 데이터 수집

이 단계에서는 철저하게 읽기전용 입니다. 메트릭은 건드리지 않습니다. 데이터를 먼저 모두 모아두고, 준비된 데이터로만 이후 작업을 수행합니다.

def collect_data_to_temp(self):
    temp_data = {
        'lb_list': [],
        'lb_servers': {},
        'service_type_counts': {},
        'collection_time': time.time()
    }
    
    # kt cloud API 호출
    lb_list = self.network.list_lb_info()
    temp_data['lb_list'] = lb_list
    
    # 각 LB별 서버 정보 수집
    for lb in lb_list:
        servers = self.network.list_lb_server(lb['lb_id'])
        temp_data['lb_servers'][lb['lb_id']] = servers
    
    return temp_data

 

📌 핵심 포인트

  • Prometheus 메트릭을 건드리지 않고 순수하게 데이터만 수집
  • API 호출이 오래 걸려도 메트릭 일관성에 영향 없음
  • 구조화된 데이터 저장으로 2단계 처리 준비

2단계: 원자적 메트릭 업데이트

🔒 락을 걸고, 한 번에 갱신하라

 

왜 락이 중요한가?

모니터링 시스템은 “실시간성”보다 “신뢰성”이 더 중요할 때가 많습니다. 여러 스레드가 동시에 데이터를 갱신하면 Race Condition이 발생할 수 있는데, 이를 사전에 방지합니다.

def atomic_update_metrics(self, temp_data):
    # 락 기반 동시성 제어
    if not self.update_lock.acquire(blocking=False):
        self.update_conflicts.inc()  # 충돌 감지
        self.update_lock.acquire()
    
    try:
        # 모든 메트릭 초기화 후 일괄 업데이트
        self.lb_info.clear()
        self.lb_server_state.clear()
        
        # 새 데이터로 메트릭 설정
        for lb in temp_data['lb_list']:
            self.lb_info.labels(...).set(state)
    finally:
        self.update_lock.release()

 

핵심 포인트

  • 스레드 락을 통한 안전한 업데이트
  • 충돌 감지 및 카운터를 통한 모니터링
  • 예외 상황에서도 락 해제 보장

메트릭 설계 전략

계층별 메트릭 구조

복잡한 시스템일수록 전체→부분→세부사항으로 문제를 추적할 수 있어야 합니다.

  1. 점진적 상세화(Progressive Disclosure)
    - 사용자는 전체 → 부분 → 세부사항 순으로 문제를 파악할 수 있습니다.
  2. 성능 최적화
    - 전체 현황은 자주 확인하지만, 서버별 세부사항은 필요할 때만 조회합니다.
  3. 알람 정책 차별화
# 전체 레벨: 심각한 알람
"전체 LB 중 50% 이상 장애" → 즉시 알람

# LB 레벨: 중간 알람  
"특정 LB 장애" → 5분 후 알람

# 서버 레벨: 정보성 알람
"특정 서버 과부하" → 모니터링만

 

데이터 세분화 레벨 예시는 아래와 같습니다.

📊 전체 현황 (Level 1)
├── 총 LB 개수: 15개
├── 정상 LB 개수: 12개  
└── 서비스 타입별 분포

📋 LB별 상세 (Level 2)
├── web-lb-01 (HTTP, 172.25.0.100:80)
├── api-lb-02 (HTTPS, 172.25.0.101:443)
└── db-lb-03 (TCP, 172.25.0.102:3306)

🖥️ 서버별 성능 (Level 3)
├── web-lb-01
│   ├── server-01 (172.25.1.10) → 연결수: 45
│   ├── server-02 (172.25.1.11) → 연결수: 38
│   └── server-03 (172.25.1.12) → 연결수: 52

 

실제 계층별 메트릭 구조는 아래와 같이 제작하였습니다.

📈 사용자 눈높이에 맞춘 메트릭 계층화

  1. Level 1: 전체 현황
  2. Level 2: LB별 상세
  3. Level 3: 서버별 성능
# 전체 현황 메트릭
self.lb_count = Gauge('ktcloud_lb_total_count', 'Total LB count')

# 상세 정보 메트릭 (다중 레이블)
self.lb_info = Gauge(
    'ktcloud_lb_info',
    'LB detailed information',
    ['lb_id', 'lb_name', 'service_ip', 'service_type', 'zone']
)

# 성능 메트릭
self.server_connections = Gauge(
    'ktcloud_server_current_connections',
    'Server connection count',
    ['lb_id', 'lb_name', 'server_ip', 'server_port']
)

 

데이터 변환

kt cloud API 응답에서 받아오는 데이터는 완벽하지 않을 수 있습니다. 실제 API 응답 예시를 보면 아래와 같은 불완전한 데이터가 발생할 수 있습니다.

{
  "cursrvrconnections": "15",        // 문자열로 온 숫자
  "throughputrate": "",              // 빈 문자열
  "avgsvrttfb": null,               // null 값
  "requestsrate": "invalid_data",    // 잘못된 형식
  "someotherfield": 42              // 이미 숫자인 경우
}

 

이런 불완전한 데이터를 그냥 float()로 변환하면 프로그램이 크래시될 수 있습니다.

이를 위해서 아래와 같은 형태로 데이터 변환을 적용 하였습니다.

def safe_float(value):
    """API 응답의 불완전한 데이터 안전 처리"""
    try:
        return float(value) if value is not None and value != "" else 0
    except (ValueError, TypeError):
        return 0

# 실제 사용
connections = safe_float(server.get('cursrvrconnections', 0))
throughput = safe_float(server.get('throughputrate', 0))

 

이번 Custom Exporter 구현의 핵심은 “운영 환경에서 통하는 구조”에 있습니다.

  • 단순히 작동하는 코드가 아니라,
  • 실시간 서비스 환경에서도 데이터의 일관성메트릭 신뢰도를 유지하는 구조.

4️⃣운영 환경 고려사항

자체 진단 메트릭

왜 필요한가?

"모니터링 시스템을 모니터링하는" 개념입니다. Exporter 자체에 문제가 생기면 Load Balancer 모니터링이 불가능해지기 때문에, Exporter의 상태를 추적해야 합니다.

 

각 메트릭의 역할은 아래와 같습니다.

  1. scrape_duration - 수집 성능 모니터링
  2. update_conflicts - 동시성 문제 감지
  3. last_scrape_timestamp - 헬스체크

실제 소스코드는 아래와 같이 작성했습니다.

# Exporter 상태 모니터링
self.scrape_duration = Gauge('ktcloud_lb_scrape_duration_seconds', 'Collection time')
self.update_conflicts = Counter('ktcloud_lb_update_conflicts_total', 'Update conflicts')
self.last_scrape_timestamp = Gauge('ktcloud_lb_last_scrape_timestamp', 'Last success time')

환경 설정 관리

.env기반으로 보안성, 환경별 설정분리, 동적 설정을 변경하실 수 있습니다.

실제 소스코드는 아래와 같이 작성했습니다.

# .env 파일 기반 설정
CLOUD_ID = os.getenv("CLOUD_ID")
CLOUD_PASSWORD = os.getenv("CLOUD_PASSWORD")
CLOUD_ZONE = os.getenv("CLOUD_ZONE")
EXPORTER_PORT = 9105
SCRAPE_INTERVAL = 60

 

너무 짧은 주기는 API 제한에 걸릴 수 있고, 너무 긴 주기는 실시간성을 떨어뜨려요. 운영 환경에 맞는 적절한 주기를 설정하는 것이 중요합니다.

SCRAPE_INTERVAL = 60  # 60초마다 데이터 수집

1분 ~ 5분 사이를 권고 드립니다!

 

성능 최적화 팁

API 호출 최적화

  • 배치 처리: 여러 개별 호출 대신 목록 조회 API 활용
  • 병렬 처리: 독립적인 LB들의 서버 정보는 병렬로 수집 가능
  • 캐싱: 자주 변경되지 않는 정보는 적절한 캐싱 적용

메모리 관리

  • 임시 데이터 정리: 대용량 데이터 처리 후 명시적 메모리 해제
  • 메트릭 레이블 최적화: 불필요한 레이블 제거로 메모리 사용량 감소

메트릭 정의

실제 LB의 정보를 가지고 오는 Prometheus 메트릭은 다음과 같이 정의할 수 있습니다.

  # === Prometheus 메트릭 정의 ===
        # 1. 전체 LB 개수
        self.lb_count = Gauge(
            'ktcloud_lb_total_count',
            'Total number of load balancers',  # 전체 로드밸런서 개수
            registry=self.registry
        )
        # 2. LB 기본 정보 (상태, IP, 포트 등)
        self.lb_info = Gauge(
            'ktcloud_lb_info',
            'Load balancer information (value: 1=UP, 0=DOWN)',  # LB 정보 (1=정상, 0=다운)
            ['lb_id', 'lb_name', 'service_ip', 'service_port', 'service_type', 
             'lb_option', 'healthcheck_type', 'zone'],  # 레이블들
            registry=self.registry
        )
        # 3. LB별 연결된 서버 개수
        self.lb_server_count = Gauge(
            'ktcloud_lb_server_count',
            'Number of servers connected to load balancer',  # LB에 연결된 서버 수
            ['lb_id', 'lb_name', 'zone'],
            registry=self.registry
        )

 

 

추가적으로 LB별 연결된 서버의 정보를 가지고 오는 메트릭은 아래과 같이 구성이 가능합니다.

 # === 서버 성능 메트릭들 ===
        # 5. 서버별 현재 연결 수
        self.server_connections = Gauge(
            'ktcloud_server_current_connections',
            'Current number of connections to the server',  # 서버의 현재 연결 수
            ['lb_id', 'lb_name', 'server_ip', 'server_port', 'zone'],
            registry=self.registry
        )
        # 6. 서버별 처리량 (KB/s)
        self.server_throughput_rate = Gauge(
            'ktcloud_server_throughput_rate_kbps',
            'Server throughput rate in KB/s',  # 서버 처리량 (KB/초)
            ['lb_id', 'lb_name', 'server_ip', 'server_port', 'zone'],
            registry=self.registry
        )
        # 7. 서버별 평균 응답 시간 (TTFB - Time To First Byte)
        self.server_avg_ttfb = Gauge(
            'ktcloud_server_avg_ttfb_ms',
            'Average server Time To First Byte in milliseconds',  # 평균 첫 바이트 응답 시간 (ms)
            ['lb_id', 'lb_name', 'server_ip', 'server_port', 'zone'],
            registry=self.registry
        )

 

위와 같은 방식으로 서버별 현재 연결 VM수, 서버별 처리량, 서버별 응답시간, 서버별 초당 요청 처리량 등의 데이터를 수집하실 수 있습니다.


5️⃣Prometheus 설정 파일

Prometheus는 Pull 방식으로 동작하기 때문에, Custom Exporter에서 변환한 데이터를 Prometheus에서 수집하기 위한 설정을 해야 합니다.

참조
  • Prometheus/Grafana 버전
    • Prometheus: 3.1.0
    • Grafana: 11.4.0
  • Custom Exporter가 메트릭을 준비하고 대기
  • Prometheus가 설정된 주기마다 능동적으로 수집
  • 수집된 데이터를 내부 시계열 DB에 저장

설정의 실제 역할은 "어떻게, 언제, 어디서 데이터를 가져올 것인가”를 정의하는 것입니다.

  static_configs:
      - targets: ["localhost:9090"]

  # kt cloud Load Balancer 익스포터 설정
  - job_name: 'ktcloud-lb'
    static_configs:
      - targets: ['localhost:9105'] # 어디서 가져올 것인가?
        labels:
          environment: 'production' # 환경 구분
          service: 'ktcloud-lb' # 서비스 식별
    scrape_interval: 60s # LB 전용 수집 주기
    scrape_timeout: 20s # API 응답 대기 시간
    metrics_path: /metrics # 어떤 경로에서 가져올 것인가?
    honor_labels: true
  1. 포트 9105: custom exporter에서 설정한EXPORTER_PORT = 9105와 일치 필요
  2. 수집 주기
    • kt cloud LB Exporter: 60초
    • Exporter의 SCRAPE_INTERVAL = 60과 일치 시키고, API 호출 부하를 고려한 설정
  3. 타임아웃 설정: 20초로 설정(kt cloud API 응답 시간을 충분히 고려하여 설정)
  4. 라벨링
    • environment: 'production': 운영 환경임을 명시
    • service: 'ktcloud-lb': 서비스 구분을 위한 라벨
  5. honor_labels: true: Exporter에서 제공하는 라벨을 우선적으로 사용하는 설정

6️⃣Grafana 대시보드 구성

전체 현황 패널

대시보드 상단에는 Load Balancer의 전체 현황을 한눈에 볼 수 있는 패널들을 배치했습니다.

  • 총 LB 수: 현재 운영 중인 전체 Load Balancer 개수
  • 정상 LB 수: 정상 동작 중인 Load Balancer 개수
  • 다운 LB 수: 장애 상태인 Load Balancer 개수
  • 서비스 타입별 분포: HTTP, HTTPS, TCP 등 서비스 타입별 파이차트

[튜토리얼] kt cloud SDK와 Grafana로 Load Balancer 실시간 모니터링 구축하기

 

동적 변수 활용

Grafana의 변수 기능을 활용해 사용자가 원하는 Load Balancer를 선택하여 상세 정보를 볼 수 있도록 구성했습니다.

{
  "name": "selected_lb",
  "type": "query", 
  "query": "label_values(ktcloud_lb_info, lb_name)",
  "label": "상세 조회 LB (선택)"
}

 

이를 통해 수십 개의 Load Balancer 중에서 특정 LB만 선택하여 집중 모니터링 할 수 있습니다.

[튜토리얼] kt cloud SDK와 Grafana로 Load Balancer 실시간 모니터링 구축하기

 

LB에 연결된 VM 정보 패널

하단에는 선택된 Load Balancer에 연결된 VM 정보를 보여주는 패널들을 구성 했습니다.
위의 동적 변수를 활용하여 상세 조회 LB를 선택할 경우 해당 LB에 연결된 VM정보들을 보여줍니다.

  • 연결된 서버 상태 테이블: 각 서버의 IP, 포트, 상태 정보
  • TTFB (Time To First Byte): 서버별 평균 응답 시간 그래프
  • 처리량(Throughput): 서버별 네트워크 처리량 그래프
  • 요청 처리율: 서버별 초당 요청 처리 개수
  • 활성 연결 수: 서버별 현재 활성 연결 개수

[튜토리얼] kt cloud SDK와 Grafana로 Load Balancer 실시간 모니터링 구축하기


7️⃣실제 구현 대시보드

[튜토리얼] kt cloud SDK와 Grafana로 Load Balancer 실시간 모니터링 구축하기


마무리

kt cloud SDK와 Grafana를 결합한 Load Balancer 모니터링 대시보드를 통해 다음과 같은 가치를 얻을 수 있습니다.

  • 실시간 가시성: 모든 LB의 상태를 한 화면에서 실시간으로 확인
  • 신속한 장애 대응: 장애 발생 시 즉시 알림을 통한 빠른 대응
  • 성능 최적화: 서버별 성능 메트릭을 통한 부하 분산 최적화
  • 운영 효율성: 수동 확인 작업 없이 자동화된 모니터링

오픈소스 도구들을 활용하면 상용 모니터링 솔루션 대비 비용을 크게 절약하면서도 충분한 기능을 구현할 수 있습니다. 특히 Grafana의 풍부한 시각화 옵션과 kt cloud SDK의 편리한 API 연동이 큰 시너지를 만들어냈습니다. Custom Exporter(lb-exporter.py), Grafana 대시보드 파일(lb_dashboard_v0.5.json) 전체 소스코드 파일도 공유 드립니다.

lb-exporter.py
0.02MB
lb_dashboard_v0.5.json
0.03MB

 

알림 기능 등의 기능을 추가도 가능하며, 별도의 모니터링 솔루션이 없으신 경우 node_exporter를 통한 VM의 CPU, Memory, Disk, Network등 다른 리소스들까지 모니터링이 가능합니다. 이러한 모니터링 대시보드가 여러분의 클라우드 운영에 도움이 되길 바랍니다.

 

더 자세한 구현 코드와 설정 방법은 tam.ktcloud@kt.com으로 문의 주시기 바랍니다.


❓ 자주 묻는 질문 (FAQ)

Q. Custom Exporter에서 원자적 업데이트 패턴이 필요한 이유는 무엇인가요?
A. Prometheus는 스크랩 기반(pull-based) 방식으로 메트릭을 수집합니다. 이때 Exporter가 데이터를 부분적으로 갱신하는 중에 Prometheus가 스크랩을 수행하면, 일부 메트릭은 새로운 값이고 일부는 이전 값인 불일치(inconsistency)가 발생할 수 있습니다.
이를 방지하기 위해 원자적 업데이트(Atomic Update) 패턴을 사용합니다. 이 방식은 크게 두 단계로 나뉩니다.
  1. 데이터 수집 단계: 모든 최신 데이터를 임시 저장소에 먼저 모읍니다.
  2. 메트릭 교체 단계: 락을 걸고 기존 메트릭을 임시 저장소의 데이터로 한 번에 교체합니다.
이렇게 하면 Prometheus가 어떤 시점에 스크랩하더라도 일관된 스냅샷(snapshot)을 얻을 수 있습니다. 특히 대규모 환경에서 메트릭 수가 많거나 스크랩 주기가 짧을 때, 원자적 업데이트 패턴은 모니터링 결과의 신뢰성Exporter 성능 안정성을 동시에 확보할 수 있는 핵심 설계 원칙입니다.