infra
Platform

모듈 맵

[Network] 서비스 안정성을 지키는 메트릭, 로그, 알림 구축 전략

0 / 35 완료

펼치기
0 / 35 완료0%

Networking · 30 / 35

[Network] 서비스 안정성을 지키는 메트릭, 로그, 알림 구축 전략

CloudWatch, Datadog, Prometheus의 모니터링 철학을 이해하고, iftop/nload로 실시간 트래픽을 진단하는 실무 패턴을 학습합니다.

🚨INCIDENT ALERT
HIGH

장애가 끝난 뒤 회고에서 "언제부터 느려졌는지" 아무도 답하지 못했습니다. 서버는 살아 있었지만 트래픽 급증, 에러율, 대역폭 사용량이 어디에도 남아 있지 않았습니다.

모니터링은 장애 후 보고서가 아니라 장애 중 판단 근거입니다. 지표와 로그가 있어야 감이 아니라 증거로 대응할 수 있습니다.

온프레미스 시절에는 Nagios나 Zabbix가 서버 한 대씩을 감시하는 구조였습니다. 그런데 서비스가 컨테이너와 오토스케일링으로 전환되면서 "서버 한 대"라는 단위 자체가 흔들리기 시작했습니다. 인스턴스가 수십 개에서 수백 개로 늘어나고 줄어드는 환경에서, 개별 서버를 직접 SSH로 들어가 확인하는 방법은 더 이상 통하지 않습니다. 지난해 블랙프라이데이에 트래픽이 몰렸을 때, 팀이 "어느 서버가 이상한지"를 파악하는 데만 20분을 쓴 회사가 있었습니다. 모니터링 시스템이 없어서가 아니었습니다. 서버별 CPU 그래프는 있었지만, 그 숫자가 실제 사용자 경험과 연결되는 관점이 없었습니다. 이 모듈은 클라우드 환경에서 모니터링을 "서버 감시"가 아닌 "서비스 가시성"으로 전환하는 사고방식을 다룹니다.

학습 목표

  • CloudWatch, Datadog, Prometheus의 수집 방식과 적합한 사용 상황을 구분할 수 있다
  • 메트릭, 로그, 트레이스의 차이와 각각이 답하는 질문을 설명할 수 있다
  • iftop, nload, vnstat으로 실시간 네트워크 트래픽을 진단할 수 있다
  • Prometheus PromQL 기본 쿼리를 작성할 수 있다
  • CloudWatch Logs Insights로 에러 패턴을 빠르게 찾을 수 있다
이번 챕터에서 배울 것
  • 1Observability 3요소 — 메트릭, 로그, 트레이스
  • 2CloudWatch — AWS 네이티브 모니터링
  • 3Datadog — SaaS 통합 모니터링
  • 4Prometheus + Grafana — 오픈소스 스택
  • 5실시간 트래픽 진단 — iftop, nload, vnstat
실습 환경 준비
💡개념

Observability 3요소 — 메트릭, 로그, 트레이스

새벽 2시에 알림이 울립니다. "API 응답 시간 초과". 서버는 살아 있고 에러 로그는 없습니다. CPU 그래프를 봐도 정상입니다. 어디가 느린지 어디서부터 파야 하는지 막막합니다. 이때 메트릭, 로그, 트레이스가 각각 다른 질문에 답하면서 범위를 좁혀줍니다. 세 가지 신호가 어떻게 서로 다른 역할을 하고 어떤 순서로 활용하는지 이해하면, 장애 대응에서 감이 아닌 증거로 판단할 수 있습니다.

Observability 3요소 — 메트릭, 로그, 트레이스

메트릭 (Metrics): "지금 어떤 상태인가?"

숫자로 표현되는 시계열 데이터입니다. CPU 사용률, 초당 요청 수, 응답 시간 P99 같은 값입니다. 집계가 가능하고 알림을 걸기 쉽습니다.

http_requests_total{method="GET", status="200"} 1234567
http_request_duration_seconds{quantile="0.99"} 0.342

로그 (Logs): "무슨 일이 있었나?"

이벤트의 텍스트 기록입니다. "언제 어떤 요청이 들어와서 어떻게 처리됐는지"를 담습니다. 세부 문맥이 있지만 양이 많아 검색과 집계가 필요합니다.

2026-04-26T14:32:01Z ERROR user_id=4892 action=checkout
  message="payment gateway timeout after 30s"
  order_id=8847291 amount=49800

트레이스 (Traces): "어디서 느려졌나?"

