Files
obsidian/infra/victorialogs.md
kappa b5e22c2081 APISIX real_ip patch + Vector parse_apisix 정규식 업데이트 기록
- apisix.md: real_ip_from 0.0.0.0/0, real_ip_header X-Forwarded-For, access_log_format에 xff/xrip 추가. helm values 미반영, cm 직접 patch 패턴
- victorialogs.md: 진짜 IP 기반 LogsQL 예시, parse_apisix 정규식과 APISIX log format이 짝이라는 주의
2026-04-08 21:02:02 +09:00

6.2 KiB

title, updated, tags
title updated tags
VictoriaLogs (K3s 로그 저장) 2026-04-08 Grafana 통합
k3s
logging
vector
observability
grafana

VictoriaLogs

K3s 클러스터의 raw 로그 저장소. 메트릭은 victoriametrics-stack, 로그는 VictoriaLogs로 분리. 같은 VM 팀 제품이라 운영 패턴 일치.

접속

항목
Web UI https://vl.inouter.com/select/vmui/
HTTP API https://vl.inouter.com/
클러스터 내부 http://vlogs-victoria-logs-single-server.logging.svc.cluster.local:9428
노출 방식 LAN 직접 (Cloudflare DNS → k3s.inouter.com → MetalLB 192.168.9.53 → Traefik IngressRoute), BunnyCDN 우회
TLS wildcard-inouter-tls (reflector로 logging ns에 자동 복제)
인증 없음 (LAN/Tailscale 안에서만 접근 가능)

설치

helm repo add vm https://victoriametrics.github.io/helm-charts/
helm install vlogs vm/victoria-logs-single -n logging -f vlogs-values.yaml

values 핵심:

server:
  retentionPeriod: 14d
  persistentVolume:
    enabled: true
    storageClassName: longhorn
    size: 50Gi
  resources:
    requests: { cpu: 100m, memory: 256Mi }
    limits:   { cpu: 1000m, memory: 1Gi }
  • 단일 노드 (victoria-logs-single), 14일 보존, longhorn 50GiB PVC
  • 네임스페이스: logging (Vector와 같은 곳)

Traefik IngressRoute

logging ns:

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: vlogs
  namespace: logging
spec:
  entryPoints: [websecure]
  routes:
    - match: Host(`vl.inouter.com`)
      kind: Rule
      services:
        - name: vlogs-victoria-logs-single-server
          port: 9428
  tls:
    secretName: wildcard-inouter-tls

데이터 파이프라인

APISIX 로그 (현재 가동 중)

APISIX (apisix ns, 2 replica) stdout (nginx access log 형식)
  → Vector daemonset (logging ns, 3 노드)
    - source: apisix_logs (kubernetes_logs, label=app.kubernetes.io/name=apisix)
    - transform: parse_apisix (정규식 파싱 → method/path/status/request_time/host/UA 등 구조화)
    - sink: vlogs (elasticsearch bulk API)
  → VictoriaLogs (/insert/elasticsearch/_bulk)

Vector helm values는 vector 문서 또는 helm get values vector -n logging 참조.

다른 잠재 source

  • Traefik 로그는 별도 sink로 crowdsec-safeline에 전송 (vector의 다른 transform/sink). VictoriaLogs로는 안 보내고 있음. 필요하면 sink inputs에 parse_traefik 추가하면 됨.

Grafana 통합

vm-stack의 Grafana(monitoring/vm-stack-grafana)에 등록되어 있음. Explore에서 data source를 VictoriaLogs로 선택하면 LogsQL 쿼리 가능.

등록 방법

두 단계로 구성:

  1. 플러그인 설치 — vm-stack helm values의 grafana.pluginsvictoriametrics-logs-datasource 추가하고 helm upgrade vm-stack. Grafana 시작 시 자동 다운로드/설치 (현재 v0.26.3).

  2. datasource 등록grafana.additionalDataSources는 vm-stack chart 구조상 sub-chart로 전달이 안 되므로 무시됨. 대신 sidecar ConfigMap 패턴 사용:

