콘텐츠로 이동

Journald


Journald 수집기는 Linux 시스템에서 systemd journal(journald)로부터 로그를 수집하는 데 사용됩니다. 외부 바이너리 래퍼를 사용해 libsystemd와 상호작용하며, journal에서 구조화된 로그 항목을 효율적으로 수집합니다.

사전 조건

  • Linux 전용: systemdjournald가 필요합니다
  • libsystemd: 외부 바이너리에는 libsystemd 개발 라이브러리가 필요합니다
  • 권한: DataKit이 journal 파일을 읽을 수 있어야 합니다(보통 systemd-journal 그룹에 추가해야 함)

시스템 요구 사항 확인

journald 수집기를 배포하기 전에 시스템이 요구 사항을 충족하는지 확인하세요.

다음 명령으로 빠르게 확인할 수 있습니다.

systemctl --version >/dev/null 2>&1 && journalctl -n 1 >/dev/null 2>&1 && echo "Systemd OK" || echo "Systemd not available"

다음은 전체 사전 점검 스크립트입니다.

journald-prereq-check.sh
#!/bin/bash
# journald-prereq-check.sh - systemd 요구 사항 확인

echo "=== Journald 수집기 사전 조건 검사 ==="
echo

# 1. systemctl 존재 여부 확인
echo -n "1. systemctl 명령어: "
if command -v systemctl >/dev/null 2>&1; then
    VERSION=$(systemctl --version | head -1)
    echo "✅ 발견됨 - $VERSION"
else
    echo "❌ 찾을 수 없음 - systemctl이 설치되어 있지 않음"
    exit 1
fi

# 2. libsystemd 라이브러리 확인
echo -n "2. libsystemd.so.0: "
if ldconfig -p 2>/dev/null | grep -q "libsystemd.so.0"; then
    LIBPATH=$(ldconfig -p 2>/dev/null | grep "libsystemd.so.0" | head -1 | awk '{print $NF}')
    echo "✅ 발견됨 - $LIBPATH"
else
    echo "❌ 찾을 수 없음 - libsystemd.so.0 누락"
    exit 1
fi

# 3. journalctl 접근 권한 확인
echo -n "3. journalctl 접근: "
if journalctl -n 1 >/dev/null 2>&1; then
    echo "✅ 정상 - journal을 읽을 수 있음"
else
    echo "⚠️  제한됨 - journalctl은 존재하지만 읽기 권한이 없음"
fi

# 4. journal 디렉터리 확인
echo "4. Journal 디렉터리: "
for dir in "/var/log/journal" "/run/log/journal"; do
    echo -n "   $dir: "
    if [ -d "$dir" ]; then
        if [ -r "$dir" ]; then
            echo "✅ 존재하며 읽기 가능"
        else
            echo "⚠️  존재하지만 읽기 불가"
        fi
    else
        echo "❌ 찾을 수 없음"
    fi
done

# 5. systemd 버전 확인
echo -n "5. systemd 버전: "
SYSTEMD_VERSION=$(systemctl --version | head -1 | grep -oP 'systemd \K\d+' || echo "0")
if [ "$SYSTEMD_VERSION" -ge 205 ]; then
    echo "✅ v$SYSTEMD_VERSION (최소 v205 요구 사항 충족)"
else
    echo "⚠️  v$SYSTEMD_VERSION (권장 버전 v205보다 낮음)"
fi

echo
echo "=== 검사 완료 ==="

journald-prereq-check.sh로 저장한 뒤 실행하세요.

chmod +x journald-prereq-check.sh
./journald-prereq-check.sh

예상 출력:

=== Journald 수집기 사전 조건 검사 ===

1. systemctl 명령어: ✅ 발견됨 - systemd 257 (257.3-1-arch)
2. libsystemd.so.0: ✅ 발견됨 - /usr/lib/libsystemd.so.0
3. journalctl 접근: ✅ 정상 - journal을 읽을 수 있음
4. Journal 디렉터리:
   /var/log/journal: ✅ 존재하며 읽기 가능
   /run/log/journal: ✅ 존재하며 읽기 가능