분산 시스템에서 요청 하나가 여러 서비스를 거칠 때, 전체 경로와 각 구간 소요 시간을 기록합니다. "API는 200ms인데 그 중 DB 쿼리가 180ms"라는 사실을 보여줍니다.

Request → API Gateway (5ms)
  → Auth Service (8ms)
  → Product Service (187ms) ← 여기가 느림
      → DB Query: SELECT * FROM products (175ms) ← 병목

실무에서의 사용 패턴:

  1. 알림 발생 (메트릭): "API P99 응답시간이 2초 초과"
  2. 로그로 원인 파악: "payment-service에서 타임아웃 에러 급증"
  3. 트레이스로 병목 위치: "외부 PG 호출이 1.8초 걸림"

세 가지가 연결될 때 장애 대응 시간이 극적으로 줄어듭니다.

💡개념

CloudWatch — AWS 네이티브 모니터링

EC2를 쓰기 시작했는데 메모리가 얼마나 쓰이는지 CloudWatch에서 보이지 않습니다. CPU와 네트워크는 보이는데 메모리는 없습니다. 알고 보니 CloudWatch가 자동 수집하는 항목과 Agent를 따로 설치해야 하는 항목이 나뉩니다. 이 차이를 모르면 장애 순간에 정작 필요한 지표가 비어 있는 상황이 됩니다. CloudWatch의 구조와 에이전트 역할을 이해해야 AWS 환경에서 모니터링 공백 없이 운영할 수 있습니다.

AWS 인프라를 쓴다면 CloudWatch가 기본 출발점입니다. EC2, RDS, ALB, Lambda 등 AWS 서비스에서 자동으로 메트릭을 수집하고, 로그를 중앙 집중화하며, 알림을 설정할 수 있습니다.

핵심 기능:

CloudWatch
├── Metrics — AWS 서비스 + 커스텀 메트릭
├── Logs — 로그 수집, 저장, 검색 (Logs Insights)
├── Alarms — 임계값 기반 알림 (SNS → Slack/PagerDuty)
└── Dashboards — 메트릭 시각화

CloudWatch Agent 설치 (EC2):

로컬 터미널
# 실습 디렉토리 준비
mkdir -p /tmp/networking/part6/exam_30 && cd /tmp/networking/part6/exam_30

# CloudWatch Agent 설치
wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb
sudo dpkg -i amazon-cloudwatch-agent.deb

# 설정 파일 생성
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard

# 메모리/디스크 메트릭은 기본 수집 안됨 — agent 필요
# 설정 예시 (/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json)
{
  "metrics": {
    "namespace": "MyApp/System",
    "metrics_collected": {
      "mem": { "measurement": ["mem_used_percent"] },
      "disk": { "measurement": ["disk_used_percent"],
                "resources": ["/", "/data"] }
    }
  },
  "logs": {
    "logs_collected": {
      "files": {
        "collect_list": [{
          "file_path": "/var/log/myapp/app.log",
          "log_group_name": "/myapp/application",
          "log_stream_name": "{instance_id}"
        }]
      }
    }
  }
}
🔍실행 후 확인할 것
  • 핵심 출력명령 결과에서 성공/실패를 가르는 값을 먼저 확인합니다
  • 대상 식별IP, 포트, 인터페이스, 프로세스명처럼 다음 조치를 결정하는 필드를 봅니다
  • 다음 분기결과가 기대와 다르면 어느 계층을 이어서 점검할지 정합니다

CloudWatch Logs Insights — 로그 빠른 분석:

# 최근 1시간 HTTP 5xx 에러가 가장 많은 엔드포인트
fields @timestamp, path, status, duration
| filter status >= 500
| stats count(*) as errors, avg(duration) as avg_ms by path
| sort errors desc
| limit 10

# 특정 사용자의 최근 요청 흐름
fields @timestamp, user_id, action, status
| filter user_id = "4892"
| sort @timestamp desc
| limit 50

# 에러율이 급증한 시간대
fields @timestamp, status
| filter status >= 500
| stats count(*) as errors by bin(5m)
| sort @timestamp asc

알람 설정 (AWS CLI):

로컬 터미널
# P99 응답시간 1초 초과 시 알림
aws cloudwatch put-metric-alarm \
  --alarm-name "API-HighLatency" \
  --metric-name "TargetResponseTime" \
  --namespace "AWS/ApplicationELB" \
  --statistic "p99" \
  --period 60 \
  --threshold 1.0 \
  --comparison-operator "GreaterThanThreshold" \
  --evaluation-periods 3 \
  --alarm-actions "arn:aws:sns:ap-northeast-2:123456:alerts"

