Step 14-15. 자동 배포 + 알림 (Deploy & Alerting)
이 문서는 인프라 파이프라인 실습의 Step 14-15이다. 돌아가기: 09-hands-on.md
용어 안내
이 문서에서 “슬롯”은 학습용 비유다. 실무 용어가 아니다. 각 슬롯 옆에 실무에서 실제로 쓰는 용어를 병기한다.
Step 14. 자동 배포 — ④ Deploy/Release 자동화 (슬롯④ / 실무: CD 파이프라인)
왜 자동 배포가 필요한가? (WHY)
Step 11에서 새 이미지가 레지스트리에 올라가도 사람이 직접 docker compose pull과
docker compose up -d를 실행해야 했다. 매번 사람이 해야 한다.
문제 상황: 새벽 3시에 긴급 패치를 배포해야 한다면? 주말에 버전 업데이트가 필요하다면? 사람이 수동으로 하면 실수가 생기고, 시간이 걸리고, 담당자가 항상 대기해야 한다.
자동화하면: 코드를 push하는 순간 → 빌드 → 레지스트리 → 서버 반영까지 사람 개입 없이 완료된다.
용어 정리
Deploy (디플로이)
- 영어 뜻: “배치하다, 전개하다” — 군대를 전선에 배치하다
- IT 뜻: 완성된 프로그램을 실제 서버에 갖다 놓는 행위
- 비유: 공장에서 만든 제품을 매장 진열대에 올리는 것
CD (Continuous Delivery / Continuous Deployment)
- 영어 뜻: “지속적 전달 / 지속적 배포”
- IT 뜻: 이미지가 바뀌면 자동으로 서버에 반영되는 체계
- 비유: 공장 컨베이어 벨트 끝에 자동 진열 로봇이 있는 것
GitOps (깃옵스)
- 영어 뜻: “Git + Operations” — Git으로 운영을 관리
- IT 뜻: Git 저장소의 상태가 곧 서버의 상태. Git이 바뀌면 서버도 자동으로 바뀐다
- 비유: 설계도를 수정하면 공장이 자동으로 설계도대로 제품을 바꾸는 것
- 실무 도구: ArgoCD, Flux 등
로컬 체험: Watchtower
Watchtower (워치타워)
- 영어 뜻: “감시탑” — 높은 곳에서 주변을 감시하는 탑
- IT 뜻: Docker 컨테이너의 이미지가 레지스트리에서 업데이트되면 자동으로 pull & restart 해주는 도구
- 비유: 진열대를 계속 감시하다가, 새 제품이 창고에 도착하면 자동으로 교체해주는 직원
14-1. docker-compose.yml에 Watchtower 추가
watchtower:
image: containrrr/watchtower # Watchtower 공식 이미지
volumes:
- /var/run/docker.sock:/var/run/docker.sock # Docker 소켓 접근 — 다른 컨테이너를 관리하려면 필요
environment:
- WATCHTOWER_POLL_INTERVAL=30 # 30초마다 레지스트리에서 새 이미지가 있는지 확인
- WATCHTOWER_CLEANUP=true # 교체 후 이전 이미지를 자동 삭제 (디스크 절약)
command: my-infra-lab-app-1 # 감시할 컨테이너 이름 (이것만 자동 업데이트)
14-2. 자동 배포 테스트
# ① app.js에서 버전 변경
# 기존: "1.0.0" → 변경: "2.0.0"
# const APP_VERSION = "2.0.0";
# ② Git에 올리기 — GitHub Actions가 새 이미지를 ghcr.io에 push한다
git add app.js
git commit -m "bump version to 2.0.0"
git push origin main
# ③ 기다린다 (CI 빌드 완료 후 + Watchtower 감지까지 약 2~5분)
# ④ 결과 확인 — 사람이 아무것도 안 했는데 버전이 바뀌어 있다
curl localhost/info
# 출력 예시: {"version":"2.0.0", ...}
핵심 체감: 사람이 아무것도 안 했는데 배포가 됐다. 이것이 CD의 핵심이다.
실무에서 ArgoCD가 하는 일도 본질은 같다. Git에서 변경을 감지 → 새 버전을 클러스터에 적용. Watchtower는 그 축소판이다.
Step 15. 알림 — ⑪ Alerting / Incident Response (슬롯⑪ / 실무: 모니터링 알림)
왜 알림이 필요한가? (WHY)
자동 배포까지 갖췄다. 하지만 서버가 죽으면 누가 아는가?
문제 상황: 새벽 3시에 서버가 죽었는데, 아침 9시에 출근해서야 알게 된다면? 6시간 동안 사용자는 서비스를 못 쓴다. 자동 알림이 있어야 즉시 대응 가능하다.
용어 정리
Alerting (얼러팅)
- 영어 뜻: “경보, 경고” — 위험을 알리는 신호
- IT 뜻: 시스템에 이상이 생기면 자동으로 담당자에게 알림을 보내는 것
- 비유: 화재 경보기. 연기를 감지하면 자동으로 사이렌이 울린다
Incident Response (인시던트 리스폰스)
- 영어 뜻: “사고 대응” — 사고가 발생했을 때 대응하는 절차
- IT 뜻: 경보 발생 후 누가, 어떻게 문제를 해결하는지의 체계
- 비유: 화재 경보가 울리면 소방대가 출동하는 매뉴얼
- 실무 용어: “온콜(on-call)” = 경보를 받을 당번, “인시던트 관리” = 사고 처리 프로세스
로컬 체험: Prometheus + Alertmanager
15-1. Express 앱에 /metrics 엔드포인트 추가
# prom-client 라이브러리 설치 — Prometheus가 읽을 수 있는 형식으로 메트릭을 노출한다
npm install prom-client
// app.js에 추가할 코드
const client = require('prom-client'); // Prometheus 메트릭 라이브러리 로드
// 기본 메트릭 자동 수집 (CPU, 메모리, 이벤트루프 등)
client.collectDefaultMetrics();
// 요청 횟수를 세는 커스텀 카운터
const httpRequestCounter = new client.Counter({
name: 'http_requests_total', // 메트릭 이름 (Prometheus에서 이 이름으로 조회)
help: 'Total HTTP requests', // 메트릭 설명
labelNames: ['method', 'path'] // 요청 방법(GET/POST)과 경로별로 구분
});
// 모든 요청마다 카운터 증가
app.use((req, res, next) => {
httpRequestCounter.inc({ method: req.method, path: req.path }); // 카운터 +1
next(); // 다음 미들웨어로 넘기기
});
// Prometheus가 이 엔드포인트를 주기적으로 호출해서 메트릭을 가져간다
app.get('/metrics', async (req, res) => {
res.set('Content-Type', client.register.contentType); // Prometheus 형식 지정
res.end(await client.register.metrics()); // 수집된 메트릭 반환
});
15-2. Prometheus 설정 파일 생성
# 프로젝트 루트에 prometheus 디렉토리 생성
mkdir -p prometheus
# prometheus/prometheus.yml — Prometheus 메인 설정
global:
scrape_interval: 15s # 15초마다 대상에서 메트릭을 수집한다
scrape_configs:
- job_name: 'express-app' # 수집 대상의 이름 (Prometheus UI에서 이 이름으로 표시)
static_configs:
- targets: ['app:3000'] # 메트릭을 가져올 주소 (app 컨테이너의 3000번 포트)
alerting:
alertmanagers:
- static_configs:
- targets: ['alertmanager:9093'] # 알림을 보낼 Alertmanager 주소
rule_files:
- 'alert_rules.yml' # 알림 규칙 파일 경로
15-3. 알림 규칙 파일 생성
# prometheus/alert_rules.yml — 어떤 상황에서 알림을 발생시킬지 정의
groups:
- name: app-alerts # 알림 그룹 이름
rules:
- alert: AppDown # 알림 이름 — "앱이 죽었다"
expr: up{job="express-app"} == 0 # 조건: express-app이 응답하지 않으면 (0 = 다운)
for: 30s # 30초 이상 지속되면 알림 발생 (일시적 오류 무시)
labels:
severity: critical # 심각도: 치명적
annotations:
summary: "Express 앱이 응답하지 않습니다!" # 알림 메시지
15-4. Alertmanager 설정 파일 생성
# prometheus/alertmanager.yml — 알림을 어디로 보낼지 설정
route:
receiver: 'console-log' # 기본 수신자 이름
group_wait: 10s # 알림 그룹화 대기 시간 (10초 동안 모아서 한 번에)
receivers:
- name: 'console-log' # 수신자 정의 — 로컬이므로 로그로 출력
# 실무에서는 여기에 Slack webhook, PagerDuty, 이메일 등을 설정한다
15-5. docker-compose.yml에 Prometheus + Alertmanager 추가
prometheus:
image: prom/prometheus # Prometheus 공식 이미지
ports:
- "9090:9090" # 웹 UI 접근용 포트
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml # 메인 설정 마운트
- ./prometheus/alert_rules.yml:/etc/prometheus/alert_rules.yml # 알림 규칙 마운트
alertmanager:
image: prom/alertmanager # Alertmanager 공식 이미지
ports:
- "9093:9093" # 웹 UI 접근용 포트
volumes:
- ./prometheus/alertmanager.yml:/etc/alertmanager/alertmanager.yml # 설정 마운트
15-6. 알림 테스트
# ① 전체 서비스 시작
docker compose up -d
# ② Prometheus UI 확인 — 브라우저에서 localhost:9090 접속
# Status > Targets → express-app 이 "UP" 상태인지 확인
# ③ 일부러 앱 컨테이너 중지 — 장애 시뮬레이션
docker stop my-infra-lab-app-1
# ④ 30초 대기 후 Prometheus > Alerts 확인
# AppDown 알림이 "FIRING" 상태로 바뀌어 있다
# ⑤ Alertmanager 로그에서 알림 확인
docker logs my-infra-lab-alertmanager-1
# 출력 예시: msg="Dispatching alert" alert=AppDown
# ⑥ 앱 복구
# ⑦ 잠시 후 알림이 "RESOLVED" 상태로 바뀐다
핵심 체감: 이것이 Alerting이다. 실무에서는 이 알림이 Slack 채널이나 PagerDuty로 전송되어 온콜 담당자의 핸드폰에 푸시 알림이 간다.
체크리스트
- 이미지가 바뀌면 자동으로 배포된다 (Watchtower)
- 앱이 죽으면 Prometheus가 감지하고 Alertmanager가 알림을 발생시킨다
- CD와 Alerting의 역할을 체감했다
다음 단계 → 09-access-and-backup.md
Comments
// admin login