Kubernetes Log에 대하여 알아보자

쿠버네티스 환경에서 로그는 컨테이너 런타임에 의해 생성되고 kubelet에 의해 관리됩니다. 이 글에서는 쿠버네티스의 로그 생성부터 관리, 그리고 수집까지의 전체 과정을 살펴보겠습니다.

쿠버네티스의 로그 생성과 관리

컨테이너 런타임의 로그 생성

쿠버네티스는 다양한 컨테이너 런타임(Docker, containerd, CRI-O 등)을 지원합니다. 이 런타임들은 컨테이너의 표준 출력(stdout)과 표준 에러(stderr)를 로그로 처리합니다.

 1┌────────────────────────────────────────────────────────────────────────────┐
 2│                              Container Runtime                             │
 3│                                                                            │
 4│  ┌──────────────┐   ┌──────────────┐   ┌──────────────┐   ┌──────────────┐ │
 5│  │              │   │              │   │              │   │              │ │
 6│  │  Container   │   │  Log Driver  │   │   Log File   │   │  Symbolic    │ │
 7│  │              │   │              │   │              │   │    Link      │ │
 8│  │ - stdout     │──▶│ - json-file  │──▶│ /var/log/    │──▶│ /var/log/    │ │
 9│  │ - stderr     │   │ - journald   │   │ pods/        │   │ containers/  │ │
10│  │              │   │ - syslog     │   │              │   │              │ │
11│  └──────────────┘   └──────────────┘   └──────────────┘   └──────────────┘ │
12│                                                                            │
13└────────────────────────────────────────────────────────────────────────────┘

로그 생성 과정

  1. 애플리케이션 출력

    • 컨테이너 내부의 애플리케이션이 stdout/stderr로 출력
    • 모든 출력은 컨테이너 런타임에 의해 캡처됨
  2. 로그 드라이버 처리

    • 컨테이너 런타임의 로그 드라이버가 출력을 처리
    • 기본적으로 JSON 형식으로 변환하여 저장
  3. 로그 파일 생성과 심볼릭 링크

    • containerd 환경
      • 원본 로그 파일: /var/log/pods/default_mypod_1234567890abcdef/mycontainer/0.log (containerd가 생성·관리)
      • 심볼릭 링크: /var/log/containers/mypod_default_abcdef1234567890.log (kubelet이 생성·관리)
      • 예시:
        1# 실제 로그 파일 (containerd)
        2/var/log/pods/default_mypod_1234567890abcdef/mycontainer/0.log
        3# Kubelet이 생성한 심볼릭 링크
        4/var/log/containers/mypod_default_abcdef1234567890.log -> /var/log/pods/default_mypod_1234567890abcdef/mycontainer/0.log
        
    • Docker 환경
      • 원본 로그 파일: /var/lib/docker/containers/abcdef1234567890/abcdef1234567890-json.log
      • 심볼릭 링크: /var/log/containers/mypod_default_abcdef1234567890.log (kubelet이 생성)
      • 예시:
        1# 실제 로그 파일 (Docker)
        2/var/lib/docker/containers/abcdef1234567890/abcdef1234567890-json.log
        3# Kubelet이 생성한 심볼릭 링크
        4/var/log/containers/mypod_default_abcdef1234567890.log -> /var/lib/docker/containers/abcdef1234567890/abcdef1234567890-json.log
        
  4. 로그 파일 관리

    • 로그 로테이션 (컨테이너 런타임)
      • 컨테이너 런타임이 실제 로그 파일의 크기와 보관 기간 관리
      • 로그 파일이 설정된 크기를 초과하면 로테이션 수행
      • 로테이션된 파일은 같은 디렉토리에 저장 (예: abc123-json.log.1, abc123-json.log.2 등)
    • 심볼릭 링크 관리 (Kubelet)
      • 파드가 생성될 때 /var/log/containers/ 디렉토리에 심볼릭 링크 생성
      • 컨테이너가 재시작될 때 심볼릭 링크 업데이트
      • 파드가 삭제될 때 심볼릭 링크 정리

Kubelet의 로그 관리

Kubelet은 컨테이너 런타임이 생성한 로그 파일의 경로와 심볼릭 링크를 관리합니다. 실제 로그 파일의 생성, 쓰기, 로테이션 등은 컨테이너 런타임(containerd)이 담당합니다.

Kubelet의 로그 관리 역할