5. systemd 버전: ✅ v257 (최소 v205 요구 사항 충족)

=== 검사 완료 ===

가능한 문제 해결 방안:

문제 해결 방법
systemctl: command not found systemd를 설치하거나 대체 로그 수집 방식을 사용하세요
libsystemd.so.0: cannot open systemd-libs를 설치하세요: apt install libsystemd0 또는 yum install systemd-libs
journalctl: no read access 사용자를 systemd-journal 그룹에 추가하세요: usermod -aG systemd-journal $USER
/var/log/journal not found 지속성 journal을 활성화하세요: mkdir -p /var/log/journal && systemd-tmpfiles --create

설정

수집기 설정

DataKit 설치 및 시작이 완료되면, 설정 파일을 복사해 Journald 수집기를 활성화할 수 있습니다.

DataKit 설치 디렉터리의 conf.d/samples 디렉터리로 이동한 뒤 journald.conf.sample을 복사해 journald.conf로 이름을 바꾸세요. 예시는 다음과 같습니다:

# 외부 바이너리를 사용해 systemd journal 로그 수집
[[inputs.journald]]
  ## 수집기 이름
  name = 'journald'

  ## 데몬으로 실행(journald 수집에 필요)
  daemon = true

  http_endpoint = "http://localhost:9529"
  log_level = "info"
  log_path = "/usr/local/datakit/externals/journald.log"

  ## datakit-journald 바이너리 경로
  ## 기본값: /usr/local/datakit/externals/datakit-journald 및 ./externals/datakit-journald에서 검색
  # cmd = "/usr/local/datakit/externals/datakit-journald"

  ## 외부 프로세스 확인 간격(daemon 모드가 아닐 때)
  # interval = "10s"

  ## 컨테이너/Kubernetes 모드에서만 사용하는 rootfs 마운트 지점
  ## DataKit은 절대 경로를 자동 접두사 처리할 때 호스트 root 접두사로 이것을 사용하며,
  ## 호스트 측 systemd 라이브러리 준비(copy_node_libs)에도 사용합니다.
  mount_dir = "/rootfs"

  ## Journal 디렉터리 경로
  ## 호스트 설치: 기본 경로 사용
  ## 컨테이너/Kubernetes: DataKit이 절대 경로에 mount_dir을 자동 접두사로 붙입니다.
  paths = [
    "/var/log/journal",      # 영구 저장소
    "/run/log/journal",      # 런타임 저장소
  ]

  ## systemd unit 이름으로 필터링(glob 패턴 지원)
  ## 비어 있으면 전체 unit
  # units = ["*.service", "docker.service", "kubelet.service"]

  ## 우선순위 수준으로 필터링
  ## 수준: emerg(0), alert(1), crit(2), err(3), warning(4), notice(5), info(6), debug(7)
  ## 비어 있으면 전체 우선순위
  # priorities = ["err", "warning", "crit", "alert", "emerg"]

  ## 필드 선택 - 기본적으로 모두 수집하고, 특정 필드만 제외
  exclude_fields = [
    "_BOOT_ID",
    "_MACHINE_ID",
    "__MONOTONIC_TIMESTAMP",
  ]

  ## 수집 동작
  ## tail_only=true: 새 항목만 수집(cursor 불필요)
  ## tail_only=false: 마지막 위치부터 읽기(cursor 필요)
  tail_only = true
  max_entries_per_batch = 1000

  ## cursor 관리(tail_only=false일 때만 사용)
  # save_cursor = true
  # cursor_file = "/usr/local/datakit/cache/journald.cursor"

  ## 외부 바이너리를 위한 환경 변수
  # envs = [
  #   "LD_LIBRARY_PATH=/usr/local/datakit/externals:$LD_LIBRARY_PATH",
  # ]

  ## 호스트 측 systemd 라이브러리 준비:
  ## - 컨테이너/Kubernetes(Docker 또는 Kubernetes): 자동으로 true로 강제 설정됩니다.
  ## - 비컨테이너 호스트: 기본적으로 비활성화됩니다. 수동으로 활성화할 경우 copy_node_libs_files를 명시적으로 설정하세요.
  ## - 컨테이너/kubernetes 모드에서 copy_node_libs_files가 비어 있으면, DataKit은 먼저
  ##   libsystemd.so*를 복사한 뒤 "LD_LIBRARY_PATH=<dst> ldd libsystemd.so.0"
  ##   형식의 의존성 탐지를 수행하고 누락된 .so 파일을 자동으로 복사합니다.
  # copy_node_libs = true
  ## 선택적 덮어쓰기 파일 목록. 설정하면 이 패턴/파일만 복사합니다.
  # copy_node_libs_files = [
  #   "libsystemd.so*",
  #   "liblz4.so*",
  #   "libzstd.so*",
  #   "liblzma.so*",
  #   "libcap.so*",
  #   "libgcrypt.so*",
  #   "libgpg-error.so*",
  #   "libselinux.so*",
  #   "libmount.so*",
  #   "libblkid.so*",
  #   "libacl.so*",
  #   "libpcre2-8.so*",
  #   "libpcre.so*",
  # ]

  ## 외부 바이너리용 추가 인자
  # args = []

  [inputs.journald.tags]
    # 필요에 따라 사용자 정의 태그 추가
    # environment = "production"
    # cluster = "k8s-cluster-1"

