Infra

모니터링 환경 설정 - 배포 포트가 변경될 때 8080...8081,, switching

SungHoJung 2025. 5. 26. 16:01

무중단 배포를 위해서 Blue-Green 전략을 사용하기로 했다. 클라우드 로드밸런서가 연결된 환경에서 블루 그린 배포를 구현할 수 있는 다양한 방법이 있지만, 우리 팀의 서비스는 한 물리 서버 내에서 모든 배포를 진행하고 있다. 블루 그린 배포 환경 구축에 대한 고찰은 아래 포스팅에서 살펴볼 수 있다.

 

0. 블루-그린 배포 환경 구성에 대한 고찰

이건 이전 포스팅을 참고하면 좋다. <- 아직 작성 안함

 

1. Promtail, Loki, Grafana, Prometheus, Logback-spring.xml이 뭔데?

이건 이전 포스트를 참고하면 좋다.<- 아직 작성 안함

 

2. (Problem) 8081 포트로 변경하면서 생기는 문제점

현재 Observability 구성

어떤 서비스가 영향을 받을까?

- logback-spring.xml 은 스프링 서버가 설정으로 가지고 운영하는 파일이기 때문에 서버가 바라보는 서비스는 Promtail 밖에 없다.

- 서버의 포트가 변경될 때는 서버를 바라보는 서비스만 영향 받는다.

- Prometheus  Pull 방식으로 동작해서, 서버 애플리케이션이 띄운 /actuator/prometheus 엔드포인트에 주기적으로 HTTP GET 요청을 보내기 때문에 서버를 바라본다고 말할 수 있다. 또, 해당 구성에서 서버를 바라보는 서비스는 Prometheus 밖에 없다.

- 결국 서버의 포트 변경으로 영향을 받는 서비스는 Prometheus 밖에 없다.

 

3. 현재 상황

현재 Prometheus는 도커 컨테이너로 관리하고 있고, 실행 스크립트는 아래와 같다

# docker-compose.obervability.yml 일부
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    ports:
      - "9090:9090"                       
    volumes:
      - ./prometheus/config:/etc/prometheus:ro
    command:
      - --config.file=/etc/prometheus/prometheus.yml
      - --web.enable-lifecycle
    networks:
      - loki-net

volumes 필드를 살펴보면, 도커를 실행하는 환경의 ./prometheus/config 폴더와 프로메테우스가 실행되는 컨테이너 내부의 etc/prometheus의 볼륨을 매핑해서 사용하고 있다.

command 필드를 보면 실행되는 프로메테우스 서비스의 설정 파일이, 프로메테우스가 실행되는 컨테이너 내부의etc/prometheus/prometheus.yml으로 설정되어 있다. 

그러면 이제 이 etc/prometheus/prometheus.yml 파일을 살펴보겠다.

# Prometheus의 설정 파일 prometheus.yml 
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'springboot'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: [ 'zaply-blue:8080' ]
        labels:

  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

static_configs의 targets 필드에서 zaply-blue라는 서비스의 8080 포트정적으로 설정돼 있다.

우리는 서버가 포트를 변경해서 실행될 때, 이 정적으로 설정된 포트 정보만 변경 가능하도록 하면 되는 것이다.

 

4. 그래서 어떻게 해결할까?

바라봐야하는 엔드포인트(포트) 정보를 별개의 json 파일로 분리하고, 기존에 매핑해놨던 로컬의 볼륨 내부에 작성하고 프로메테우스에서 설정 정보를 업데이트하도록 구성하면 된다. 그림의 플로우와 같다.

# Prometheus의 설정 파일 prometheus.yml 
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'springboot'
    metrics_path: '/actuator/prometheus'
	file_sd_configs:
      - files:
          - '/etc/prometheus/file_sd/springboot_targets.json'

  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

설정 파일이 /etc/prometheus/file_sd/springboot_targets.json을 바라보도록 설정했다. 현재 Github Actions를 통해 배포가 이루어지기 때문에 배포 과정에서 설정파일 작성과, reload 하는 과정을 추가해준다.

# GithubActions에 설정된 CD.yml 일부

# file_sd.json 에서 version 을 뽑아냄
CURRENT_VERSION=$(grep -Po '(?<="version": ")[^"]+' /etc/prometheus/file_sd/springboot_targets.json)
if [ "$CURRENT_VERSION" = "blue" ]; then
  INACTIVE_VERSION=green
  INACTIVE_PORT=8081
else
  INACTIVE_VERSION=blue
  INACTIVE_PORT=8080
fi
echo ">>> Current: $CURRENT_VERSION, Deploying to: $INACTIVE_VERSION($INACTIVE_PORT)"
            
# Prometheus file_sd.json 덮어쓰기
cat <<JSON >/etc/prometheus/file_sd/springboot_targets.json
[
  { 
    "labels": {
    "job": "springboot",
    "version": "${VERSION}",
    },
    "targets": ["zaply-${VERSION}:${INACTIVE}"]
  }
]
JSON
echo ">>> Updated Prometheus file_sd.json with version ${INACTIVE}"
            
# Prometheus 설정 리로드
curl -X POST http://localhost:9090/-/reload
echo ">>> Reloaded Prometheus configuration"