Skip to content

로깅 개요

마지막 업데이트: 2026년 2월 20일

Kubernetes 환경에서 효과적인 로깅은 시스템의 가시성, 문제 해결, 보안 감사에 필수적입니다. 이 문서에서는 로깅의 기본 개념, 로그 수집 파이프라인 아키텍처, 그리고 EKS 환경에서의 로깅 전략에 대해 설명합니다.

목차

  1. 로깅 기본 개념
  2. 로그 수집 파이프라인 아키텍처
  3. 로그 저장소 선택 기준
  4. EKS 로깅 전략
  5. 솔루션 비교

로깅 기본 개념

구조화된 로깅 (Structured Logging)

구조화된 로깅은 로그 메시지를 일관된 형식으로 출력하여 파싱과 분석을 용이하게 합니다. 비구조화된 텍스트 로그와 달리, 구조화된 로그는 필드-값 쌍으로 구성되어 검색과 필터링이 훨씬 효율적입니다.

비구조화 로그 vs 구조화 로그

plaintext
# 비구조화 로그 (파싱이 어려움)
2025-02-15 10:23:45 ERROR Failed to connect to database: connection timeout after 30s

# 구조화 로그 (JSON 형식)
{
  "timestamp": "2025-02-15T10:23:45.123Z",
  "level": "ERROR",
  "message": "Failed to connect to database",
  "error": "connection timeout",
  "timeout_seconds": 30,
  "service": "user-api",
  "pod": "user-api-7d4f8b9c6-x2k9m",
  "namespace": "production",
  "trace_id": "abc123def456"
}

구조화된 로깅의 장점

장점설명
검색 효율성특정 필드로 빠른 필터링 가능
일관성모든 서비스에서 동일한 형식 사용
상관 관계 분석trace_id, request_id 등으로 요청 추적
자동화파싱 없이 즉시 분석 도구에서 사용 가능
알림 설정특정 필드 값 기반 알림 규칙 생성 용이

로그 레벨 (Log Levels)

로그 레벨은 메시지의 중요도와 심각도를 나타냅니다. 적절한 로그 레벨 사용은 효과적인 문제 해결과 노이즈 감소에 중요합니다.

레벨숫자용도예시
TRACE0가장 상세한 디버깅 정보함수 진입/종료, 변수 값
DEBUG1개발 중 디버깅 정보SQL 쿼리, 요청 파라미터
INFO2일반적인 운영 정보서비스 시작, 요청 처리 완료
WARN3잠재적 문제 상황재시도 발생, 성능 저하
ERROR4오류 발생 (복구 가능)API 호출 실패, 유효성 검사 실패
FATAL5치명적 오류 (복구 불가)서비스 시작 실패, 필수 의존성 없음

환경별 권장 로그 레벨

yaml
# 개발 환경
LOG_LEVEL: DEBUG

# 스테이징 환경
LOG_LEVEL: INFO

# 프로덕션 환경
LOG_LEVEL: INFO  # 또는 WARN (높은 트래픽 시)

JSON 로그 형식

Kubernetes 환경에서 JSON 형식은 사실상 표준입니다. 대부분의 로그 수집기와 분석 도구가 JSON을 기본 지원합니다.

권장 JSON 필드

json
{
  "timestamp": "2025-02-15T10:23:45.123Z",
  "level": "INFO",
  "logger": "com.example.UserService",
  "message": "User login successful",
  "context": {
    "user_id": "user-12345",
    "session_id": "sess-abc123",
    "ip_address": "10.0.1.50"
  },
  "kubernetes": {
    "namespace": "production",
    "pod": "user-api-7d4f8b9c6-x2k9m",
    "container": "user-api",
    "node": "ip-10-0-1-100.ec2.internal"
  },
  "trace": {
    "trace_id": "abc123def456",
    "span_id": "789ghi",
    "parent_span_id": "456def"
  }
}

주요 필드 설명

필드 그룹필드설명
기본timestampISO 8601 형식 타임스탬프
level로그 레벨
message사람이 읽을 수 있는 메시지
컨텍스트context.*비즈니스 로직 관련 정보
Kuberneteskubernetes.*파드, 네임스페이스 등 K8s 메타데이터
추적trace.*분산 추적 ID (OpenTelemetry 연동)

로그 수집 파이프라인 아키텍처

