Skip to content

[FEATURE] Prometheus/Grafana 환경 추가#30

Merged
youyeon11 merged 5 commits intodevelopfrom
feat/add-monitoring-29
Oct 2, 2025
Merged

[FEATURE] Prometheus/Grafana 환경 추가#30
youyeon11 merged 5 commits intodevelopfrom
feat/add-monitoring-29

Conversation

@youyeon11
Copy link
Contributor

📌 작업 목적

GPU 환경에서의 모니터링 추가를 위하여 Prometheus와 Grafana를 추가했습니다.


🗂 작업 유형

  • 기능 추가 (Feature)
  • 버그 수정 (Bug Fix)
  • 리팩터링 (Refactor)
  • 성능 개선 (Performance)
  • 테스트 추가/수정 (Test)
  • 빌드/배포/환경 설정 (Chore)
  • 문서 수정 (Docs)

🔨 주요 작업 내용

  • 라이브러리 추가하였습니다(prometheus)
prometheus-client==0.19.0
prometheus-fastapi-instrumentator==6.1.0
  • prometheus의 rule에 다음 데이터를 수집하도록 설정하였습니다
  - job_name: 'fastapi-actuator-blue'
    metrics_path: '/actuator/prometheus'
    scrape_interval: 1m
    static_configs:
      - targets: [ 'app-blue:8000' ]
  - job_name: 'fastapi-actuator-green'
    metrics_path: '/actuator/prometheus'
    scrape_interval: 1m
    static_configs:
      - targets: [ 'app-green:8001' ]

📎 관련 이슈


@gemini-code-assist
Copy link

Summary of Changes

Hello @youyeon11, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 GPU 환경에서 애플리케이션의 성능과 상태를 모니터링하기 위한 기반을 마련합니다. Prometheus와 Grafana를 통합하여 FastAPI 애플리케이션의 메트릭을 수집하고 시각화할 수 있도록 하며, 이를 통해 시스템의 안정성과 운영 효율성을 향상시키는 것을 목표로 합니다.

Highlights

  • 모니터링 스택 추가: GPU 환경 모니터링을 위해 Prometheus와 Grafana를 도입했습니다.
  • FastAPI 애플리케이션 계측: prometheus-fastapi-instrumentator 라이브러리를 사용하여 FastAPI 애플리케이션에 Prometheus 메트릭 엔드포인트(/actuator/prometheus)를 추가했습니다.
  • Prometheus 설정 업데이트: 블루/그린 배포 환경의 FastAPI 애플리케이션에서 메트릭을 수집하도록 Prometheus 스크랩 설정을 추가했습니다.
  • 배포 스크립트 개선: docker compose 명령어에 -f docker-compose.yml 옵션을 명시하여 배포 스크립트의 안정성을 높였습니다.
  • 모니터링 서비스 정의: docker-compose.monitoring.yml 파일을 추가하여 Prometheus 및 Grafana 서비스를 Docker Compose로 관리할 수 있도록 정의했습니다.
  • Prometheus 규칙 및 설정 파일 추가: prometheus-rule.ymlprometheus.yml 파일을 추가하여 Prometheus의 경고 규칙과 전역 설정을 구성했습니다.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/workflow.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@youyeon11 youyeon11 changed the title Feat/add monitoring 29 [FEATURE] Prometheus/Grafana 환경 추가 Oct 2, 2025
@youyeon11
Copy link
Contributor Author

🤖 Gemini 코드 리뷰 결과

네, 시니어 개발자로서 제출된 PR에 대한 코드 리뷰를 작성하겠습니다.


안녕하세요, [동료 개발자 이름]님. Prometheus/Grafana 모니터링 환경을 추가하는 PR 잘 확인했습니다. 우리 서비스의 관측 가능성(Observability)을 높이는 중요한 첫걸음이네요! 전체적으로 모니터링 스택의 기본 구조를 잘 구성해 주셨습니다. 몇 가지 개선점을 더하면 앞으로 더 안정적이고 확장성 있게 운영할 수 있을 것 같아 아래와 같이 피드백을 정리했습니다.

1) PR 의도 요약

