ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • EFK 트러블슈팅: Fluent Bit CRI Parser 오류
    이코에코(Eco²)/Troubleshooting 2025. 12. 18. 11:44

    요약

    Elasticsearch에 수집된 로그가 JSON 파싱 없이 raw 문자열로 저장되는 문제 발생.
    원인은 containerd 런타임 환경에서 Docker parser를 사용한 것이었으며, CRI parser로 변경하여 해결.


    증상

    Kibana에서 로그 확인 시, log 필드에 CRI 형식 전체가 raw 문자열로 저장됨:

    {
      "log": "2025-12-18T00:25:46.032696223+09:00 stdout F {\"@timestamp\": \"2025-12-17T15:25:46.032+00:00\", \"message\": \"Attempting to instrument...\", \"log.level\": \"warning\"}"
    }

    기대했던 결과:

    {
      "stream": "stdout",
      "log_processed": {
        "@timestamp": "2025-12-17T15:25:46.032+00:00",
        "message": "Attempting to instrument...",
        "log.level": "warning"
      }
    }

    🔍 원인 분석

    1. Container Runtime 확인

    kubectl get nodes -o wide
    노드 Container Runtime
    k8s-api-auth containerd://2.1.5
    k8s-api-character containerd://2.1.5
    ... containerd

    발견: 모든 노드가 containerd 런타임을 사용 중.

    2. 로그 파일 형식 비교

    Docker 로그 형식 (JSON)

    {"log":"Hello World\n","stream":"stdout","time":"2025-01-01T00:00:00.000Z"}

    CRI 로그 형식 (containerd)

    2025-12-18T02:29:52.760924368+09:00 stderr F {"level":"info","msg":"..."}
    │                                    │      │ └── 실제 JSON 로그
    │                                    │      └── Flag (F=Full, P=Partial)
    │                                    └── Stream (stdout/stderr)
    └── CRI Timestamp

    3. 기존 Fluent Bit 설정 문제

    # ❌ 잘못된 설정
    [INPUT]
        Name              tail
        Path              /var/log/containers/*.log
        Parser            docker    # Docker 형식 파서 사용

    문제점: docker parser는 JSON 형식만 파싱 가능. CRI 형식의 로그는 파싱 실패.


    해결 방법

    1. CRI Parser 추가

    # parsers.conf
    [PARSER]
        Name        cri
        Format      regex
        Regex       ^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<logtag>[^ ]*) (?<log>.*)$
        Time_Key    time
        Time_Format %Y-%m-%dT%H:%M:%S.%L%z
        Time_Keep   On

    2. INPUT 설정 변경

    # fluent-bit.conf
    [INPUT]
        Name              tail
        Tag               kube.*
        Path              /var/log/containers/*.log
        Parser            cri    # ✅ CRI 파서로 변경
        DB                /fluent-bit/db/flb_kube.db
        Mem_Buf_Limit     50MB
        Skip_Long_Lines   On
        Refresh_Interval  10

    3. Kubernetes Filter (JSON 병합)

    [FILTER]
        Name                kubernetes
        Match               kube.*
        Kube_URL            https://kubernetes.default.svc:443
        Merge_Log           On           # JSON 로그 자동 파싱
        Merge_Log_Key       log_processed # 파싱 결과 저장 키
        K8S-Logging.Parser  On
        Labels              On

    4. 전체 파이프라인 흐름

    ┌─────────────────────────────────────────────────────────────────────────┐
    │  CRI 로그 파일                                                           │
    │  2025-12-18T02:29:52.760Z stderr F {"level":"info","msg":"Hello"}      │
    └─────────────────────────────────────────────────────────────────────────┘
                                        │
                                        ▼
    ┌─────────────────────────────────────────────────────────────────────────┐
    │  CRI Parser                                                              │
    │  time: 2025-12-18T02:29:52.760Z                                         │
    │  stream: stderr                                                          │
    │  logtag: F                                                               │
    │  log: {"level":"info","msg":"Hello"}                                    │
    └─────────────────────────────────────────────────────────────────────────┘
                                        │
                                        ▼
    ┌─────────────────────────────────────────────────────────────────────────┐
    │  Kubernetes Filter (Merge_Log)                                           │
    │  stream: stderr                                                          │
    │  logtag: F                                                               │
    │  log: {"level":"info","msg":"Hello"}                                    │
    │  log_processed:                                                          │
    │    level: info                                                           │
    │    msg: Hello                                                            │
    │  k8s_namespace_name: auth                                                │
    │  k8s_pod_name: auth-api-xxx                                              │
    └─────────────────────────────────────────────────────────────────────────┘
                                        │
                                        ▼
    ┌─────────────────────────────────────────────────────────────────────────┐
    │  Elasticsearch                                                           │
    │  인덱스: logs-2025.12.18                                                 │
    └─────────────────────────────────────────────────────────────────────────┘

    결과 확인

    적용 후 로그 샘플

    {
      "timestamp": "2025-12-17T18:59:58.713Z",
      "namespace": "auth",
      "container": "ext-authz",
      "stream": "stdout",
      "log_processed": {
        "@timestamp": "2025-12-17T18:59:58.713336366Z",
        "log_level": "INFO",
        "msg": "Starting metrics server",
        "ecs": { "version": "8.11" },
        "service": {
          "name": "ext-authz",
          "version": "1.0.7",
          "environment": ""
        },
        "address": ":9090"
      }
    }

    검색 가능한 필드

    필드 설명 예시 값
    stream stdout/stderr stdout
    logtag Full/Partial F
    log_processed.log_level 로그 레벨 INFO, ERROR
    log_processed.msg 로그 메시지 Starting metrics server
    log_processed.service.name 서비스명 ext-authz
    k8s_namespace_name 네임스페이스 auth
    k8s_pod_name Pod 이름 ext-authz-xxx

    교훈

    1. Container Runtime 확인 필수

    • Kubernetes 클러스터 구축 시 컨테이너 런타임 확인
    • Docker → containerd 마이그레이션 트렌드로 CRI 형식이 기본

    2. Fluent Bit Parser 선택 기준

    Container Runtime 로그 형식 권장 Parser
    Docker JSON docker
    containerd CRI cri
    CRI-O CRI cri

    3. Merge_Log 동작 이해

    • Merge_Log On: log 필드가 JSON이면 파싱하여 병합
    • Merge_Log_Key: 파싱 결과를 저장할 키 지정 (미지정 시 루트에 병합)

    소요 시간

    작업일: 2025-12-18
    소요시간: 약 30분
    결과: ✅ 해결


    Reference


    관련 파일

    • workloads/logging/base/fluent-bit.yaml - Fluent Bit 설정
    • docs/monitoring/EFK_LOGGING_PLAN.md - EFK 로깅 계획

    댓글

ABOUT ME

🎓 부산대학교 정보컴퓨터공학과 학사: 2017.03 - 2023.08
☁️ Rakuten Symphony Jr. Cloud Engineer: 2024.12.09 - 2025.08.31
🏆 2025 AI 새싹톤 우수상 수상: 2025.10.30 - 2025.12.02
🌏 이코에코(Eco²) 백엔드/인프라 고도화 중: 2025.12 - Present

Designed by Mango