feat(infra): scrape systemd journal logs via promtail#3542
Conversation
Add a journal scrape job to promtail with a whitelist of K8s and
security units (k3s, k3s-agent, containerd, sshd, systemd-logind,
sudo, kernel transport). Mounts host /var/log/journal as read-only.
Bumps memory limit 128Mi -> 256Mi for journal cursor overhead.
Estimated additional ingest: ~700 MB/day raw (~6 GB on minio over
90-day retention, well within capacity).
Enables LogQL queries like {job="systemd-journal", unit="k3s.service"}
for control plane debugging without SSH dependency.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request enables Promtail to scrape systemd-journal logs by mounting the host journal directory and adding a dedicated scrape configuration for system services like k3s and containerd. It also increases the memory limit for the Promtail deployment. Feedback suggests increasing the memory request to match the limit for 'Guaranteed' QoS and extending the journal 'max_age' to 24h to prevent data loss during extended downtime.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0e15e68e1c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Code reviewFound 1 issue:
codedang/infra/k8s/monitoring/promtail/values.yaml Lines 14 to 24 in 0e15e68 Bot reviewers (gemini-code-assist, chatgpt-codex-connector) raised two additional points that did not meet this review's confidence threshold but are worth a glance: bumping Robot Generated with Claude Code - If this code review was useful, please react with thumbs-up. Otherwise, react with thumbs-down. |
Without the host machine-id, the journal reader inside the container uses the container's own /etc/machine-id and looks for journals under /var/log/journal/<container-machine-id>/, which does not exist on the host filesystem. Result: zero logs ingested, no error surfaced. Independently flagged by codex and the in-house code review. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
max_age caps how far back promtail catches up when the positions cursor is unavailable. Positions live on tmpfs (/run/promtail/) so a node reboot triggers catch-up from now-max_age. 12h misses logs from a weekday outage that recovers the next morning; 24h covers that case while keeping startup catch-up bounded. Suggested by gemini-code-assist on PR review. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Description
promtail에
systemd-journalscrape job을 추가합니다. K8s/보안 관련 unit (k3s, k3s-agent, containerd, sshd, sudo, systemd-logind, kernel transport)을 화이트리스트로 수집하고, 호스트의/var/log/journal을 read-only로 마운트합니다. journal cursor 오버헤드를 위해 메모리 limit을 128Mi → 256Mi로 올립니다.해결하려는 문제: 최근 prod 컨트롤플레인 장애 조사 시 노드 로그(k3s, kernel link-flap 등)를 보려고
kubectl debug node+ chroot 우회로를 매번 사용해야 했습니다. systemd journal을 Loki에 중앙화하면 다음 사고 때 SSH 키 배포에 의존하지 않고 Grafana에서 LogQL 한 번으로 모든 노드 로그를 트리아지할 수 있습니다.L4-cheap에 해당하는 보안 시그널(sshd / sudo)도 추가 비용 거의 없이 함께 수집합니다.
수집 범위
k3s.service,k3s-agent.service,containerd.servicesystemd-logind.servicesshd.service,sudo이 PR 범위 밖 (별도 PR로 진행 예정): K8s API audit log, K8s Events (eventrouter), Falco.
동작 방식
promtail이 systemd journal을 어떻게 읽고, 어떤 라벨로 Loki에 보내는지 (펼쳐 보기)
파이프라인 (3단계):
journal:블록 핵심path: /var/log/journal— host에서 마운트한 위치. promtail은 sd-journal 라이브러리로 binary 파일 직접 readmax_age: 24h— positions cursor가 없거나 오래됐을 때 catch-up 상한. 정상 운영 (cursor 살아있음) 중엔 무관. 노드 재부팅(positions가 tmpfs/run/promtail/에 있어 휘발) 시 영향labels: { job: systemd-journal }— 모든 entry에 강제로 붙는 정적 라벨. LogQL{job="systemd-journal"}진입점matches:— source-side 필터 (read 자체를 안 함, drop보다 효율적). journalctl 매치 문법:UNIT=A UNIT=B→ A 또는 B)+= OR 그룹 분리(UNIT=k3s|k3s-agent|containerd|sshd|systemd-logind) OR TRANSPORT=kernel OR COMM=sudorelabel_configs— 라벨 변환internal 라벨(이중 underscore prefix)은 Loki push 전 drop됨. 보고 싶은 건
target_label로 promote.__journal__systemd_unit(2 underscore)unit_SYSTEMD_UNIT__journal__hostname(2)hostname_HOSTNAME__journal__transport(2)transport_TRANSPORT__journal_priority_keyword(1)levelPRIORITY0~7 →emerg..debug)라벨 카디널리티
Loki는 라벨 조합당 stream 1개. 우리 조합:
job1 ×hostname5 ×unit~7 ×transport4 ×level8 = 이론 max ~1,120 stream200400 stream 예상 (Loki 단일 tenant 권장 한계 1만~10만)_PID_UID같은 고카디널리티 field는 라벨로 promote 안 함 — 본문 검색(|=)으로 충분LogQL 사용 예시
Additional context
용량 추정 —
kubectl debug node로 prod 노드에서 직접 샘플링한 결과:k3s.service)노드 측 작업 불필요 — prod 5개 노드 모두
/var/log/journal/디렉토리가 이미 존재하고 journaldStorage=auto기본값에서 persistent로 동작 중입니다. Ansible playbook 수정 없음.리뷰 포인트
matches:화이트리스트 문법 (journalctl 스타일;+는 필드 간 OR, 같은 필드 반복은 필드 내 OR)검증 계획 (
main머지 후 stage 클러스터에서):{job="systemd-journal"}결과 반환 확인{unit="k3s.service"},{transport="kernel"},{unit="sshd.service"}kubernetes-podsscrape 회귀 없음Before submitting the PR, please make sure you do the following
fixes #123).🤖 Generated with Claude Code