설정을 완료한 뒤 DataKit을 재시작하세요.

ConfigMap으로 수집기 설정 주입 또는 ENV_DATAKIT_INPUTS 설정을 통해 활성화할 수 있습니다.

설정 옵션

옵션 유형 기본값 설명
paths []string ["/var/log/journal", "/run/log/journal"] Journal 디렉터리 경로
units []string [] systemd unit 이름으로 필터링(glob 패턴 지원, 예: *.service)
priorities []string [] 우선순위로 필터링: emerg, alert, crit, err, warning, notice, info, debug
exclude_fields []string [] 수집에서 제외할 journal 필드(예: _BOOT_ID, _MACHINE_ID)
tail_only bool true 새 항목만 수집(시작 시 이전 로그는 건너뜀)
max_entries_per_batch int 1000 배치당 수집할 최대 항목 수
save_cursor bool true 재시작 후 복구할 수 있도록 읽기 위치를 영구 저장
cursor_file string /usr/local/datakit/cache/journald.pos cursor 위치를 저장하는 경로
mount_dir string "/rootfs" 컨테이너/Kubernetes 모드에서만 사용하는 rootfs 마운트 디렉터리. DataKit은 절대 paths의 접두사와 호스트 측 동적 라이브러리 준비의 소스 디렉터리 루트로 이것을 사용합니다
copy_node_libs bool false(컨테이너 또는 Kubernetes에서는 자동으로 true로 강제됨) external collector 시작 전에 mount_dir에서 호스트 동적 라이브러리를 DataKit의 external-libs 디렉터리로 복사할지 여부. 컨테이너 또는 Kubernetes 환경(datakit.Docker || config.IsKubernetes())에서는 자동 활성화됩니다
copy_node_libs_files []string [] 복사할 동적 라이브러리 파일명 또는 glob 목록. 명시적으로 설정하면 해당 목록만 복사합니다. 컨테이너/Kubernetes 자동 모드에서 비어 있으면 DataKit은 먼저 libsystemd.so*를 복사한 뒤 LD_LIBRARY_PATH=/usr/local/datakit/externals/systemd-libs ldd libsystemd.so.0 형식의 의존성 탐지를 수행하고 누락된 .so를 자동으로 보완합니다. 비컨테이너/Kubernetes 환경에서 copy_node_libs=true인데 비어 있으면 설정 오류로 시작에 실패합니다

