8.4 KiB
date, topic, areas, tags
| date | topic | areas | tags | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2026-04-23 | Netbis NPM 6대 → VictoriaLogs 로그 수집 파이프라인 구축 (zlambda Vector 중계) |
|
|
배경 / 결정
Netbis 오리진 6대(NPM, Linode Tokyo public)의 nginx access/error log를 사내 VictoriaLogs(vl.inouter.com)로 수집. 목적: 향후 CrowdSec 파싱/anomaly-detect 연동 + 요청 패턴 모니터링.
핵심 제약: vl.inouter.com의 public DNS가 LAN IP(192.168.9.53)으로만 해석되어 public NPM들이 직접 도달 불가. 해결로 zlambda(Tailscale 100.78.51.18 / public 139.162.71.52) 를 Vector HTTP 중계 로 투입.
선택지 검토:
- (A) 6대에 Tailscale 설치 — 방침상 탈락 (설치 불가)
- (B) zlambda Vector 중계 — 선택 (기존 NixOS 플레이크에 모듈 추가)
- (C) VL public 엔드포인트 노출 — 공격면 확대 우려 탈락
최종 구조
┌────────── public internet ──────────┐ ┌── tailnet ──┐
NPM-1..6 (Linode Tokyo) │ │ │
Vector 0.55 (host, file source) │ │ │
http sink POST:9999 (basic auth) ├─► zlambda Vector-relay 0.45 ─► vl.inouter.com
│ HTTP server bearer=basic │ (K3s Traefik → vlogs svc)
│ ES bulk sink │
└─────────────────────────────┘
- NPM Vector: 호스트-레벨.
/etc/vector/vector.yaml(mode 600, bearer 평문),vector.service - 중계: zlambda
vector-relay컨테이너 (NixOS oci-container, docker networkvector-net) - VL ingest:
https://vl.inouter.com/insert/elasticsearch(Tailscale로 LAN 도달, Traefik TLS)
구현
1. zlambda vector.nix 모듈
~/nixos-infra/vector.nix 신규 작성. 요점:
virtualisation.oci-containers.containers.vector-relay—docker.io/timberio/vector:0.45.0-debian,--network=vector-net,ports=[9999:9999]systemd.services.vector-relay-render-configoneshot —/var/lib/vector-relay/vector.yaml템플릿 렌더 (env interpolation${VECTOR_BEARER_TOKEN})systemd.services.vector-relay-envoneshot — agenix 복호 결과(/run/agenix/vector-bearer-token) 를/run/vector-relay/env로 이동 후 container에environmentFiles주입systemd.services.init-vector-netoneshot — docker network 생성age.secrets.vector-bearer-token.file = ./secrets/vector-bearer-token.age(상대경로, pure eval 호환)
Vector 컨테이너 config:
sources.http_npm: { type: http_server, address: 0.0.0.0:9999, encoding: ndjson,
auth: { strategy: basic, username: npm-relay, password: "${VECTOR_BEARER_TOKEN}" } }
transforms.tag_relay: { type: remap, source: | .relay = "zlambda" }
sinks.vlogs: { type: elasticsearch, endpoints: [https://vl.inouter.com/insert/elasticsearch],
mode: bulk, healthcheck.enabled: false, query._stream_fields: [host, service, log_type] }
2. agenix bearer token
# 64자 URL-safe base64 난수 생성 후 age 로 2 recipient 암호화
age -r "<kaffa user ed25519>" -r "<zlambda host ed25519>" \
-o secrets/vector-bearer-token.age < bearer.secret
secrets/secrets.nix 에 "vector-bearer-token.age".publicKeys = allUsers ++ allHosts; 추가.
3. flake/config 배선
configuration.niximports에./vector.nix추가configuration.nixusers.users.root.openssh.authorizedKeys.keys에 heimdallops-agents@kaffaed25519 공개키 추가 (runtime 임시 등록을 flake 영속화)git add vector.nix secrets/vector-bearer-token.age secrets/secrets.nix configuration.nixnixos-rebuild switch --flake .#zlambda
4. Linode 방화벽 (zlambda id 691875)
allow-npm-relay-9999:
protocol TCP, ports 9999, action ACCEPT
addresses.ipv4: [172.104.100.11/32, 139.162.114.197/32, 139.162.73.17/32,
139.162.73.240/32, 172.104.70.137/32, 172.105.226.218/32]
기존 rules(SSH, CF HTTP/HTTPS, Tailscale UDP 41641, ICMP) 보존. inbound_policy=DROP 유지.
5. NPM 6대 Vector 설치
setup.vector.dev (공식 sh 스크립트)로 /usr/local/bin/vector 0.55 설치. systemd unit 생성 후 enable+start.
각 호스트 /etc/vector/vector.yaml (mode 600):
- sources.npm_access / npm_error: file tail
- NPM-1..5:
/root/data/logs/proxy-host-*_access.log등 - NPM-6:
/home/kaffa/npm/data/log/...(다른 install)
- NPM-1..5:
- transforms.parse_npm_access / parse_npm_error: remap (VRL)
- NPM proxy log_format 정규식 파싱 → ip/method/path/status/bytes/domain/upstream/UA/referer 구조화
- 실패 시 NPM standard log_format 재시도, 그래도 실패하면
log_format="raw" - 공통 필드:
.service="npm",.host="<label>",.zone="<served zones csv>",.log_type=access|error - 파일명에서
proxy_host_id추출
- sinks.relay:
type: http,uri: http://139.162.71.52:9999/,auth.strategy: basic (user=npm-relay, password=<bearer>),encoding.codec: json,framing.method: newline_delimited,batch: {max_events:100, timeout_secs:5},healthcheck.enabled: false
6. 호스트별 라벨
| Host | Public IP | 로그 경로 | zone 라벨 |
|---|---|---|---|
| npm-1 | 172.104.100.11 | /root/data/logs | shared |
| npm-2 | 139.162.114.197 | /root/data/logs | psd777.com |
| npm-3 | 139.162.73.17 | /root/data/logs | rss-555.com,rss-7790.com |
| npm-4 | 139.162.73.240 | /root/data/logs | fall-vip.com,fall-mvp.com,fall-vip7.com |
| npm-5 | 172.104.70.137 | /root/data/logs | shared |
| npm-6 | 172.105.226.218 | /home/kaffa/npm/data/log | shared |
검증
각 NPM에서 합성 로그 주입 후 https://vl.inouter.com/select/logsql/query?query=service:npm host:"<host>" 로 확인:
npm-1 rows>=9 (probe + 실 요청)
npm-2 rows=1000 (cap, 실 트래픽 다수)
npm-3 rows=1000
npm-4 rows=1000
npm-5 rows>=1 (probe, 조용한 호스트)
npm-6 rows>=1 (probe)
VL 문서에서 확인된 필드 샘플(npm-1 sythetic):
{"host":"npm-1","service":"npm","zone":"shared","log_type":"access","log_format":"proxy","relay":"zlambda",
"domain":"h.test","ip":"127.0.0.1","method":"GET","path":"/debug-test","status":"200",
"upstream_cache_status":"-","upstream_status":"200","user_agent":"heimdall-debug-v","referer":"-","bytes":"0",
"proxy_host_id":null,"file":"/root/data/logs/fallback_access.log"}
운영 주의
- NPM 측 bearer 평문:
/etc/vector/vector.yaml내부. 호스트 compromised 시 노출 → zlambda 방화벽 IP allowlist + basic auth 2중 방어. 노출 탐지 시 agenix 재발급 + 재배포 - zlambda 측 호환성:
vector 0.45의 http_server source는auth.strategy: basic만 지원.bearerstrategy 미지원이라 basic + fixed user(npm-relay) 로 구현. 기능적 차이 없음 - Vector http sink 그레이스풀 종료 지연: 오래된 elasticsearch sink(이전 config)를
systemctl restart vector할 때 inflight retry로 최대 60초 대기. 빠른 재기동 필요 시systemctl kill -s SIGKILL vector && systemctl reset-failed vector && systemctl start vector - VL endpoint TLS:
http://vl.inouter.com/insert/elasticsearch는 404 반환(Traefik HTTPS-only routing). 반드시https:// - checkpoint 위치:
/var/lib/vector/npm_{access,error}/checkpoints.json. 로그 재수집이 필요하면 해당 파일 삭제 후 vector 재시작
영향 및 롤백
- NPM 부하: Vector agent ~20MB RSS, negligible
- zlambda 부하: 중계 컨테이너 ~30MB, 6 NPM 집계 트래픽 ≪ 기존 APISIX DR
- VL 스토리지: index
npm-netbis, 초당 수십 건 수준 예상 - 롤백:
- 각 NPM
systemctl disable --now vector+apt purge(or/usr/local/bin/vector삭제 + unit 제거) - zlambda
configuration.niximports 에서./vector.nix제거 +nixos-rebuild switch - Linode 방화벽
allow-npm-relay-9999rule 삭제 - agenix
secrets/vector-bearer-token.age제거
- 각 NPM
관련 문서
- ../services/netbis — NPM 구성, 라우트, CrowdSec 연동
- ../infra/platform/victorialogs — VL 구조 + LogsQL
- ../infra/security/crowdsec-safeline — 기존 로그 파이프라인(APISIX, SafeLine)