EC2 메모리/디스크는 자동 수집 안 됩니다. AWS가 하이퍼바이저 수준에서 볼 수 없는 데이터라 CloudWatch Agent를 별도 설치해야 합니다. 이걸 모르고 "메모리가 터졌는데 CloudWatch에 안 보여요"라고 하는 팀이 많습니다.

💡개념

Prometheus + Grafana — 오픈소스 모니터링 스택

AWS 밖에서도 쓰고 싶거나, 메트릭을 직접 컨트롤하고 싶다면 Prometheus + Grafana 조합이 사실상 표준입니다. 쿠버네티스 환경에서 특히 강점이 있습니다.

아키텍처:

애플리케이션 서버들
├── /metrics 엔드포인트 노출 (Prometheus 형식)
│
Prometheus Server (15초마다 pull)
├── 시계열 데이터 저장 (TSDB)
├── Alert Rules 평가
└── Alertmanager → Slack/PagerDuty
│
Grafana
└── Prometheus 쿼리 → 대시보드 시각화

Docker Compose로 빠른 시작:

YAML
# docker-compose.yml
version: '3'
services:
  prometheus:
    image: prom/prometheus:latest
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin123
YAML
# prometheus.yml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'node-exporter'
    static_configs:
      - targets: ['node-exporter:9100']

  - job_name: 'myapp'
    static_configs:
      - targets: ['myapp:8080']  # /metrics 엔드포인트
Docker
# Node Exporter 설치 (서버 메트릭 수집)
docker run -d \
  --name node-exporter \
  --pid="host" \
  -v "/:/host:ro,rslave" \
  prom/node-exporter \
  --path.rootfs=/host

PromQL 핵심 쿼리 패턴:

# 초당 요청 수 (5분 평균)
rate(http_requests_total[5m])

# 에러율 (%)
rate(http_requests_total{status=~"5.."}[5m])
/ rate(http_requests_total[5m]) * 100

# P99 응답시간
histogram_quantile(0.99,
  rate(http_request_duration_seconds_bucket[5m])
)

# 서비스별 초당 에러 수 비교
sum by (service) (
  rate(http_requests_total{status=~"5.."}[5m])
)

# 메모리 사용률 (Node Exporter)
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100

알림 규칙 예시:

YAML
# alert.rules.yml
groups:
  - name: api_alerts
    rules:
      - alert: HighErrorRate
        expr: |
          rate(http_requests_total{status=~"5.."}[5m])
          / rate(http_requests_total[5m]) > 0.05
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "에러율 5% 초과: {{ $labels.service }}"
          description: "현재 에러율: {{ $value | humanizePercentage }}"

pull vs push 방식의 실무 함의: Prometheus는 타깃 서버의 /metrics 엔드포인트에 접속해서 데이터를 가져갑니다(pull). 서버가 방화벽으로 인바운드가 모두 막힌 환경이라면 Prometheus가 접속할 수 없습니다. 이 경우 Pushgateway를 중간에 두거나, 아웃바운드만 되는 Datadog agent 방식을 택해야 합니다.

실습: 실시간 네트워크 트래픽 진단

서버에서 "트래픽이 갑자기 늘었다"는 알림을 받았을 때, 무슨 트래픽인지 빠르게 파악해야 합니다.

iftop — IP별 실시간 대역폭

로컬 터미널
# 설치
sudo apt install iftop -y

# eth0 인터페이스 모니터링
sudo iftop -i eth0

# IP 대신 호스트명 표시 (-n 끄면 DNS 역조회)
sudo iftop -i eth0

# 특정 포트만 필터
sudo iftop -i eth0 -f "port 443"

# 실행 중 키보드 단축키:
# n — IP/호스트명 전환
# s — 출발지 집계
# d — 목적지 집계
# t — 전송/수신 토글
# p — 포트 표시 토글
# q — 종료

iftop 화면 읽기:

                   12.5Kb          25.0Kb          37.5Kb      50.0Kb
└──────────────────────────────────────────────────────────────────────
server-01.example.com              =>  52.95.121.30     3.42Kb  2.87Kb  2.45Kb
                                   <=                   1.23Kb  1.01Kb   987b
server-01.example.com              =>  10.0.0.15       15.3Kb  12.1Kb   8.9Kb
                                   <=                    890b   756b    623b