로그 필드

journald

Systemd 로그입니다. 참고: 필드의 사용 가능 여부는 systemd 버전에 따라 다릅니다 - 각 필드 설명의 버전 표기(v188+, v205+ 등)를 참고하세요

Tags & Fields Description
host
(tag)
Hostname (_HOSTNAME에서 가져옴, v188+)
service
(tag)
Service 식별자(SYSLOG_IDENTIFIER, _SYSTEMD_UNIT, 또는 _COMM에서 가져옴)
CODE_FILE 디버깅용 소스 코드 파일명(v188+)
Type: string
Unit: N/A
CODE_FUNC 디버깅용 함수명(v188+)
Type: string
Unit: N/A
CODE_LINE 디버깅용 소스 코드 줄 번호(v188+)
Type: int
Unit: N/A
COREDUMP_CMDLINE 크래시 시점의 전체 명령줄(v188+)
Type: string
Unit: N/A
COREDUMP_CWD 크래시 시점의 현재 작업 디렉터리(v188+)
Type: string
Unit: N/A
COREDUMP_EXE 크래시한 바이너리의 실행 파일 경로(v188+)
Type: string
Unit: N/A
COREDUMP_GID 크래시한 프로세스의 GID(v188+)
Type: int
Unit: N/A
COREDUMP_HOSTNAME 크래시 시점의 호스트명(v188+)
Type: string
Unit: N/A
COREDUMP_PID 크래시한 프로세스의 PID(v188+)
Type: int
Unit: N/A
COREDUMP_ROOT 루트 디렉터리, 보통 /(v188+)
Type: string
Unit: N/A
COREDUMP_SIGNAL 크래시를 유발한 시그널 번호(v188+)
Type: int
Unit: N/A
COREDUMP_STACKTRACE 전체 스택 트레이스 백트레이스(v188+)
Type: string
Unit: N/A
COREDUMP_TIMESTAMP 마이크로초 단위 크래시 타임스탬프(v188+)
Type: int
Unit: timeStamp,usec
COREDUMP_UID 크래시한 프로세스의 UID(v188+)
Type: int
Unit: N/A
COREDUMP_UNIT 크래시한 시스템 unit(v198+)
Type: string
Unit: N/A
COREDUMP_USER_UNIT 크래시한 사용자 unit(v198+)
Type: string
Unit: N/A
DOCUMENTATION 문서 URL http/https/file/man/info(v246+)
Type: string
Unit: N/A
ERRNO 메시지와 연관된 Unix 오류 번호(v188+)
Type: int
Unit: N/A
INVOCATION_ID systemd 코드 메시지의 invocation ID(v245+)
Type: string
Unit: N/A
MESSAGE_ID 128비트 메시지 식별자(UUID 형식, v188+)
Type: string
Unit: N/A
OBJECT_AUDIT_LOGINUID 대상 로그인 UID(v205+)
Type: int
Unit: N/A
OBJECT_AUDIT_SESSION 대상 audit 세션 ID(v205+)
Type: int
Unit: N/A
OBJECT_CMDLINE 대상 프로세스의 전체 명령줄(v205+)
Type: string
Unit: N/A
OBJECT_COMM 대상 프로세스 comm(v205+)
Type: string
Unit: N/A
OBJECT_EXE 대상 프로세스 실행 파일 경로(v205+)
Type: string
Unit: N/A
OBJECT_GID 대상 프로세스 GID(v205+)
Type: int
Unit: N/A
OBJECT_PID 대상 프로세스 PID, 설정에는 UID 0이 필요함(v205+)
Type: int
Unit: N/A
OBJECT_SYSTEMD_CGROUP 대상 cgroup 경로(v205+)
Type: string
Unit: N/A
OBJECT_SYSTEMD_INVOCATION_ID 대상 invocation ID(v235+)
Type: string
Unit: N/A
OBJECT_SYSTEMD_OWNER_UID 대상 세션 소유자 UID(v205+)
Type: int
Unit: N/A
OBJECT_SYSTEMD_SESSION 대상 세션 ID(v205+)
Type: string
Unit: N/A
OBJECT_SYSTEMD_UNIT 대상 unit 이름(v205+)
Type: string
Unit: N/A
OBJECT_SYSTEMD_USER_UNIT 대상 사용자 unit 이름(v205+)
Type: string
Unit: N/A
OBJECT_UID 대상 프로세스 UID(v205+)
Type: int
Unit: N/A
SYSLOG_FACILITY Syslog facility 0-23(v188+)
Type: int
Unit: N/A
SYSLOG_PID syslog의 클라이언트 PID, _PID와 다를 수 있음(v188+)
Type: int
Unit: N/A
SYSLOG_RAW MESSAGE가 수정되었거나 타임스탬프가 손실된 경우의 원본 syslog 라인(v240+)
Type: string
Unit: N/A
SYSLOG_TIMESTAMP 수신된 원본 syslog 타임스탬프(v188+)
Type: string
Unit: N/A
TID 숫자형 스레드 ID(v247+)
Type: int
Unit: N/A
UNIT _SYSTEMD_UNIT의 사용자 제공 대안 unit 이름(v251+)
Type: string
Unit: N/A
USER_INVOCATION_ID 사용자 관리자 메시지용 user invocation ID(v245+)
Type: string
Unit: N/A
USER_UNIT _SYSTEMD_USER_UNIT의 사용자 제공 대안 user unit 이름(v251+)
Type: string
Unit: N/A
_AUDIT_LOGINUID 커널 audit의 login UID(v188+)
Type: int
Unit: N/A
_AUDIT_SESSION 커널의 audit 세션 ID(v188+)
Type: int
Unit: N/A
_BOOT_ID 부팅 ID 128비트 hex UUID(v188+)
Type: string
Unit: N/A
_CAP_EFFECTIVE 유효 capabilities 비트마스크(v206+)
Type: int
Unit: N/A
_CMDLINE 전체 명령줄, 가장 완전한 프로세스 정보(v188+)
Type: string
Unit: N/A
_COMM 15자로 잘린 명령 이름(v188+)
Type: string
Unit: N/A
_CONTAINER_ID nspawn/컨테이너용 컨테이너 ID(v205+)
Type: string
Unit: N/A
_CONTAINER_IMAGE nspawn/컨테이너용 컨테이너 이미지(v205+)
Type: string
Unit: N/A
_CONTAINER_NAME nspawn/컨테이너용 컨테이너 이름(v205+)
Type: string
Unit: N/A
_EXE 실행 파일 경로, 전체 경로(v188+)
Type: string
Unit: N/A
_GID 그룹 ID, 신뢰됨(v188+)
Type: int
Unit: N/A
_KERNEL_DEVICE 커널 디바이스 이름 형식: bM:N, cM:N, nN, +subsys:name(v189+)
Type: string
Unit: N/A
_KERNEL_SUBSYSTEM 커널 하위 시스템 예: block, net(v189+)
Type: string
Unit: N/A
_LINE_BREAK 줄 끝 정보: nul, line-max, eof, pid-change(v235+)
Type: string
Unit: N/A
_MACHINE_ID /etc/machine-id의 Machine ID(v188+)
Type: string
Unit: N/A
_NAMESPACE Journal 네임스페이스 ID(v245+)
Type: string
Unit: N/A
_RUNTIME_SCOPE 런타임 범위: initrd, system, user(v252+)
Type: string
Unit: N/A
_SELINUX_CONTEXT SELinux 보안 컨텍스트 레이블(v188+)
Type: string
Unit: N/A
_SOURCE_BOOTTIME_TIMESTAMP 마이크로초 단위 부팅 시간 타임스탬프 CLOCK_BOOTTIME(v257+)
Type: int
Unit: time,μs
_SOURCE_REALTIME_TIMESTAMP 마이크로초 단위 소스 타임스탬프 CLOCK_REALTIME(v188+)
Type: int
Unit: timeStamp,usec
_STREAM_ID stdout 스트림용 스트림 연결 ID 128비트 UUID(v235+)
Type: string
Unit: N/A
_SYSTEMD_CGROUP 제어 그룹 경로(v188+)
Type: string
Unit: N/A
_SYSTEMD_INVOCATION_ID unit 시작마다 고유한 unit invocation ID(v233+)
Type: string
Unit: N/A
_SYSTEMD_OWNER_UID 세션 소유자 UID(v188+)
Type: int
Unit: N/A
_SYSTEMD_SESSION 로그인 세션 ID(v188+)
Type: string
Unit: N/A
_SYSTEMD_SLICE slice unit 이름 예: system.slice(v188+)
Type: string
Unit: N/A
_SYSTEMD_UNIT unit 이름 예: sshd.service(v188+)
Type: string
Unit: N/A
_SYSTEMD_USER_SLICE 사용자 slice 이름 예: user.slice(v188+)
Type: string
Unit: N/A
_SYSTEMD_USER_UNIT 사용자 세션용 user unit 이름(v188+)
Type: string
Unit: N/A
_TRANSPORT 항목이 수신된 방식: audit, driver, syslog, journal, stdout, kernel(v205+)
Type: string
Unit: N/A
_UDEV_DEVLINK 디바이스로 가는 심볼릭 링크, 여러 번 나타날 수 있음(v189+)
Type: string
Unit: N/A
_UDEV_DEVNODE /dev/의 디바이스 노드 전체 경로(v189+)
Type: string
Unit: N/A
_UDEV_SYSNAME /sys/의 디바이스 이름(v189+)
Type: string
Unit: N/A
_UID 사용자 ID, 신뢰됨으로 위조 불가(v188+)
Type: int
Unit: N/A
__CURSOR 항목 cursor, address field export only(v188+)
Type: string
Unit: N/A
__MONOTONIC_TIMESTAMP 마이크로초 단위의 단조 증가 타임스탬프, address field export only(v188+)
Type: int
Unit: time,μs
__REALTIME_TIMESTAMP 마이크로초 단위 수신 타임스탬프, address field export only(v188+)
Type: int
Unit: timeStamp,usec
__SEQNUM 시퀀스 번호, address field export only(v254+)
Type: int
Unit: N/A
__SEQNUM_ID 시퀀스 ID, address field export only(v254+)
Type: string
Unit: N/A
journald_timestamp _SOURCE_REALTIME_TIMESTAMP 또는 __REALTIME_TIMESTAMP에서 가져온 나노초 단위 Journal 항목 타임스탬프(v188+)
Type: int
Unit: timeStamp,nsec
message 로그 메시지 내용(MESSAGE에서 가져옴, v188+)
Type: string
Unit: N/A
pid 프로세스 ID(_PID 또는 SYSLOG_PID에서 가져옴, v188+)
Type: int
Unit: N/A
priority 숫자 우선순위 수준 0-7(PRIORITY에서 가져옴, v188+)
Type: int
Unit: N/A
status 우선순위에서 매핑된 로그 상태 수준: error, warn, critical, notice, info, debug, unknown
Type: string
Unit: N/A