Kubelet은 다음과 같은 로그 관리 역할을 수행합니다:

  1. 로그 설정 전달

    • 로그 로테이션 설정값을 컨테이너 런타임에 전달
    • 컨테이너 런타임이 이해할 수 있는 형식으로 변환
  2. 심볼릭 링크 관리

    • 파드가 생성될 때 /var/log/containers/ 디렉토리에 심볼릭 링크 생성
    • 컨테이너가 재시작될 때 심볼릭 링크 업데이트
    • 파드가 삭제될 때 심볼릭 링크 정리
  3. 로그 경로 관리

    • 쿠버네티스의 파드 구조를 반영한 일관된 로그 경로 제공
    • 네임스페이스, 파드 이름, 컨테이너 이름 등을 포함한 구조화된 경로 생성
  4. 로그 접근 제어

    • 로그 파일에 대한 접근 권한 관리
    • 보안 컨텍스트에 따른 로그 접근 제한
  5. 로그 수집기 통합

    • 로그 수집기(예: Fluentd, Filebeat)가 쉽게 로그에 접근할 수 있도록 지원
    • 일관된 로그 경로 구조 제공으로 수집기 설정 단순화

kubelet이 로그 로테이션 설정값을 컨테이너 런타임에 전달하는 이유

kubelet이 로그 로테이션 설정값을 컨테이너 런타임에 전달하는 이유는 다음과 같습니다.

  • 클러스터 전체의 일관성: kubelet이 정책을 통제함으로써, 모든 노드와 파드에 동일한 로그 정책을 적용할 수 있습니다.
  • 중앙집중적 관리: 운영자는 kubelet 설정만으로 전체 클러스터의 로그 정책을 쉽게 관리할 수 있습니다.
  • 동적 정책 적용: 파드 특성이나 클러스터 정책 변화에 따라 kubelet이 로그 정책을 유연하게 조정할 수 있습니다.
  • 런타임 추상화: kubelet이 중간에서 정책을 전달하므로, 컨테이너 런타임 종류와 무관하게 동일한 방식으로 로그 정책을 적용할 수 있습니다.
1kubelet:
2  containerLogMaxSize: "10Mi"      # 로그 파일의 최대 크기
3  containerLogMaxFiles: 5          # 보관할 로그 파일의 최대 개수
4  containerLogMaxAge: "7d"         # 로그 파일의 최대 보관 기간

이 설정들은 Kubelet이 컨테이너 런타임에 전달하는 설정값입니다. Kubelet은 이 설정값들을 컨테이너 런타임의 로그 드라이버 설정으로 변환하여 전달합니다.

 1┌──────────────────────────────────────────────────────────┐
 2│                          Kubelet                         │
 3│                                                          │
 4│  ┌──────────────┐   ┌──────────────┐   ┌──────────────┐  │
 5│  │              │   │              │   │              │  │
 6│  │  Log Config  │   │  Config      │   │  Container   │  │
 7│  │  Parameters  │   │  Converter   │   │  Runtime     │  │
 8│  │              │   │              │   │              │  │
 9│  │ - MaxSize    │──▶│ - Convert    │──▶│ - Apply      │  │
10│  │ - MaxFiles   │   │ - Validate   │   │ - Rotate     │  │
11│  │ - MaxAge     │   │ - Pass       │   │ - Cleanup    │  │
12│  └──────────────┘   └──────────────┘   └──────────────┘  │
13│                                                          │
14└──────────────────────────────────────────────────────────┘

정리:

  • kubelet이 로그 로테이션 설정값을 컨테이너 런타임에 전달하는 것은 쿠버네티스의 일관성, 중앙집중적 관리, 동적 정책 적용, 런타임 추상화라는 운영적 강점을 실현하기 위함입니다.

로그 관리 프로세스

 1┌────────────────────────────────────────────────────────────────────────────┐
 2│                                   Kubelet                                  │
 3│                                                                            │
 4│  ┌──────────────┐   ┌──────────────┐   ┌──────────────┐   ┌──────────────┐ │
 5│  │              │   │              │   │              │   │              │ │
 6│  │  Pod Watch   │   │  Symlink     │   │  Log Config  │   │  Access      │ │
 7│  │              │   │  Manager     │   │  Manager     │   │  Control     │ │
 8│  │ - Create     │──▶│ - Create     │──▶│ - Convert    │──▶│ - Permissions│ │
 9│  │ - Update     │   │ - Update     │   │ - Validate   │   │ - Security   │ │
10│  │ - Delete     │   │ - Delete     │   │ - Pass       │   │ - Context    │ │
11│  └──────────────┘   └──────────────┘   └──────────────┘   └──────────────┘ │
12│                                                                            │
13└────────────────────────────────────────────────────────────────────────────┘
  1. 파드 생명주기 관리

    • 파드 생성 시 로그 디렉토리 및 심볼릭 링크 생성
    • 파드 업데이트 시 필요한 로그 경로 조정
    • 파드 삭제 시 로그 관련 리소스 정리
  2. 심볼릭 링크 관리

    • 컨테이너 런타임의 로그 파일을 쿠버네티스 구조에 맞게 연결
    • 컨테이너 재시작 시 심볼릭 링크 업데이트
    • 로그 파일 경로의 일관성 유지
  3. 로그 설정 관리

    • 로그 로테이션 설정값 변환 및 전달
    • 컨테이너 런타임별 설정 형식 변환
    • 설정 유효성 검증
  4. 접근 제어 관리

    • 로그 파일에 대한 접근 권한 설정
    • 보안 컨텍스트에 따른 접근 제한
    • 로그 수집기 접근 허용