──────────────────────────────────────────────────────────────────────
TX:             cum:   45.2KB   peak:   22.4Kb      rates:   18.7Kb  14.9Kb  11.3Kb
RX:                    12.1KB             8.9Kb               2.1Kb   1.7Kb   1.3Kb
TOTAL:                 57.3KB            31.3Kb              20.8Kb  16.6Kb  12.6Kb

=> 아웃바운드, <= 인바운드. 오른쪽 세 숫자는 2초/10초/40초 평균입니다.

nload — 전체 대역폭 현황

로컬 터미널
# 설치 후 실행
sudo apt install nload -y
nload eth0

# 여러 인터페이스 동시 확인 (화살표 키로 전환)
nload

# 단위 변경 (기본 kbit/s)
nload -u h  # human-readable

vnstat — 누적 트래픽 통계

위험 명령어

이 명령은 실행 중인 서비스 상태를 바꿔 순간적인 중단이나 설정 반영 실패를 만들 수 있습니다. 운영 트래픽 영향과 재시작 후 확인 명령을 먼저 준비하세요.

로컬 터미널
# 설치 및 초기화
sudo apt install vnstat -y
sudo systemctl enable --now vnstat

# 오늘/이번 달 사용량
vnstat -d  # 일별
vnstat -m  # 월별
vnstat -h  # 시간별
vnstat -l  # 라이브 (nload와 유사)

# 특정 인터페이스
vnstat -i eth0 -m

이상 트래픽 추적 워크플로우

로컬 터미널
# 1. 어떤 IP가 많은 트래픽을 쓰는지 확인 (iftop)
sudo iftop -i eth0

# 2. 의심 IP가 보이면, 어느 프로세스가 연결을 만들었는지 확인
ss -tnp | grep "52.95.121.30"
# 또는
netstat -tnp | grep "52.95.121.30"
# 출력: tcp  ESTABLISHED  10.0.0.5:52341  52.95.121.30:443  users:(("node",pid=1234,fd=12))

# 3. PID로 프로세스 확인
ps aux | grep 1234
ls -la /proc/1234/exe  # 실행 파일 경로

# 4. 해당 프로세스가 열고 있는 모든 연결
ss -tnp | grep "pid=1234"

상황: Prometheus가 타깃 서버의 /metrics를 수집하지 못합니다.

원인 1 — 타깃 서버에서 exporter가 실행 중이지 않음:

위험 명령어

이 명령은 실행 중인 서비스 상태를 바꿔 순간적인 중단이나 설정 반영 실패를 만들 수 있습니다. 운영 트래픽 영향과 재시작 후 확인 명령을 먼저 준비하세요.

로컬 터미널
# 타깃 서버에서 확인
ss -tlnp | grep 9100  # node-exporter 포트
# 아무것도 나오지 않으면 exporter가 꺼진 것

# 재시작
sudo systemctl start node-exporter
sudo systemctl status node-exporter

원인 2 — 방화벽이 9100 포트 차단:

위험 명령어

이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.

로컬 또는 서버
# Prometheus 서버에서 직접 테스트
curl http://TARGET_IP:9100/metrics

# 타깃 서버 방화벽 확인
sudo ufw status
sudo firewall-cmd --list-all

# 9100 포트 열기 (Ubuntu)
sudo ufw allow from PROMETHEUS_IP to any port 9100

원인 3 — prometheus.yml의 타깃 주소 오타:

로컬 터미널
# Prometheus 웹 UI → Status → Targets 에서 실제 연결 시도 주소 확인
# http://localhost:9090/targets

# 설정 파일 확인
cat prometheus.yml | grep -A5 "static_configs"

상황: CloudWatch 콘솔에서 메트릭을 보려 하는데 "No data" 상태입니다.

원인 1 — EC2 메모리/디스크 메트릭 (CloudWatch Agent 미설치):

위험 명령어

이 명령은 실행 중인 서비스 상태를 바꿔 순간적인 중단이나 설정 반영 실패를 만들 수 있습니다. 운영 트래픽 영향과 재시작 후 확인 명령을 먼저 준비하세요.

서버 터미널
# AWS 기본 제공 메트릭은 CPU, 네트워크, 디스크 I/O만 포함
# 메모리, 디스크 사용률은 Agent 필요

# Agent 상태 확인
sudo systemctl status amazon-cloudwatch-agent

# Agent 시작
sudo systemctl start amazon-cloudwatch-agent

# 로그 확인
sudo tail -f /opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log

원인 2 — IAM 권한 부족:

로컬 터미널
# EC2 인스턴스 역할에 CloudWatchAgentServerPolicy 있는지 확인
aws iam list-attached-role-policies \
  --role-name YOUR_EC2_ROLE_NAME

# 없으면 추가
aws iam attach-role-policy \
  --role-name YOUR_EC2_ROLE_NAME \
  --policy-arn arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy

원인 3 — Namespace/MetricName 불일치:

로컬 터미널
# Agent 설정에서 namespace 확인
grep "namespace" /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json

# CLI로 실제 수집된 메트릭 목록 확인
aws cloudwatch list-metrics --namespace "MyApp/System"
💼
실무 맥락
현업 패턴

시나리오: 서비스 성능 저하 대응 — 모니터링 3요소 활용

새벽 2시, PagerDuty 알림이 울렸습니다. Prometheus 알림: "결제 API P99 응답시간 4초 초과 (정상: 200ms)".

1단계 — 메트릭으로 범위 파악 (2분 이내): Grafana 대시보드를 열고 결제 서비스, DB, 외부 PG(Payment Gateway) 메트릭을 동시에 확인합니다. histogram_quantile(0.99, rate(http_request_duration_seconds_bucket{service="payment"}[5m])) 그래프에서 03:47부터 급증한 것을 확인. DB 메트릭은 정상, 외부 PG 호출 시간이 3.8초로 폭등.

2단계 — 로그로 확인 (5분 이내): CloudWatch Logs Insights:

fields @timestamp, pg_response_time, error_code
| filter service = "payment" and pg_response_time > 1000
| sort @timestamp desc
| limit 100

결과: 특정 카드사 API가 03:47부터 타임아웃 반환 중. error_code=TIMEOUT 패턴.

3단계 — 조치:

  • 해당 카드사를 일시 비활성화 (서킷브레이커 발동)
  • 담당 팀 에스컬레이션
  • 30분 후 카드사 측 장애 복구 확인 후 복원

모니터링 시스템이 없었다면 사용자 신고 접수 → 원인 추적 → 조치까지 최소 30-40분 걸렸을 상황을 6분 만에 처리했습니다.


실무 모니터링 스택 선택 기준:

상황권장
AWS 인프라 중심, 빠른 시작CloudWatch + CloudWatch Agent
멀티클라우드 or 온프레미스 포함Datadog (agent push)
쿠버네티스 환경, 자체 구축Prometheus + Grafana
소규모, 비용 최소화Prometheus + Grafana (오픈소스)
분산 트레이싱 필요Jaeger or AWS X-Ray 추가

대부분의 팀은 CloudWatch(기본 인프라) + Prometheus/Grafana(앱 메트릭) 조합을 사용합니다. Datadog은 All-in-one이지만 비용이 상당합니다.

지식 확인

퀴즈 — 5문제

Q1

서비스 배포 직후 API 응답 시간이 갑자기 늘어났습니다. CloudWatch에서 가장 먼저 확인해야 할 메트릭 조합으로 적절한 것은?

Q2

Prometheus의 pull 방식과 Datadog의 agent push 방식의 차이가 실무에서 의미 있는 상황은?

Q3

iftop 실행 중 특정 외부 IP와의 트래픽이 예상보다 10배 많게 표시됩니다. 다음 중 가장 적절한 다음 단계는?

Q4

Prometheus에서 rate(http_requests_total[5m])와 irate(http_requests_total[5m])의 실무적 차이는?

Q5

CloudWatch Logs Insights에서 최근 1시간 동안 HTTP 5xx 에러가 가장 많이 발생한 엔드포인트를 찾으려 합니다. 올바른 쿼리 패턴은?

0 / 5 답변

🧪 실습으로 확인하기

포트는 열렸다는데 왜 안 되지? — ss/netstat/telnet으로 TCP 진단

초급

"포트 8080 열었는데요?"와 "왜 안 돼요?" 사이의 간극을 메우는 실습. ss로 바인딩 상태를 확인하고, telnet/nc으로 원격 연결을 테스트하고, iptables 방화벽을 진단하고, 바인딩 주소(0.0.0.0 vs 127.0.0.1)까지 수정하는 4단계 TCP 포트 진단 플로우를 완성한다.

35📋 4단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요

networking고급 · 45
[Network] 통신 장애를 실시간으로 탐지하는 쉘 스크립트 작성
Networking 트랙 계속
docker입문 · 30
[Docker] 백엔드 개발자에게 Docker와 컨테이너 가상화가 필수인 이유
Docker 트랙 시작점