일반적인 사용 사례

  • 특정 서비스의 로그 수집
[[inputs.journald]]
  units = ["nginx.service", "mysql.service", "docker.service"]
  priorities = ["err", "crit", "alert", "emerg"]
  tail_only = true
  • 불필요한 필드 제외
[[inputs.journald]]
  exclude_fields = [
    "_BOOT_ID",
    "_MACHINE_ID",
    "__MONOTONIC_TIMESTAMP",
    "_AUDIT_SESSION",
    "_AUDIT_LOGINUID",
  ]
  • Kubernetes 노드 journal 수집(자동 모드)
[[inputs.journald]]
  paths = ["/var/log/journal", "/run/log/journal"]
  tail_only = true

설명:

  • collector는 설정된 순서대로 후보 디렉터리를 해석하며, 가장 먼저 읽을 수 있는 journal 디렉터리를 우선 열려고 시도합니다
  • 컨테이너 또는 Kubernetes 환경(datakit.Docker || config.IsKubernetes())에서는 DataKit이 journald rootfs 모드를 자동 활성화합니다
  • 컨테이너/Kubernetes 모드에서는 절대 경로에 자동으로 mount_dir 접두사("/rootfs" 기본값)가 붙습니다
  • 경로 자체가 <mount_dir>/var/log/journal 같은 journal 루트 디렉터리이면, collector는 machine-id 하위 디렉터리로 자동 진입한 뒤 엽니다
  • kind, k3d 같은 컨테이너화된 노드 환경에서는 host가 아니라 node 컨테이너 안에서 logger/journalctl을 검증해야 합니다

  • Kubernetes 노드 journal 수집 및 시작 전 호스트 systemd 관련 라이브러리 준비