전체 아키텍처 개요

계층별 역할

1. 수집 계층 (Collection Layer)

로그 소스에서 원시 로그를 수집하는 역할을 담당합니다.

방식장점단점적합한 경우
DaemonSet리소스 효율적, 중앙 관리노드당 하나만 실행대부분의 표준 워크로드
Sidecar애플리케이션별 격리, 커스텀 처리리소스 오버헤드특수 로그 형식, 멀티테넌트
Direct Push실시간성, 유연한 전송애플리케이션 수정 필요고성능 요구사항

2. 처리 계층 (Processing Layer)

수집된 로그를 정규화하고 메타데이터를 추가합니다.

yaml
# FluentBit 처리 파이프라인 예시
[FILTER]
    Name         kubernetes
    Match        kube.*
    Kube_URL     https://kubernetes.default.svc:443
    Merge_Log    On
    K8S-Logging.Parser  On

[FILTER]
    Name         modify
    Match        *
    Add          cluster_name eks-production
    Add          environment production

[FILTER]
    Name         grep
    Match        *
    Exclude      log HealthCheck

3. 저장 계층 (Storage Layer)

처리된 로그를 저장하고 인덱싱합니다. 각 솔루션의 특성에 따라 저장 방식이 다릅니다.

4. 분석 계층 (Analysis Layer)

저장된 로그를 검색하고 시각화합니다.


로그 저장소 선택 기준

주요 고려 사항

1. 비용

월간 로그 볼륨: 1TB 기준 예상 비용 (2025년 기준)

솔루션저장 비용/GB쿼리 비용
Loki (S3)$0.023 (S3)무료
OpenSearch$0.10-0.15무료
CloudWatch$0.50 (수집)$0.005/GB 스캔
ClickHouse$0.023 (S3)무료

2. 쿼리 성능

솔루션실시간 쿼리집계 쿼리전문 검색대시보드
Loki우수양호제한적Grafana
OpenSearch우수우수우수OpenSearch Dashboards
CloudWatch양호양호양호CloudWatch 콘솔
ClickHouse우수우수양호Grafana

3. 보존 기간

yaml
# 권장 보존 정책
regulatory_compliance:
  financial: 7년
  healthcare: 6년
  general: 1년

operational:
  hot_storage: 7-14일    # 빠른 쿼리
  warm_storage: 30-90일  # 조사용
  cold_storage: 1년+     # 규정 준수

4. 운영 복잡성

솔루션설치 복잡성운영 부담확장성
Loki낮음낮음높음
OpenSearch중간높음중간
CloudWatch매우 낮음매우 낮음높음
ClickHouse높음중간높음

EKS 로깅 전략

로그 수집 패턴

1. stdout/stderr 패턴 (권장)

컨테이너의 표준 출력/에러를 통한 로깅은 Kubernetes의 기본 패턴입니다.

yaml
apiVersion: v1
kind: Pod
metadata:
  name: app-pod
spec:
  containers:
  - name: app
    image: myapp:1.0
    # 애플리케이션은 stdout/stderr로 로그 출력
    # kubelet이 /var/log/containers/에 파일로 저장
    # DaemonSet 에이전트가 수집

장점:

  • Kubernetes 네이티브 방식
  • 로그 로테이션 자동 관리 (/var/log/containers/)
  • kubectl logs 명령어 사용 가능
  • 별도 볼륨 마운트 불필요

로그 파일 위치:

bash
# 실제 로그 파일
/var/log/containers/<pod-name>_<namespace>_<container-name>-<container-id>.log

# 심볼릭 링크
/var/log/pods/<namespace>_<pod-name>_<pod-uid>/<container-name>/0.log

2. Sidecar 패턴

파일 기반 로그나 특수 처리가 필요한 경우 사용합니다.

yaml
apiVersion: v1
kind: Pod
metadata:
  name: app-with-sidecar
spec:
  containers:
  - name: app
    image: legacy-app:1.0
    volumeMounts:
    - name: log-volume
      mountPath: /var/log/app

  - name: log-collector
    image: fluent/fluent-bit:latest
    volumeMounts:
    - name: log-volume
      mountPath: /var/log/app
      readOnly: true
    - name: fluent-bit-config
      mountPath: /fluent-bit/etc/

  volumes:
  - name: log-volume
    emptyDir: {}
  - name: fluent-bit-config
    configMap:
      name: fluent-bit-sidecar-config

