새벽에 울리는 알람 소리에 잠을 깨본 적이 있나요?
깊은 잠에 빠져 있는 새벽 3시, 갑작스럽게 울리는 휴대전화 알람 소리에 정신이 번쩍 든 경험이 있으신가요? 서비스가 중단되었다는 긴급 메시지를 확인하고 급하게 컴퓨터 앞에 앉았지만, 정작 어떤 컨테이너가 왜 죽었는지 알 수 없어 막막했던 적이 한두 번이 아닐 거예요. 로그를 뒤지고 컨테이너 상태를 하나하나 확인하는 동안 서비스 장애 시간은 길어지고, 운영자의 피로도는 극에 달합니다.
이런 문제는 단순히 운이 없어서 발생하는 것이 아니에요. 사전에 장애를 예측할 수 있는 관측 체계가 제대로 갖춰지지 않았기 때문입니다. 컨테이너 기반의 환경은 매우 역동적이라서, 단순히 서비스가 ‘살아있다’는 것만 확인해서는 부족해요. 메모리가 서서히 차오르고 있지는 않은지, 네트워크 응답 속도가 조금씩 느려지고 있지는 않은지를 실시간으로 파악해야 합니다.
도커 컴포즈를 사용하는 환경에서 모니터링을 구축한다는 것은 단순히 그래프를 그리는 일이 아니에요. 그것은 장애가 발생하기 전, 시스템이 보내는 미세한 신호를 포착하여 운영자가 대응할 시간을 버는 과정입니다. 이번 글을 통해 야간 장애 알림을 획기적으로 줄이고, 안정적인 컨테이너 운영을 가능하게 하는 실무적인 방법을 단계별로 설명해 드릴게요.
이 글에서는 다음과 같은 내용을 심도 있게 다룹니다.
- 컨테이너의 건강 상태를 스스로 체크하게 만드는 법
- 시스템 지표를 수집하고 시각화하는 도구 구성법
- 흩어져 있는 로그를 한곳으로 모아 검색하는 체계
- 실제 장애 상황에서 유용한 알림 규칙 설계하기
관측 체계를 구축하기 전 반드시 챙겨야 할 것들
무턱대고 화려한 대시보드부터 만들려고 하면 오히려 독이 될 수 있어요. 모니터링 도구는 많지만, 우리 서비스의 규모와 운영 인력의 숙련도에 맞는 도구를 선택하는 것이 가장 중요합니다. 무거운 도구를 도입했다가 오히려 모니터링 서버 자체가 시스템 자원을 다 잡아먹는 불상사가 생길 수도 있거든요.
본격적인 구축에 앞서 관측 가능성(Observability)의 세 가지 기둥을 이해해야 합니다. 첫째는 메트릭(Metrics)이에요. CPU, 메모리 사용량처럼 숫자로 표현되는 데이터입니다. 둘째는 로그(Logs)입니다. 애플리케이션이 남기는 기록들이죠. 셋째는 트레이스(Traces)인데, 이는 요청이 여러 컨테이너를 거쳐가는 경로를 추적하는 기능입니다. 도커 컴포즈 환경에서는 주로 메트릭과 로그에 집중하는 것부터 시작하는 것이 현명해요.
모니터링 시스템을 설계할 때는 ‘무엇을 볼 것인가’보다 ‘무엇을 무시할 것인가’를 먼저 결정해야 합니다. 너무 많은 지표를 수집하면 진짜 중요한 신호를 놓치는 ‘알람 피로(Alert Fatigue)’에 빠질 수 있어요.
운영 환경의 특성에 따라 적합한 도구 조합이 달라집니다. 아래 표를 통해 현재 상황에 맞는 방향을 고민해 보세요.
| 구분 | Prometheus + Grafana 조합 | ELK Stack 조합 | 클라우드 네이티브(Managed) |
|---|---|---|---|
| 주요 목적 | 시계열 지표 및 상태 모니터링 | 대규모 로그 수집 및 분석 | 운영 부담 최소화 |
| 장점 | 가볍고 설정이 매우 직관적임 | 로그 검색 기능이 매우 강력함 | 인프라 관리 노력이 거의 없음 |
| 단점 | 로그 저장 용량이 제한적임 | 자원 소모가 매우 큼 | 비용이 급격히 증가할 수 있음 |
| 추천 대상 | 도커 컴포즈 사용자 대다수 | 로그 분석이 핵심인 서비스 | 자원 여유가 있는 기업 |
준비가 되었다면 이제 실제 도커 컴포즈 파일에 어떻게 설정을 녹여낼지 단계별로 살펴볼게요. 핵심은 자동화라는 점을 잊지 마세요. 사람이 일일이 명령어를 치는 구조가 아니라, 컨테이너가 뜨면 자동으로 모니터링 대상에 포함되는 구조를 지향해야 합니다.
안정적인 컨테이너 운영을 위한 5단계 모니터링 구축법
이제 본격적으로 도커 컴포즈 환경에 모니터링 체계를 이식해 보겠습니다. 단순히 도구를 실행하는 것을 넘어, 각 단계가 어떻게 유기적으로 연결되는지가 핵심입니다. 이론적인 설명보다는 실제 구성 로직을 중심으로 설명해 드릴게요.
STEP 1. 컨테이너 자가 진단(Health Check) 설정하기
가장 먼저 할 일은 컨테이너가 단순히 ‘실행 중’인 상태를 넘어 ‘정상적으로 서비스할 수 있는 상태’인지 스스로 판단하게 만드는 거예요. 도커 컴포즈의 healthcheck 옵션을 사용하면 됩니다. 프로세스는 살아있지만 데이터베이스 연결이 끊겨서 실제로는 아무 일도 못 하는 ‘좀비 컨테이너’를 찾아내는 데 아주 효과적입니다.
예를 들어, 웹 서버라면 특정 URL에 요청을 보냈을 때 200 OK가 오는지 확인하는 명령어를 넣을 수 있어요. 설정 시 주의할 점은 검사 주기(interval)와 타임아웃(timeout)을 너무 짧게 잡지 않는 것입니다. 검사 자체가 시스템에 부하를 줄 수 있거든요. 보통 30초에서 1분 정도의 주기가 적당합니다. 이렇게 설정된 상태 값은 `docker ps` 명령어로도 확인할 수 있어 운영자가 직관적으로 상태를 파악하기 좋습니다.
STEP 2. 시계열 지표 수집(Prometheus & Node Exporter)
시스템의 상태를 숫자로 기록하기 위해 프로메테우스(Prometheus)를 배치해야 합니다. 하지만 프로메테우스 혼자서는 컨테이너 내부의 상세한 정보나 호스트 머신의 하드웨어 정보를 다 알 수 없어요. 그래서 두 가지 보조 도구가 필요합니다.
- Node Exporter: 호스트 머신의 CPU, 메모리, 디스크 사용량 등 하드웨어 지표를 수집합니다.
- cAdvisor: 도커 컨테이너별로 사용 중인 자원량(CPU 점유율, 네트워크 트래픽 등)을 수집합니다.
도커 컴포즈 파일에 이들을 서비스로 등록하고, 프로메테우스가 이들의 엔드포인트를 주기적으로 긁어갈(Scrape) 수 있도록 설정하세요. 이때 서비스 이름(Service Name)을 활용한 DNS 설정을 이용하면 네트워크 설정이 매우 간편해집니다. 프로메테우스 설정 파일에서 `targets: [‘cadvisor:8080’]`처럼 작성하기만 하면 됩니다.
STEP 3. 로그 통합 관리(Loki & Promtail)
컨테이너가 재시작되면 기존의 로그는 사라질 위험이 큽니다. 그래서 로그를 외부로 빼내어 저장해야 하죠. 최근에는 ELK 스택보다 훨씬 가벼운 Grafana Loki 조합이 도커 컴포즈 환경에서 큰 인기를 얻고 있습니다. Loki는 로그 전체를 인덱싱하는 대신 메타데이터(레이블)만 인덱싱하기 때문에 저장 공간을 훨씬 적게 차지합니다.
구조는 이렇습니다. 각 컨테이너가 로그를 남기면, Promtail이라는 에이전트가 해당 로그 파일들을 읽어서 Loki 서버로 쏴줍니다. Loki 서버는 이 로그들을 안전하게 보관하고, 우리는 나중에 Grafana를 통해 마치 SQL을 쓰듯 로그를 검색할 수 있습니다. “특정 에러 메시지가 포함된 로그만 보여줘” 같은 요청이 순식간에 해결되죠.
STEP 4. 시각화 대시보드 구성(Grafana)
수집된 데이터가 아무리 많아도 사람이 읽기 힘들면 소용없습니다. 그라파나(Grafana)를 사용하여 한눈에 들어오는 대시보드를 만들어야 합니다. 대시보드에는 반드시 다음과 같은 항목들이 포함되어야 합니다.
- 시스템 전반 상태: 전체 컨테이너 개수, 실행 중/중지 중/에러 상태의 비율
- 리소스 사용량: 호스트 CPU/메모리 사용량 및 컨테이너별 점유율 TOP 5
- 네트워크 및 디스크: 입출력량(I/O) 및 잔여 디스크 용량
- 애플리케이션 핵심 지표: HTTP 응답 시간, 에러율(5xx 에러), 요청 건수
처음부터 너무 많은 그래프를 넣으려 하지 마세요. 운영자가 가장 먼저 확인해야 할 ‘골든 시그널’에 집중하는 것이 좋습니다.
STEP 5. 지능형 알림 규칙 설계(Alertmanager)
마지막 단계는 알림입니다. 알림은 양날의 검이에요. 너무 안 오면 장애를 놓치고, 너무 자주 오면 무시하게 됩니다. 가장 권장하는 방식은 임계치 기반 알림과 상태 변화 알림을 분리하는 것입니다.
예를 들어, ‘메모리가 90%를 넘었을 때’는 경고(Warning) 수준으로 슬랙(Slack) 채널에 메시지를 보내고, ‘컨테이너가 갑자기 종료되었을 때’는 즉시 전화를 걸거나 긴급 알림을 보내도록 설정하는 식입니다. 프로메테우스의 Alertmanager를 활용하면 이러한 복잡한 로직을 구현할 수 있습니다. 알림 메시지에는 반드시 장애가 발생한 컨테이너 이름과 발생 시간, 그리고 확인해야 할 대시보드 링크를 포함하세요. 그래야 운영자가 당황하지 않고 바로 대응할 수 있습니다.
모니터링 시스템 자체도 컨테이너로 운영된다면, 모니터링 서버의 자원 상태를 모니터링할 별도의 외부 수단(예: 호스트 자체의 모니터링)을 하나쯤은 두는 것이 안전합니다.
자주 하는 실수와 해결법
모니터링 체계를 구축하다 보면 예상치 못한 난관에 부딪히기 마련입니다. 실제 현장에서 가장 많이 발생하는 실수 5가지를 정리했습니다.
- ❌ 모든 지표에 알림을 설정함
→ 왜 발생하는가: 모든 상황을 다 감시하고 싶은 욕심 때문입니다.
✅ 해결법: 서비스 가용성에 직접적인 영향을 주는 핵심 지표 3~5개에만 즉각적인 알림을 걸고, 나머지는 대시보드로만 확인하세요. - ❌ Health Check 주기를 너무 짧게 설정함
→ 왜 발생하는가: 장애를 1초라도 빨리 알고 싶기 때문입니다.
✅ 해결법: 검사 자체가 부하를 일으켜 장애를 유발할 수 있습니다. 서비스의 성격에 따라 30초~1분 사이로 적절한 타협점을 찾으세요. - ❌ 로그 보관 기간을 설정하지 않음
→ 왜 발생하는가: 로그를 쌓아두기만 하면 된다고 생각하기 때문입니다.
✅ 해결법: 디스크 용량은 반드시 한계가 옵니다. Loki나 로그 수집기 설정에서 반드시 보관 주기(Retention)를 지정하세요. - ❌ 컨테이너 자원 제한(Limit)을 설정하지 않음
→ 왜 발생하는가: 성능을 최대한 뽑아 쓰고 싶기 때문입니다.
✅ 해결법: 특정 컨테이너가 자원을 독점하면 모니터링 도구조차 죽을 수 있습니다. 반드시 Docker Compose 파일에 CPU와 메모리 제한을 명시하세요. - ❌ 알림 메시지를 모호하게 작성함
→ 왜 발생하는가: 알림 설정이 귀찮기 때문입니다.
✅ 해결법: “에러 발생”이라고만 보내지 마세요. “[Production] Web-API 컨테이너 메모리 90% 초과
지속 가능한 관측 체계를 위한 마지막 점검
모니터링 체계를 구축하는 것은 마라톤과 같습니다. 한 번에 완벽한 시스템을 만들려고 하기보다는, 장애를 겪으면서 조금씩 살을 붙여 나가는 과정이 필요해요. 오늘 배운 내용을 바탕으로 지금 당장 실행할 수 있는 것부터 시작해 보세요. 시스템이 여러분 대신 밤을 지새워줄 수 있도록 만드는 것이 목표입니다.
✅ 핵심 요약- 컨테이너에 healthcheck를 설정하여 좀비 프로세스를 방지하세요.
- Prometheus와 cAdvisor로 자원 사용량을 숫자로 기록하세요.
- Loki를 통해 흩어진 로그를 한곳으로 모으고 보관 주기를 설정하세요.
- Grafana 대시보드는 핵심 지표(골든 시그널) 중심으로 단순하게 구성하세요.
- 알림은 심각도에 따라 채널을 분리하여 알람 피로를 줄이세요.
이제 무엇을 해야 할지 감이 오시나요? 다음의 단계별 실행 계획을 따라가 보세요.
- 오늘 할 일: 현재 운영 중인 서비스 중 가장 중요한 컨테이너 하나에
healthcheck옵션 추가하기 - 이번 주 할 일: 도커 컴포즈에 Prometheus와 Grafana를 추가하여 기본 CPU/메모리 그래프 확인하기
- 실행 직전 할 일: 알림 메시지에 컨테이너 이름과 대시보드 링크가 포함되어 있는지 확인하기
가장 중요한 것은 핵심 지표 3가지만 먼저 정하고 알림을 거는 것입니다. 처음부터 너무 거창하게 시작하지 마세요. 작은 성공이 쌓여야 안정적인 운영이 가능합니다.
도커 컴포즈의 더 깊은 활용법이 궁금하시다면, 도커 컴포즈 기본 개념 완벽 정리 — 개념부터 실무 활용까지 한눈에 보는 가이드를 함께 읽어보시는 것을 추천드려요.