apiVersion: v1
kind: ConfigMap
metadata:
  name: vlogs-grafana-datasource
  namespace: monitoring
  labels:
    grafana_datasource: "1"   # ← grafana-sc-datasources sidecar가 자동 발견
data:
  vlogs.yaml: |
    apiVersion: 1
    datasources:
      - name: VictoriaLogs
        type: victoriametrics-logs-datasource
        access: proxy
        url: http://vlogs-victoria-logs-single-server.logging.svc.cluster.local:9428
        isDefault: false
        editable: true

kubectl apply -f 한 번이면 sidecar가 즉시 picks up하고 grafana가 hot reload (Writing /etc/grafana/provisioning/datasources/vlogs.yaml).

주의

  • Grafana PVC가 ReadWriteOnce이므로 helm upgrade 시 새 pod이 다른 노드에 스케줄되면 Multi-Attach error → 기존 pod 수동 삭제 필요. (또는 Grafana Deployment의 strategy를 Recreate로 변경)
  • helm values의 grafana.additionalDataSources는 무시되지만 plugin 설치는 작동하므로, plugin 라인은 helm values에 두는 게 맞음.

LogsQL 쿼리 예시

# 모든 APISIX 로그
program:apisix

# 5xx 에러만
program:apisix status:>=500

# 특정 path
program:apisix path:/apisix/admin/routes

# 느린 요청 (1초 이상)
program:apisix request_time:>1.0

# 특정 클라이언트 외부 IP (real_ip 적용 후 진짜 IP)
program:apisix remote_addr:211.211.28.97

# 특정 호스트
program:apisix host:juiceshop.keepanker.cv

# 특정 호스트의 4xx/5xx
program:apisix host:juiceshop.keepanker.cv status:>=400

# 특정 노드 pod
program:apisix _stream:{kubernetes.pod_name="apisix-f5764d796-kdj2x"}

[!info] 진짜 IP 추적 2026-04-08 apisix#real_ip 설정 (2026-04-08 patch 반영) 이후 remote_addr에 BunnyCDN edge가 전달한 진짜 외부 IP가 찍힘. xff/xrip 필드로 X-Forwarded-For/X-Real-IP 헤더 원본도 보존. 그 이전 로그는 K3s pod CIDR(10.42.x.x)만 찍혀 있음.

[!warning] parse_apisix 정규식과 APISIX log format은 짝 APISIX의 access_log_format을 바꾸면 vector helm values의 parse_apisix 정규식도 같이 업데이트해야 함. 안 그러면 매치 실패해서 log_type=raw로 떨어지고 구조화 필드(method/status/path 등) 추출이 안 됨.

UI에서 직접 쿼리하거나 HTTP API:

curl -s "https://vl.inouter.com/select/logsql/query?query=program:apisix+status:>=500&limit=20"

운영 명령

# 메트릭 (ingest 통계)
curl -s https://vl.inouter.com/metrics | grep vl_rows_ingested_total

# 디스크 사용량
kubectl exec -n logging vlogs-victoria-logs-single-server-0 -- du -sh /storage

# Vector 상태
kubectl logs -n logging -l app.kubernetes.io/name=vector --tail=50

# Vector configmap 직접 보기
kubectl get cm vector -n logging -o jsonpath='{.data.vector\.yaml}'

향후 작업

  • Grafana data source 추가 (2026-04-08 완료, 위 "Grafana 통합" 섹션 참조)
  • CrowdSec와 통합 (APISIX 로그 → CrowdSec 시나리오)
  • AI 분석 컴포넌트 (CronJob 또는 streaming, 새 공격 패턴 자동 차단 룰 생성)
  • Traefik 로그도 VL로 동시 sink (현재는 CrowdSec only)