[[inputs.journald]]
  mount_dir = "/rootfs"
  paths = ["/var/log/journal", "/run/log/journal"]
  tail_only = true
  copy_node_libs = true
  copy_node_libs_files = [
    "libsystemd.so*",
    "liblz4.so*",
    "libzstd.so*",
    "liblzma.so*",
    "libcap.so*",
    "libgcrypt.so*",
    "libgpg-error.so*",
    "libselinux.so*",
    "libmount.so*",
    "libblkid.so*",
    "libacl.so*",
    "libpcre2-8.so*",
    "libpcre.so*",
  ]
  • 모든 로그 수집(디버그)
[[inputs.journald]]
  tail_only = false
  max_entries_per_batch = 500
  exclude_fields = []

문제 해결

권한 오류

DataKit에 journal 파일을 읽을 권한이 있는지 확인하세요.

# datakit 사용자를 systemd-journal 그룹에 추가
sudo usermod -aG systemd-journal datakit

# DataKit 재시작
sudo systemctl restart datakit

로그가 수집되지 않음

  1. journald가 실행 중인지 확인하세요:
systemctl status systemd-journald
  1. journal 파일이 존재하는지 확인하세요:
ls -la /var/log/journal/
ls -la /run/log/journal/
  1. 현재 환경에 journalctl이 설치되어 있다면 추가 검증에 계속 사용할 수 있습니다. 컨테이너에 journalctl이 없다면 DataKit의 호환성 경고와 probe 결과를 직접 확인하세요:
journalctl -n 10

시작 로그에 reason=unsupported-format이 나타나면, 현재 collector가 사용하는 libsystemd 버전이 대상 journal 파일 형식보다 낮다는 뜻입니다. 이 경우 DataKit은 경고를 기록하고 journald collector를 inactive 상태로 유지하며, 일부 또는 오해를 부를 수 있는 수집 결과를 계속 내보내지 않습니다.

이 문제는 EKS에서만 발생하는 것이 아닙니다. Kubernetes에서는 DataKit이 node의 journal을 수집해야 하는데, 컨테이너 이미지에 포함된 libsystemd 버전이 호스트의 journal 파일 형식에 필요한 버전보다 낮으면 같은 문제가 발생할 수 있습니다. 대표적인 현상은 다음과 같습니다.

  • Pod 안에 journalctl이 설치되어 있으면 실행 시 unsupported feature가 나타날 수 있음
  • DataKit은 이미 시작되었지만, journald collector는 호환성 경고 이후 inactive 상태로 유지됨

컨테이너 또는 Kubernetes 환경(datakit.Docker || config.IsKubernetes())에서는 DataKit이 호스트 systemd 관련 동적 라이브러리 준비 기능을 자동으로 활성화합니다. 비컨테이너 환경에서도 활성화하려면 다음처럼 설정할 수 있습니다.