사용 사례:

  • 레거시 애플리케이션 (파일 로깅만 지원)
  • 멀티테넌트 환경에서 로그 격리
  • 애플리케이션별 특수 파싱 필요
  • 높은 보안 요구사항

3. DaemonSet 패턴 (가장 일반적)

노드당 하나의 에이전트가 모든 컨테이너 로그를 수집합니다.

yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluent-bit
  namespace: logging
spec:
  selector:
    matchLabels:
      app: fluent-bit
  template:
    metadata:
      labels:
        app: fluent-bit
    spec:
      serviceAccountName: fluent-bit
      tolerations:
      - operator: Exists  # 모든 노드에 배포
      containers:
      - name: fluent-bit
        image: public.ecr.aws/aws-observability/aws-for-fluent-bit:latest
        volumeMounts:
        - name: varlog
          mountPath: /var/log
          readOnly: true
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
        resources:
          limits:
            memory: 200Mi
            cpu: 200m
          requests:
            memory: 100Mi
            cpu: 100m
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers

EKS 컨트롤 플레인 로깅

EKS 컨트롤 플레인 로그는 CloudWatch Logs로 전송됩니다.

bash
# AWS CLI로 컨트롤 플레인 로깅 활성화
aws eks update-cluster-config \
  --name my-cluster \
  --logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}'
로그 유형설명권장 여부
apiAPI 서버 로그필수
auditKubernetes 감사 로그필수 (보안)
authenticatorIAM 인증 로그권장
controllerManager컨트롤러 매니저 로그선택
scheduler스케줄러 로그선택

Container Insights 로깅

yaml
# CloudWatch Agent ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: cloudwatch-agent-config
  namespace: amazon-cloudwatch
data:
  cwagentconfig.json: |
    {
      "logs": {
        "metrics_collected": {
          "kubernetes": {
            "cluster_name": "my-cluster",
            "metrics_collection_interval": 60
          }
        },
        "force_flush_interval": 5
      }
    }

솔루션 비교

기능 비교표

기능LokiOpenSearchCloudWatchClickHouse
설치 복잡성낮음중간없음 (관리형)높음
쿼리 언어LogQLLucene/DQLInsights QLSQL
전문 검색제한적우수양호양호
스키마스키마리스스키마리스스키마리스스키마 정의
압축률높음중간N/A매우 높음
실시간 테일링지원지원제한적지원
알림Grafana내장내장Grafana
멀티테넌시지원지원지원지원
S3 백엔드네이티브스냅샷만N/A네이티브

사용 사례별 권장 솔루션

사용 사례권장 솔루션
비용 최적화가 최우선Loki + S3
전문 검색 및 분석 필요OpenSearch
AWS 네이티브 환경, 간편한 운영CloudWatch Logs
대규모 분석 워크로드, SQL 선호ClickHouse
기존 Grafana 스택 보유Loki
규정 준수 요구사항OpenSearch/CloudWatch
스타트업/소규모 팀Loki 또는 CloudWatch
대기업/복잡한 분석 요구OpenSearch

비용 시뮬레이션 (월간 100GB 로그 기준)

솔루션별 예상 월간 비용:

Loki (S3 Simple Scalable):
  ├─ S3 저장: $2.30
  ├─ S3 요청: $0.50
  ├─ EC2 (3x m5.large): $180
  └─ 총계: ~$183

OpenSearch (3x m5.large):
  ├─ 인스턴스: $300
  ├─ EBS 스토리지: $15
  └─ 총계: ~$315

CloudWatch Logs:
  ├─ 수집: $50
  ├─ 저장: $3
  ├─ 쿼리 (추정): $10
  └─ 총계: ~$63

ClickHouse (자체 호스팅):
  ├─ EC2 (3x m5.large): $180
  ├─ S3 저장: $2.30
  └─ 총계: ~$183

참고: 실제 비용은 쿼리 패턴, 보존 기간, 리전에 따라 크게 달라질 수 있습니다.

의사결정 플로우차트


다음 단계

각 로그 저장소에 대한 자세한 내용은 다음 문서를 참조하세요:


퀴즈

이 장에서 배운 내용을 테스트하려면 로깅 개요 퀴즈를 풀어보세요.