이 PR은 GPU 기반 서비스 환경의 안정성과 성능을 지속적으로 추적하기 위해 모니터링 시스템을 도입하는 것을 목표로 합니다. FastAPI 애플리케이션에 prometheus-fastapi-instrumentator 라이브러리를 적용하여 HTTP 요청 메트릭을 노출하고, Docker Compose를 이용해 Prometheus와 Grafana 컨테이너를 배포합니다. 또한, Blue/Green 배포 환경에 맞게 각 애플리케이션 인스턴스의 메트릭을 수집하고, 기본적인 알림 규칙을 설정하는 내용이 핵심입니다.

2) 전반적 평가 (품질/가독성/테스트/아키텍처)

  • 컨벤션: 전반적인 코드와 설정 파일(YAML)의 형식이 깔끔하고 표준 컨벤션을 잘 따르고 있습니다.
  • 네이밍/모듈 경계: 모니터링 관련 설정 파일(docker-compose.monitoring.yml, prometheus.yml 등)을 deployment 디렉터리에 분리하여 관리한 점이 책임 분리 원칙에 부합하여 좋습니다.
  • 테스트 전략: 인프라 변경의 특성상 자동화된 테스트는 없지만, 실제 배포 후 Staging 환경에서 Prometheus UI를 통해 타겟들이 정상적으로 수집되는지, Grafana 대시보드가 잘 그려지는지, 그리고 의도적으로 부하를 발생시켜 알림이 동작하는지 검증하는 과정이 반드시 필요합니다.

3) 우선순위별 피드백 목록

[P1] Prometheus 알림 규칙(Rule) 표현식 오류

  • 파일/위치: deployment/prometheus-rule.yml:13

  • 근거(왜 문제인지): prometheus-fastapi-instrumentator 라이브러리는 기본적으로 Histogram 타입의 메트릭(http_requests_latency_seconds)을 생성합니다. 제안된 expr: api_http_request_latencies_second{quantile="0.5"} > 1 표현식은 Summary 타입 메트릭에서 사용되는 방식이며, 메트릭 이름(...latencies_second)에도 오타가 있습니다. 따라서 이 알림 규칙은 실제로는 전혀 동작하지 않습니다.

  • 영향(버그): API 지연 시간이 실제로 1초를 초과하더라도 알림이 발생하지 않아 장애 상황을 인지하지 못하는 심각한 문제가 발생합니다. 모니터링의 핵심 기능인 '알림'이 동작하지 않게 됩니다.

  • 제안(구체적 조치): Histogram 타입의 메트릭에서 분위수(Quantile)를 계산하기 위해 PromQL의 histogram_quantile() 함수를 사용해야 합니다. 아래와 같이 수정하는 것을 제안합니다.

    # deployment/prometheus-rule.yml
    
      - alert: APIHighRequestLatency
        # Histogram 타입의 메트릭에서 95% 분위수를 계산하도록 수정
        expr: histogram_quantile(0.95, sum(rate(http_requests_latency_seconds_bucket[5m])) by (le, job, instance)) > 1.0
        for: 10m
        annotations:
          summary: "High request latency on {{ $labels.instance }}"
          # 95% 요청의 지연 시간이 1초를 초과했음을 명시
          description: "{{ $labels.instance }} has a 95th percentile request latency above 1s (current value: {{ $value }}s)"

    추가 설명: 50% 중앙값(median) 대신 95% 또는 99% 분위수(percentile)를 기준으로 삼는 것이 일부 느린 요청(tail latency)을 탐지하는 데 더 효과적입니다.

