Add VictoriaMetrics observability stack + sync catalog for monitoring test
- VM stack 10 charts: victoria-metrics-cluster/auth, victoria-logs-cluster, victoria-metrics-agent/alert, opentelemetry-collector, kube-state-metrics, prometheus-node-exporter, alertmanager, perses (JWT/OIDC, Infisical-ready) - ArgoCD ApplicationSet (syncWave) + per-chart dip-values overlays - doc/victoria-metrics-architecture.md, define-chart-resources updates - includes pending working-tree changes (mlflow, kubeflow, apisix, CLAUDE.md) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,324 @@
|
||||
# VictoriaMetrics 옵저버빌리티 스택 아키텍처
|
||||
|
||||
dip-catalog가 배포하는 **VictoriaMetrics 기반 옵저버빌리티 스택**(메트릭·로그 + 시각화·알림)의 구성, 데이터 흐름, 멀티테넌시, 인증을 정리한 문서다.
|
||||
|
||||
## 1. 개요
|
||||
|
||||
- **목적**: Grafana 계열(AGPLv3)을 대체하는 **Apache 2.0 기반** 옵저버빌리티 스택.
|
||||
- **구성**: 카탈로그에 등록된 **10개 Helm 차트**. 메트릭(VictoriaMetrics), 로그(VictoriaLogs), 수집(vmagent/OpenTelemetry Collector), 알림(vmalert/Alertmanager), 시각화(Perses).
|
||||
- **인증 전제**: 배포 환경에 항상 존재하는 **Keycloak `paasup` realm** 기반 JWT/OIDC. vmauth가 토큰을 검증하고 테넌트별로 라우팅한다.
|
||||
- **네임스페이스**: `monitoring` (전 컴포넌트 공통).
|
||||
- **범위**: 메트릭·로그 파이프라인. 분산 트레이싱은 본 스택 범위에 포함하지 않는다.
|
||||
|
||||
## 2. 전체 아키텍처
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph collect[수집]
|
||||
NE[node-exporter]
|
||||
KSM[kube-state-metrics]
|
||||
VMA[vmagent]
|
||||
OTC[otelcol DaemonSet]
|
||||
OTE[otelcol-events]
|
||||
end
|
||||
subgraph store[저장]
|
||||
VMC[(vmcluster<br/>vminsert/vmselect/vmstorage)]
|
||||
VL[(vlogs<br/>vlinsert/vlstorage/vlselect)]
|
||||
end
|
||||
subgraph access[인증·조회]
|
||||
VAUTH[vmauth :8427<br/>JWT/OIDC]
|
||||
end
|
||||
subgraph consume[시각화·알림]
|
||||
PERSES[Perses]
|
||||
VMALERT[vmalert]
|
||||
AM[Alertmanager]
|
||||
end
|
||||
KC[(Keycloak<br/>paasup realm)]
|
||||
|
||||
NE -->|scrape| VMA
|
||||
KSM -->|scrape| VMA
|
||||
VMA -->|remote_write| VMC
|
||||
OTC -->|logs| VL
|
||||
OTE -->|events| VL
|
||||
|
||||
PERSES -->|client_credentials| VAUTH
|
||||
VAUTH -->|/select metrics| VMC
|
||||
VAUTH -->|logs / AccountID hdr| VL
|
||||
VMALERT -->|query multitenant| VMC
|
||||
VMALERT -->|alerts| AM
|
||||
AM -->|webhook| DISCORD[(Discord)]
|
||||
|
||||
KC -. OIDC 로그인 .-> PERSES
|
||||
KC -. JWT 검증 .-> VAUTH
|
||||
```
|
||||
|
||||
## 3. 컴포넌트 목록
|
||||
|
||||
| 컴포넌트 | 차트/버전 | 역할 | 포트 |
|
||||
|---|---|---|---|
|
||||
| vmcluster | victoria-metrics-cluster/0.43.0 | 메트릭 저장 (vminsert/vmselect/vmstorage) | 8480 / 8481 / 8482 |
|
||||
| vmauth | victoria-metrics-auth/0.33.0 | 인증·라우팅 프록시 (JWT/OIDC) | 8427 |
|
||||
| vlogs | victoria-logs-cluster/0.1.5 | 로그 저장 (vlinsert/vlstorage/vlselect) | 9481 / 9491 / 9471 |
|
||||
| vmagent | victoria-metrics-agent/0.40.0 | 메트릭 스크레이프 → vminsert | - |
|
||||
| vmalert | victoria-metrics-alert/0.41.0 | 알림 규칙 평가 | 8880 |
|
||||
| otelcol | opentelemetry-collector/0.156.2 (DaemonSet) | 파드 로그 수집 | - |
|
||||
| otelcol-events | opentelemetry-collector/0.156.2 (Deployment) | K8s 이벤트 수집 | - |
|
||||
| kube-state-metrics | kube-state-metrics/7.4.0 | K8s 오브젝트 메트릭 | 8080 |
|
||||
| node-exporter | prometheus-node-exporter/4.55.0 | 노드 시스템 메트릭 | 9100 |
|
||||
| alertmanager | alertmanager/1.37.0 | 알림 라우팅·발송 | 9093 |
|
||||
| perses | perses/0.21.0 | 대시보드/시각화 | 8080 |
|
||||
|
||||
각 컴포넌트의 상세 설정은 차트별 `CUSTOM-README.md` 참조(11장 링크).
|
||||
|
||||
## 4. 데이터 플로우
|
||||
|
||||
### 4.1 메트릭
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
NE[node-exporter] --> VMA[vmagent]
|
||||
KSM[kube-state-metrics] --> VMA
|
||||
KUBELET[kubelet/cadvisor] --> VMA
|
||||
PODS[pod annotations] --> VMA
|
||||
VMA -->|"/insert/{accountID}/prometheus"| VMI[vminsert :8480]
|
||||
VMI --> VMS[(vmstorage :8482)]
|
||||
CLIENT[사용자/Grafana] -->|"Bearer JWT"| VAUTH[vmauth :8427]
|
||||
PERSES[Perses] -->|"SA 토큰"| VAUTH
|
||||
VAUTH -->|"/select/{accountID}/prometheus"| VSEL[vmselect :8481]
|
||||
VMALERT[vmalert] -->|"/select/multitenant/"| VSEL
|
||||
VSEL --> VMS
|
||||
```
|
||||
|
||||
- **쓰기**: vmagent가 `/insert/{accountID}/prometheus/api/v1/write`로 직접 vminsert에 기록(vmauth 미경유).
|
||||
- **조회**: vmauth가 JWT `vm_access.metrics_account_id`로 `/select/{accountID}/`에 라우팅.
|
||||
- **vmalert**: 내부 서비스로 vmselect multitenant 엔드포인트 직결.
|
||||
|
||||
### 4.2 로그
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
PODLOG[파드 로그] --> OTC[otelcol DaemonSet]
|
||||
EVENTS[K8s 이벤트] --> OTE[otelcol-events]
|
||||
OTC -->|"VictoriaLogs-AccountID 헤더"| VLI[vlinsert :9481]
|
||||
OTE -->|"AccountID 0"| VLI
|
||||
VLI --> VLS[(vlstorage :9491)]
|
||||
PERSES[Perses] -->|"SA 토큰"| VAUTH[vmauth :8427]
|
||||
VAUTH -->|"AccountID 헤더 + /select/logsql/"| VLSEL[vlselect :9471]
|
||||
VLSEL --> VLS
|
||||
```
|
||||
|
||||
- **쓰기**: otelcol이 namespace 기준으로 필터해 `VictoriaLogs-AccountID` 헤더(0/1/2)로 테넌트별 기록.
|
||||
- **조회**: vmauth가 `AccountID` 헤더를 주입해 vlselect로 전달.
|
||||
|
||||
## 5. 멀티테넌시
|
||||
|
||||
vm과 vl은 **격리 메커니즘이 다르지만 단일 토큰으로 처리**된다. 토큰의 `vm_access` 클레임이 두 차원을 함께 담는다.
|
||||
|
||||
| 시그널 | 격리 방식 | vmauth 라우팅 | vm_access 필드 |
|
||||
|---|---|---|---|
|
||||
| 메트릭 | URL **경로** `/select/{accountID}/prometheus` | url_prefix 경로 치환 `{{.MetricsAccountID}}` | `metrics_account_id` |
|
||||
| 로그 | HTTP **헤더** `AccountID` / `ProjectID` | 헤더 주입 `AccountID: {{.LogsAccountID}}` | `logs_account_id` |
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
T["JWT vm_access<br/>{metrics_account_id:1, logs_account_id:1}"]
|
||||
T --> M["메트릭: /select/1/prometheus"]
|
||||
T --> L["로그: vlselect + AccountID: 1"]
|
||||
```
|
||||
|
||||
> **비대칭**: 메트릭은 `/select/multitenant/`로 전체 테넌트 집계가 가능하나, VictoriaLogs는 합산 엔드포인트가 없어 `(AccountID, ProjectID)` 단위로만 조회된다.
|
||||
|
||||
## 6. 인증/인가 (Keycloak `paasup` realm)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as 사용자/SA
|
||||
participant KC as Keycloak (paasup)
|
||||
participant VA as vmauth
|
||||
participant VM as vmselect/vlselect
|
||||
U->>KC: 인증 (OIDC / client_credentials)
|
||||
KC-->>U: JWT (vm_access 클레임)
|
||||
U->>VA: 요청 + Bearer JWT
|
||||
VA->>KC: OIDC Discovery 공개키 fetch (최초 1회·rotate)
|
||||
VA->>VA: 서명 검증 + vm_access 파싱
|
||||
VA->>VM: accountID 기준 라우팅 (경로/헤더)
|
||||
VM-->>U: 결과
|
||||
```
|
||||
|
||||
- **Client Scope `vm-access`**: User Attribute 매퍼 2종 → `vm_access.metrics_account_id` / `vm_access.logs_account_id` (점 표기 중첩 JSON).
|
||||
- **Clients**: `perses`(UI 로그인), `perses-vmauth`(datasource service-account, client_credentials), `vmauth-client`(선택, 직접 API).
|
||||
- **vmauth**: `config.users[].jwt.oidc.issuer = https://keycloak.example.org/realms/paasup`.
|
||||
- **테넌트 온보딩**: Keycloak Group + user attribute만 추가 → **재배포 불필요**.
|
||||
- **Perses 권한**: OIDC groups 자동 동기화 미지원 → Perses 자체 RBAC(Project별 Role/RoleBinding, subject = Keycloak UUID) 수동 관리.
|
||||
|
||||
상세 절차: [victoria-metrics-auth CUSTOM-README](../manifests/helm/victoria-metrics-auth/0.33.0/CUSTOM-README.md) 3장.
|
||||
|
||||
## 7. 시각화 (Perses)
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
USER[사용자] -->|OIDC 로그인| PERSES[Perses :8080]
|
||||
subgraph prov[사이드카 프로비저닝]
|
||||
DASH[대시보드 5종]
|
||||
DS[데이터소스 3종]
|
||||
end
|
||||
PERSES --- prov
|
||||
DS -->|client_credentials 토큰| VAUTH[vmauth :8427]
|
||||
VAUTH --> VSEL[vmselect]
|
||||
VAUTH --> VLSEL[vlselect]
|
||||
```
|
||||
|
||||
- **로그인**: Keycloak OIDC(`config.security.authentication`).
|
||||
- **데이터소스**: `victoriametrics`(Prometheus 호환)·`victorialogs`(LogsQL)가 vmauth를 경유하며, HTTPProxy `secret`으로 **client_credentials 토큰** 사용.
|
||||
- **프로비저닝**: `perses.dev/resource: "true"` ConfigMap을 사이드카가 자동 로드. 대시보드 4종(k8s-node-overview, k8s-workloads, k8s-pod-diagnostics, k8s-pod-history).
|
||||
|
||||
소스: [perses/0.21.0/files/perses-provisioning.yaml](../manifests/helm/perses/0.21.0/files/perses-provisioning.yaml)
|
||||
|
||||
## 8. 알림
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
VSEL[vmselect multitenant] --> VMALERT[vmalert]
|
||||
VMALERT -->|"ALERTS 메트릭 /insert/0/"| VMI[vminsert]
|
||||
VMALERT -->|"알림 발생"| AM[Alertmanager :9093]
|
||||
AM -->|webhook_url_file| DISCORD[(Discord)]
|
||||
```
|
||||
|
||||
- **규칙**: 클러스터 헬스 8종(NodeDown, NodeHighCPU, NodeHighMemory, NodeDiskPressure, PodCrashLooping, PodNotReady, DeploymentReplicasMismatch, PVCFillingUp), 평가 30s.
|
||||
- **Alertmanager**: `[alertname, severity]` 그룹핑, critical→warning inhibit, Discord webhook(Secret 마운트).
|
||||
|
||||
## 9. 의존 관계
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
vmcluster
|
||||
vlogs
|
||||
vmauth --> vmcluster
|
||||
vmauth --> vlogs
|
||||
vmagent --> vmcluster
|
||||
kube-state-metrics -.scraped by.-> vmagent
|
||||
node-exporter -.scraped by.-> vmagent
|
||||
otelcol --> vlogs
|
||||
otelcol-events --> vlogs
|
||||
vmalert --> vmcluster
|
||||
vmalert --> alertmanager
|
||||
perses --> vmauth
|
||||
vmauth -.JWT.-> Keycloak[(Keycloak paasup)]
|
||||
perses -.OIDC.-> Keycloak
|
||||
```
|
||||
|
||||
**배포 순서**: vmcluster → vmauth → vlogs → kube-state-metrics/node-exporter → vmagent → otelcol(+events) → alertmanager → vmalert → perses. (Keycloak `vm-access` scope·Client는 perses/vmauth 설치 전에 생성)
|
||||
|
||||
## 10. 스토리지·리소스
|
||||
|
||||
| 컴포넌트 | PVC | 보존기간 |
|
||||
|---|---|---|
|
||||
| vmstorage | 10Gi (longhorn) | 메트릭 1개월 |
|
||||
| vlstorage | 5Gi | 로그 7일 |
|
||||
| perses | 1Gi | 대시보드 영속 |
|
||||
| alertmanager | 비활성(기본) | - |
|
||||
|
||||
리소스 티어(Small/Medium/Large)는 [doc/define-chart-resources.md](define-chart-resources.md) 43~52번 항목 참조.
|
||||
|
||||
## 11. 참고 (차트별 가이드)
|
||||
|
||||
| 컴포넌트 | CUSTOM-README |
|
||||
|---|---|
|
||||
| vmcluster | [link](../manifests/helm/victoria-metrics-cluster/0.43.0/CUSTOM-README.md) |
|
||||
| vmauth | [link](../manifests/helm/victoria-metrics-auth/0.33.0/CUSTOM-README.md) |
|
||||
| vlogs | [link](../manifests/helm/victoria-logs-cluster/0.1.5/CUSTOM-README.md) |
|
||||
| vmagent | [link](../manifests/helm/victoria-metrics-agent/0.40.0/CUSTOM-README.md) |
|
||||
| vmalert | [link](../manifests/helm/victoria-metrics-alert/0.41.0/CUSTOM-README.md) |
|
||||
| opentelemetry-collector | [link](../manifests/helm/opentelemetry-collector/0.156.2/CUSTOM-README.md) |
|
||||
| kube-state-metrics | [link](../manifests/helm/kube-state-metrics/7.4.0/CUSTOM-README.md) |
|
||||
| prometheus-node-exporter | [link](../manifests/helm/prometheus-node-exporter/4.55.0/CUSTOM-README.md) |
|
||||
| alertmanager | [link](../manifests/helm/alertmanager/1.37.0/CUSTOM-README.md) |
|
||||
| perses | [link](../manifests/helm/perses/0.21.0/CUSTOM-README.md) |
|
||||
|
||||
## 12. 배포 아키텍처 (ArgoCD + dip-console)
|
||||
|
||||
### 12.1 배포 모델
|
||||
|
||||
GitOps 기반. 역할을 4개로 분리한다.
|
||||
|
||||
| 구성요소 | 역할 |
|
||||
|---|---|
|
||||
| **카탈로그 repo** (`dip-catalog`) | Helm 차트 + `dip-values.yaml`(템플릿) + 정적 대시보드 매니페스트 |
|
||||
| **값 repo** (`dip/values-*`) | 환경별 값 파일(`$values/...`로 참조), `{{ .Domain }}`·`$VAR` 치환 |
|
||||
| **ArgoCD ApplicationSet** | 10개 차트를 syncWave 순서로 선언적 배포(이중 소스) |
|
||||
| **dip-console** | 클러스터 외부/차트 밖 리소스 오케스트레이션 — Keycloak 인증, Infisical 시크릿, 테넌트 프로젝트 |
|
||||
|
||||
### 12.2 책임 분담
|
||||
|
||||
| 영역 | 담당 | 방식 |
|
||||
|---|---|---|
|
||||
| 인증 (Keycloak `paasup`) | **dip-console** | `vm-access` scope·`perses`/`perses-vmauth` client·테넌트 그룹/attribute를 Admin API로 생성 |
|
||||
| 시크릿 | **dip-console + Infisical** | Infisical 등록 → external-secrets가 `monitoring` ns Secret 동기화 → 차트는 `existingSecret` 참조 |
|
||||
| root-ca-cert | **dip-console** | platform ns → `monitoring` 복사 |
|
||||
| 테넌트 relabel (`vmagent-relabel-configs`) | **dip-console** | 테넌트(demo01/demo02/platform) 추가·수정 |
|
||||
| 대시보드 ConfigMap | **카탈로그/ArgoCD** | 정적 → ArgoCD 경로 소스로 적용(사이드카 로드) |
|
||||
| StorageClass / Ingress / cert-manager | **플랫폼 기본 배포** | 전제(longhorn, ingress controller, root-ca-issuer) |
|
||||
| 알림 채널 | **dip-console (교체 가능)** | discord/email/slack 교체 — 12.5 |
|
||||
|
||||
### 12.3 ApplicationSet + syncWave
|
||||
|
||||
openmetadata ApplicationSet 패턴(list generator + 이중 소스 `$values/` + `argocd.argoproj.io/sync-wave`)을 재사용한다.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph w0[syncWave 0 · 무의존]
|
||||
VMC[vmcluster]
|
||||
VL[vlogs]
|
||||
KSM[kube-state-metrics]
|
||||
NE[node-exporter]
|
||||
AM[alertmanager]
|
||||
end
|
||||
subgraph w1[syncWave 1 · 저장소·AM 의존]
|
||||
VAUTH[vmauth]
|
||||
VMA[vmagent]
|
||||
OTC[otelcol]
|
||||
OTE[otelcol-events]
|
||||
VMALERT[vmalert]
|
||||
end
|
||||
subgraph w2[syncWave 2 · vmauth 의존]
|
||||
PERSES[perses]
|
||||
end
|
||||
w0 --> w1 --> w2
|
||||
```
|
||||
|
||||
배포 소스: 카탈로그 repo(`{{ .chartPath }}`) + 값 repo(`$values/{{ .valuesPath }}`). `syncPolicy.automated{prune,selfHeal}` + `CreateNamespace=true`. 네임스페이스 `monitoring` 고정.
|
||||
|
||||
### 12.4 시크릿 흐름
|
||||
|
||||
차트는 인라인 시크릿을 두지 않고 `existingSecret`만 참조한다. 실제 값은 dip-console → Infisical → external-secrets 경로로 채워진다.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
CONSOLE[dip-console] -->|등록| INF[(Infisical)]
|
||||
INF -->|sync| ES[external-secrets]
|
||||
ES -->|K8s Secret 생성| NS[monitoring ns Secret]
|
||||
NS -->|existingSecret 참조| CHART[alertmanager / perses / ...]
|
||||
```
|
||||
|
||||
대상: alertmanager 알림 자격증명, perses OIDC `client_secret`·`secret_key`(`secret.create=false`/`envVarsExternalSecretName`), perses-vmauth OAuth secret, root-ca-cert(dip-console 복사).
|
||||
|
||||
### 12.5 알림 채널 교체 가능 구조
|
||||
|
||||
Alertmanager `config.receivers`는 채널 무관하게 작성하고, 자격증명은 Infisical 시크릿을 파일로 마운트한다(평문 금지).
|
||||
|
||||
| 채널 | receiver 키 | 자격증명(파일 마운트) |
|
||||
|---|---|---|
|
||||
| Discord | `discord_configs.webhook_url_file` | webhook URL |
|
||||
| Slack | `slack_configs.api_url_file` | webhook URL |
|
||||
| Email | `email_configs`(smarthost/from/to) | `auth_password_file` |
|
||||
|
||||
**새 채널 추가 3단계**: ① Infisical에 자격증명 등록 → ② dip-values의 `config.receivers`(+ `extraSecretMounts`) 추가, `route.receiver` 지정 → ③ ArgoCD 재동기화. (상세 예시: [alertmanager CUSTOM-README](../manifests/helm/alertmanager/1.37.0/CUSTOM-README.md))
|
||||
|
||||
### 12.6 사전 준비 체크리스트
|
||||
|
||||
ArgoCD 동기화 전에 갖춰져야 하는 항목.
|
||||
|
||||
- **dip-console**: Keycloak `vm-access` scope·client 생성 / Infisical 시크릿 등록 / `root-ca-cert` 복사 / `vmagent-relabel-configs` 테넌트 ConfigMap 생성
|
||||
- **플랫폼 기본**: 기본 StorageClass(longhorn), Ingress controller + cert-manager(`root-ca-issuer`), DNS
|
||||
- **GitOps**: ArgoCD에 카탈로그 repo·값 repo 등록(자격증명), 값 repo에 `dip-values` 작성
|
||||
- 누락 시 실패 지점: perses/vmauth(Keycloak·시크릿 미비), vmagent(relabel ConfigMap 미비), PVC(StorageClass 미비)
|
||||
Reference in New Issue
Block a user