이러한 Kubelet의 로그 관리 역할은 쿠버네티스 클러스터에서 일관된 로그 관리와 접근을 가능하게 합니다.

로그 수집 구현체의 동작 방식

쿠버네티스 환경에서 로그를 수집하는 다양한 구현체들(예: Fluentd, Filebeat, Promtail 등)은 다음과 같은 방식으로 로그를 수집합니다.

파일 읽기 방식

1. 직접 파일 읽기

 1┌───────────────────────────────────────────────────────────┐
 2│                        Log Collector                      │
 3│                                                           │
 4│  ┌──────────────┐   ┌──────────────┐   ┌──────────────┐   │
 5│  │              │   │              │   │              │   │
 6│  │  File Watch  │   │  File Read   │   │  Log Process │   │
 7│  │              │   │              │   │              │   │
 8│  │ - inotify    │──▶│ - Read       │──▶│ - Parse      │   │
 9│  │ - fsnotify   │   │ - Buffer     │   │ - Position   │   │
10│  │              │   │ - Position   │   │ - Enrich     │   │
11│  └──────────────┘   └──────────────┘   └──────────────┘   │
12│                                                           │
13└───────────────────────────────────────────────────────────┘
  • 파일 감시

    • inotify(Linux) 또는 fsnotify(Go)를 사용하여 파일 변경 감지
    • 새로운 로그 파일 생성 감지
    • 로그 파일 수정 감지
  • 파일 읽기

    • 파일의 마지막 읽은 위치 추적
    • 새로운 내용만 읽어서 처리
    • 버퍼를 사용하여 효율적인 읽기 수행
  • 로그 처리

    • 읽은 로그 데이터 파싱
    • 필요한 메타데이터 추가
    • 로그 형식 변환

2. Tail 방식

 1┌──────────────────────────────────────────────────────────┐
 2│                        Log Collector                     │
 3│                                                          │
 4│  ┌──────────────┐   ┌──────────────┐   ┌──────────────┐  │
 5│  │              │   │              │   │              │  │
 6│  │  Tail Start  │   │  Tail Watch  │   │  Log Process │  │
 7│  │              │   │              │   │              │  │
 8│  │ - Open File  │──▶│ - Follow     │──▶│ - Parse      │  │
 9│  │ - Seek End   │   │ - Read New   │   │ - Buffer     │  │
10│  │              │   │ - Buffer     │   │ - Enrich     │  │
11│  └──────────────┘   └──────────────┘   └──────────────┘  │
12│                                                          │
13└──────────────────────────────────────────────────────────┘
  • Tail 시작

    • 로그 파일을 열고 끝으로 이동
    • 파일의 현재 크기 기록
  • Tail 감시

    • 파일 크기 변경 감지
    • 새로운 내용이 추가될 때마다 읽기
    • 버퍼를 사용하여 효율적인 읽기 수행
  • 로그 처리

    • 읽은 로그 데이터 파싱
    • 필요한 메타데이터 추가
    • 로그 형식 변환

로그 수집 최적화

1. 버퍼링과 배치 처리

  • 메모리 버퍼

    • 로그 데이터를 메모리에 버퍼링
    • 설정된 크기나 시간에 도달하면 배치 처리
  • 배치 처리

    • 여러 로그 라인을 하나의 요청으로 처리
    • 네트워크 오버헤드 감소
    • 처리 효율성 향상

2. 재시도와 장애 복구

  • 재시도 메커니즘

    • 로그 전송 실패 시 지수 백오프로 재시도
    • 최대 재시도 횟수 설정
  • 장애 복구

    • 로그 파일의 읽은 위치 저장
    • 재시작 시 마지막 위치부터 읽기 재개
    • 중복 수집 방지

3. 리소스 관리

  • 메모리 사용량 제한

    • 버퍼 크기 제한
    • 배치 크기 제한
  • CPU 사용량 제한

    • 파싱 및 처리 작업의 CPU 사용량 제한
    • 스로틀링 메커니즘 구현

이러한 로그 수집 구현체들은 쿠버네티스의 로그 관리 시스템과 잘 통합되어 작동하며, 대규모 클러스터에서도 안정적으로 로그를 수집할 수 있습니다.

댓글