[P2] Docker Compose 내 호스트 경로 하드코딩

  • 파일/위치: deployment/docker-compose.monitoring.yml:6, deployment/docker-compose.monitoring.yml:7, deployment/docker-compose.monitoring.yml:21

  • 근거(왜 문제인지): 볼륨 마운트 경로에 /home/ubuntu/... 와 같이 특정 사용자 및 절대 경로가 하드코딩되어 있습니다. 이는 다른 환경(예: 로컬 PC, 다른 계정의 서버)에서의 재사용성을 크게 저해합니다.

  • 영향(유지보수): 다른 팀원이나 다른 서버 환경에서 이 docker-compose 파일을 실행하려면 매번 경로를 수정해야 하므로, 설정이 깨지기 쉽고 이식성이 떨어집니다. 로컬 테스트도 번거로워집니다.

  • 제안(구체적 조치): Docker Compose 파일이 위치한 곳을 기준으로 상대 경로를 사용하면 이식성을 크게 높일 수 있습니다.

    # deployment/docker-compose.monitoring.yml
    
    services:
      prometheus:
        # ...
        volumes:
          # 절대 경로 대신 상대 경로 사용
          - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
          # 데이터 볼륨은 Docker가 관리하는 명명된 볼륨(named volume)으로 변경
          - prometheus-data:/prometheus
        # ...
      grafana:
        # ...
        volumes:
          # 데이터 볼륨은 Docker가 관리하는 명명된 볼륨(named volume)으로 변경
          - grafana-data:/var/lib/grafana
        # ...
    
    # 파일 최하단에 명명된 볼륨 정의 추가
    volumes:
      prometheus-data:
      grafana-data:

    이렇게 하면 docker compose 명령어 실행 위치와 무관하게 docker-compose.monitoring.yml 파일이 있는 디렉터리 기준으로 prometheus.yml을 찾게 되고, 데이터는 Docker가 관리하여 훨씬 안정적입니다.

[P2] 비효율적인 서비스 디스커버리 방식

  • 파일/위치: deployment/prometheus.yml:18, deployment/prometheus.yml:22

  • 근거(왜 문제인지): Prometheus와 Node Exporter를 수집 대상으로 설정할 때 ${REMOTE_HOST} 환경 변수를 사용하고 있습니다. 이는 Docker 내부 네트워크 통신이 아닌, 호스트의 외부 IP를 통해 트래픽이 나갔다가 다시 들어오는 비효율적인 구조를 만듭니다.

  • 영향(성능/안정성): 불필요한 네트워크 홉(hop)을 거치며 미세한 성능 저하를 유발하고, 호스트의 방화벽 설정에 따라 스크레이프가 실패할 수 있는 잠재적 위험이 있습니다.

  • 제안(구체적 조치): 같은 Docker 네트워크에 속한 서비스들은 서비스 이름을 이용해 통신할 수 있습니다. Docker의 내장 DNS를 활용하여 서비스 이름으로 직접 타겟을 지정하는 것이 가장 안정적이고 효율적입니다.

    # deployment/prometheus.yml
    
    # ...
      - job_name: 'prometheus'
        # ...
        static_configs:
          # REMOTE_HOST 대신 Docker 서비스 이름(prometheus)과 내부 포트(9090) 사용
          - targets: ['prometheus:9090']
            labels:
              service: 'monitor-1'
      - job_name: 'node'
        static_configs:
          # Node Exporter가 있다면, 해당 서비스 이름으로 지정해야 합니다.
          # 예: - targets: ['node-exporter:9100']
          # 현재는 Prometheus 자신을 가리키므로 위 job_name: 'prometheus'와 중복됩니다. 이 타겟의 의도를 다시 확인해볼 필요가 있습니다.
          - targets: ['prometheus:9090']

[P3] Prometheus Scrape Job 설정 중복

  • 파일/위치: deployment/prometheus.yml:24-34

  • 근거(왜 문제인지): fastapi-actuator-bluefastapi-actuator-green 잡(job)의 설정이 targets를 제외하고 모두 동일합니다. 이는 불필요한 중복입니다.

  • 영향(유지보수): 나중에 scrape_interval이나 metrics_path를 변경해야 할 때 두 군데를 모두 수정해야 하므로 실수가 발생할 가능성이 있고 관리가 번거롭습니다.

  • 제안(구체적 조치): 하나의 잡에 여러 타겟을 등록하여 중복을 제거할 수 있습니다. job 레이블을 통해 Blue/Green을 구분하는 것이 더 일반적인 패턴입니다.

    # deployment/prometheus.yml
    
      # ...
      - job_name: 'fastapi-app' # 통합된 잡 이름
        metrics_path: '/actuator/prometheus'
        scrape_interval: 1m
        static_configs:
          # blue와 green 타겟을 한 번에 정의
          - targets: [ 'app-blue:8000', 'app-green:8001' ]