[[inputs.journald]]
  copy_node_libs = true

활성화되면 DataKit은 collector 시작 전에 mount_dir(기본 "/rootfs") 아래의 후보 시스템 라이브러리 디렉터리에서 동적 라이브러리를 복사해 자신의 external-libs 디렉터리에 넣고, 해당 디렉터리를 LD_LIBRARY_PATH 앞부분에 추가합니다.

복사 동작의 세부 사항:

  • copy_node_libs_files가 설정되어 있고 비어 있지 않으면, 그 목록만 복사합니다.
  • 컨테이너/Kubernetes 자동 모드에서 copy_node_libs_files가 비어 있으면, DataKit은 먼저 libsystemd.so*를 복사한 뒤 복사된 디렉터리에서 libsystemd.so.0에 대해 ldd 의존성 탐지를 수행하고 누락된 .so를 자동으로 보완합니다.
  • 비컨테이너이면서 Kubernetes도 아니고 copy_node_libs=true이며 copy_node_libs_files가 비어 있으면, DataKit은 설정 오류를 보고 collector를 inactive 상태로 유지합니다.
  • copy_node_libs 활성화 후 라이브러리 준비에 실패하면 journald 수집기는 inactive 상태를 유지합니다(DataKit의 다른 수집기에는 영향 없음).

collector가 journal을 성공적으로 연 뒤에는 external journald.log에 다음과 비슷한 로그를 출력하여 런타임에 어떤 libsystemd 세트가 실제로 로드되었는지 확인하는 데 도움을 줍니다.

loaded libsystemd paths: [/usr/local/datakit/externals/systemd-libs/libsystemd.so.0.35.0]

제약 사항:

  • 호스트의 libsystemd가 DataKit이 현재 사용하는 journald external binary와 항상 호환되는 것은 아닙니다
  • 호스트의 libsystemd 버전이 너무 낮으면, external binary는 동적 링크 단계에서 심볼 또는 버전 불일치로 시작하지 못할 수 있습니다
  • 호스트의 libsystemd 버전이 더 높더라도 journal 파일을 읽을 때 unsupported feature가 발생할 수 있습니다
  • 따라서 copy_node_libs는 사전 준비 기능일 뿐이며, 복사된 라이브러리가 반드시 호환된다는 뜻은 아닙니다. 최종 판단은 여전히 시작 로그와 probe 결과를 함께 봐야 합니다

호스트 전체 /usr/lib64를 그대로 LD_LIBRARY_PATH에 추가하지 마세요. 그러면 호환되지 않는 glibc 구성 요소까지 collector 프로세스에 함께 들어와 더 진단하기 어려운 문제가 생길 수 있습니다.

시작 로그에 다음이 표시되면:

resolved journal directory: target=...
opening journal from directory: ...

collector가 디렉터리 방식으로 journal을 열고 있다는 뜻이며, 이것이 현재 live journal에 권장되는 경로입니다. 단일 .journal 파일 경로를 주요 설정 방식으로 수동 지정하지 마세요.

cursor 파일 문제

cursor 파일이 손상된 경우(예: 호스트 재부팅 후) 수집기는 자동으로 tail 모드로 되돌아가 새 cursor를 생성합니다. 수동으로 초기화하려면:

# cursor 파일 삭제
rm /usr/local/datakit/cache/journald.pos

# DataKit 재시작
sudo systemctl restart datakit

메모리 사용량이 높음

기본 배치 크기는 1000개 항목입니다. 메모리 사용량이 문제라면 배치 크기를 줄일 수 있습니다.

[[inputs.journald]]
  max_entries_per_batch = 100

문서 평가

이 페이지가 도움이 되었나요?