[P3] 환경 변수 관리 방안 부재

  • 파일/위치: deployment/docker-compose.monitoring.yml:3, deployment/docker-compose.monitoring.yml:17

  • 근거(왜 문제인지): docker-compose.monitoring.yml 파일에서 ${PROMETHEUS_USER}${GRAFANA_USER} 같은 환경 변수를 사용하고 있지만, 이 변수들을 어떻게 설정해야 하는지에 대한 안내가 없습니다.

  • 영향(유지보수): 다른 개발자가 이 프로젝트를 처음 설정할 때 어떤 환경 변수가 필요한지 알기 어려워 설정 과정에서 시간을 낭비하거나 오류를 겪을 수 있습니다.

  • 제안(구체적 조치): 프로젝트 루트에 .env.example 파일을 추가하여 필요한 환경 변수 목록과 예시 값을 제공하고, 실제 값은 각자 .env 파일에 작성하여 사용하도록 안내하는 것이 좋습니다. .gitignore.env 파일을 추가하는 것도 잊지 마세요.

    .env.example 파일 예시:

    # Monitoring Stack User IDs (Check with 'id -u' command on the host)
    PROMETHEUS_USER=1000
    GRAFANA_USER=472
    
    # Prometheus scrape target host (if needed, but prefer Docker DNS)
    REMOTE_HOST=your.server.ip

[P4] Docker 네트워크 이름 구체화 제안

  • 파일/위치: deployment/docker-compose.monitoring.yml:25, deployment/docker-compose.monitoring.yml:30

  • 근거(왜 문제인지): 네트워크 이름으로 mynetwork를 사용하고 있습니다. 이는 매우 일반적인 이름이라, 같은 호스트에서 다른 프로젝트가 우연히 같은 네트워크 이름을 사용할 경우 충돌이 발생할 수 있습니다.

  • 영향(안정성): 드물지만 네트워크 충돌 시 서비스가 예상치 못하게 서로 통신하거나, 컨테이너 시작에 실패할 수 있습니다.

  • 제안(구체적 조치): 프로젝트 이름을 접두사로 사용해 더 구체적인 이름으로 변경하는 것을 권장합니다. 예를 들어, dearbelly-monitoring-net 과 같이요.

    # deployment/docker-compose.monitoring.yml
    
    # ...
    networks:
      - dearbelly-monitoring-net # 더 구체적인 이름으로 변경
    
    networks:
      dearbelly-monitoring-net:
        driver: bridge

다시 한번 좋은 작업에 감사드립니다. 위에 제안된 내용들을 검토해 보시고 궁금한 점이 있다면 언제든지 편하게 이야기 나눠요

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

GPU 환경에서의 모니터링을 위해 Prometheus와 Grafana를 추가하는 PR이네요. 전체적인 방향은 좋지만, 몇 가지 중요한 수정이 필요해 보입니다. 특히, Docker 설정의 하드코딩된 경로, 잘못된 Prometheus 설정 및 경고 규칙 등은 시스템의 안정성과 이식성에 영향을 줄 수 있습니다. 아래에 자세한 리뷰를 남겼으니 확인 부탁드립니다.

monitor: 'codelab-monitor'
query_log_file: query_log_file.log
rule_files:
- "prometheus-rule.yml"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

prometheus-rule.yml 파일을 규칙 파일로 참조하고 있지만, docker-compose.monitoring.yml 파일에서 해당 파일을 컨테이너로 마운트하는 설정이 누락되었습니다. 이로 인해 Prometheus가 경고 규칙을 로드하지 못하여 알림이 동작하지 않습니다. docker-compose.monitoring.ymlprometheus 서비스 volumes에 다음을 추가해야 합니다:

- ./prometheus-rule.yml:/etc/prometheus/prometheus-rule.yml:ro

summary: "Instance {{ $labels.instance }} down"
description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes."
- alert: APIHighRequestLatency
expr: api_http_request_latencies_second{quantile="0.5"} > 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

prometheus-fastapi-instrumentator 라이브러리는 기본적으로 Histogram 타입의 http_requests_latency_seconds 메트릭을 생성합니다. 현재 사용된 api_http_request_latencies_second{quantile="0.5"} 표현식은 Summary 타입의 메트릭을 위한 것이므로, 이 경고 규칙은 동작하지 않습니다. Histogram 메트릭에서 분위수(quantile)를 계산하려면 histogram_quantile 함수를 사용해야 합니다. 또한 메트릭 이름도 http_requests_latency_seconds로 수정이 필요해 보입니다.

        expr: histogram_quantile(0.5, sum(rate(http_requests_latency_seconds_bucket[5m])) by (le, job, instance)) > 1

metrics_path: '/actuator/prometheus'
scrape_interval: 1m
static_configs:
- targets: [ 'app-green:8001' ] No newline at end of file

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

app-green 서비스의 수집 대상 포트가 8001로 잘못 설정되어 있습니다. docker-compose.yml을 보면 app-green 컨테이너는 내부적으로 8000 포트를 사용하고, 이를 호스트의 8001 포트로 매핑합니다. Docker 브릿지 네트워크 내에서 서비스 간 통신은 내부 포트를 사용해야 하므로, app-green:8000으로 수정해야 합니다.

      - targets: [ 'app-green:8000' ]

Comment on lines +7 to +8
- /home/ubuntu/dearbelly/deployment/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- /home/ubuntu/prometheus/volume:/prometheus/data

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

볼륨 경로에 /home/ubuntu와 같은 하드코딩된 절대 경로를 사용하면 다른 환경으로 이식하기가 매우 어렵습니다. 설정 파일은 상대 경로를 사용하고, 데이터 볼륨은 Docker의 named volume을 사용하는 것을 강력히 권장합니다. 이렇게 하면 다른 개발자나 서버 환경에서도 쉽게 컨테이너를 실행할 수 있습니다.

      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus-data:/prometheus/data


grafana:
user: ${GRAFANA_USER}
image: grafana/grafana:latest

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Docker 이미지에 :latest 태그를 사용하는 것은 예기치 않은 버전 업데이트로 인한 장애를 유발할 수 있습니다. 프로덕션 환경에서는 특정 버전을 명시하여 안정성을 확보하는 것이 좋습니다. 예를 들어 grafana/grafana:10.4.2와 같이 구체적인 버전을 사용해주세요.

metrics_path: '/actuator/prometheus'
scrape_interval: 1m
static_configs:
- targets: [ 'app-green:8001' ] No newline at end of file

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

파일 끝에 개행 문자가 없습니다. POSIX 표준에 따라 텍스트 파일은 개행 문자로 끝나야 합니다.

evaluation_interval: 2m
external_labels:
monitor: 'codelab-monitor'
query_log_file: query_log_file.log

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

query_log_file을 설정하면 컨테이너 내부에 로그 파일이 생성됩니다. 컨테이너가 재시작되면 이 로그는 사라집니다. 로그를 영속적으로 보관하거나 중앙에서 관리하려면, 이 설정을 제거하고 stdout/stderr로 로그를 출력하여 Docker의 로깅 드라이버를 사용하는 것을 고려해보세요.

@@ -0,0 +1,17 @@
groups:
- name: example

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

규칙 그룹 이름이 example로 되어 있습니다. fastapi-rules와 같이 좀 더 의미 있는 이름으로 변경하면 향후 규칙을 관리하기가 더 수월해집니다.

  - name: fastapi-rules

for: 10m
annotations:
summary: "High request latency on {{ $labels.instance }}"
description: "{{ $labels.instance }} has a median request latency above 1s (current value: {{ $value }}s)" No newline at end of file

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

파일 끝에 개행 문자가 없습니다. POSIX 표준에 따라 텍스트 파일은 개행 문자로 끝나야 합니다.

logging No newline at end of file
logging
prometheus-client==0.19.0
prometheus-fastapi-instrumentator==6.1.0 No newline at end of file

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

파일 끝에 개행 문자가 없습니다. POSIX 표준에 따라 텍스트 파일은 개행 문자로 끝나야 합니다.

@youyeon11 youyeon11 merged commit e1abee9 into develop Oct 2, 2025
1 check passed
@youyeon11 youyeon11 mentioned this pull request Oct 2, 2025
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant