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:
wbsong111
2026-06-25 11:10:51 +09:00
parent a55427730e
commit 6290322f1b
514 changed files with 68103 additions and 40 deletions
@@ -0,0 +1,119 @@
# Perses 배포 (Keycloak OIDC 로그인 + 대시보드 프로비저닝)
Perses는 Apache 2.0 라이선스의 대시보드/시각화 플랫폼이다(Grafana AGPLv3 대체). Keycloak OIDC로 로그인하고, VictoriaMetrics·VictoriaLogs를 데이터소스로 사용한다.
## 1. 배포 방법
### 사전 준비
> Keycloak 리소스는 배포 환경에 **항상 존재하는 `paasup` realm**에 생성한다 (realm 신규 생성 금지). issuer: `https://keycloak.example.org/realms/paasup`.
1. **Client `perses`** 생성 (confidential, Valid Redirect URIs: `https://perses.example.org/api/auth/providers/oidc/keycloak/callback`)
2. **datasource용 service-account Client `perses-vmauth`** 생성 (client_credentials 활성화, `vm-access` Client Scope 연결 → `vm_access` 클레임으로 플랫폼 조회 권한). vmauth `CUSTOM-README.md` 3장 참조.
3. (사내 CA 사용 시) Keycloak TLS CA Secret 생성
```sh
kubectl create secret generic root-ca-cert -n monitoring --from-file=ca.crt=./ca.crt
```
```sh
helm upgrade perses ./ -f custom-values.yaml --install -n monitoring
```
## 2. custom-values.yaml 설정 설명
### 2.1 OIDC 로그인 (`config.security`)
`enable_auth: true` + Keycloak OIDC provider. `enable_native: true`로 네이티브 로그인도 병행 가능하다.
### 2.2 secret_key (쿠키 서명 키)
미설정 시 파드 재시작마다 랜덤 생성되어 OIDC state 쿠키가 무효화된다. **운영에서는 Secret으로 고정**한다(`custom-values.yaml`의 `PERSES_SECURITY_ENCRYPTION_KEY` 주석 참조).
### 2.3 SSL_CERT_FILE
사내 CA로 서명된 Keycloak을 신뢰하도록 `/ca/ca.crt`를 마운트하고 환경변수로 지정한다.
### 2.4 사이드카 프로비저닝
`sidecar.enabled: true`이면 `perses.dev/resource: "true"` 라벨이 붙은 ConfigMap을 자동 로드한다. 대시보드·데이터소스·프로젝트가 이 방식으로 등록된다(아래 4장).
## 3. 권한 관리 (Perses RBAC)
> ⚠️ **Perses v0.53.1은 OIDC groups claim 자동 동기화를 지원하지 않는다.** 로그인 시 Keycloak `sub`(UUID)가 Perses User의 `name`이 된다.
따라서 권한은 Perses 자체 RBAC로 관리한다.
- **Role** (Project별): `owner`(`actions:[*]`), `editor`(Dashboard/Datasource/Folder/Secret/Variable 전체 + Project/Role/RoleBinding read), `viewer`(read-only)
- **RoleBinding**: `subject = {kind: User, name: <Keycloak UUID>}`
그룹 멤버 → RoleBinding 매핑은 자동이 아니므로, **운영자가 온보딩 시점에 직접** Keycloak UUID를 조회해 RoleBinding을 생성한다(또는 CronJob으로 자동화 — 참고 구현: vm-stack `install/14-onboard-project.sh`). 별도 스크립트는 카탈로그에 포함하지 않는다.
### 온보딩 절차 (테넌트마다, Perses REST API)
```sh
PERSES=https://perses.example.org
KC=https://keycloak.example.org
# Keycloak 관리자 토큰 → UUID 조회 (sub == Perses User name)
KTOKEN=$(curl -s -X POST "$KC/realms/master/protocol/openid-connect/token" \
-d grant_type=password -d client_id=admin-cli -d username=admin -d password="$KC_ADMIN_PW" | jq -r .access_token)
UID=$(curl -s "$KC/admin/realms/paasup/users?username=alice" -H "Authorization: Bearer $KTOKEN" | jq -r '.[0].id')
# 1) Project 생성 (이미 사이드카로 생성됐다면 생략)
curl -s -X POST "$PERSES/api/v1/projects" -H 'Content-Type: application/json' \
-d '{"kind":"Project","metadata":{"name":"tenant-demo01"}}'
# 2) editor RoleBinding (subject = Keycloak UUID)
curl -s -X POST "$PERSES/api/v1/projects/tenant-demo01/rolebindings" \
-H 'Content-Type: application/json' -d "{
\"kind\":\"RoleBinding\",
\"metadata\":{\"name\":\"editors\",\"project\":\"tenant-demo01\"},
\"spec\":{\"role\":\"editor\",\"subjects\":[{\"kind\":\"User\",\"name\":\"$UID\"}]}
}"
```
> Role(`owner`/`editor`/`viewer`)은 Project 생성 시 1회만 정의하면 재사용된다(`/api/v1/projects/<p>/roles`).
## 4. 대시보드/데이터소스 프로비저닝 (`files/perses-provisioning.yaml`)
`perses.dev/resource: "true"` 라벨 ConfigMap이며 사이드카가 자동 로드한다.
```sh
# 데이터소스 URL / OAuth client_secret 등을 환경에 맞게 수정 후 적용
kubectl apply -f files/perses-provisioning.yaml
```
### 포함 리소스 (project: `monitoring`)
| 리소스 | 이름 | 비고 |
|--------|------|------|
| Dashboard | k8s-node-overview | 노드 CPU/메모리/디스크/네트워크 |
| Dashboard | k8s-workloads | 네임스페이스별 Pod/리소스/Deployment/PVC |
| Dashboard | k8s-pod-diagnostics | Pod 로그·이벤트 (VictoriaLogs) |
| Dashboard | k8s-pod-history | Pod 재배포/재시작 이력 |
| Datasource | victoriametrics | Prometheus 호환 → vmauth:8427 |
| Datasource | victorialogs | LogsQL → vmauth:8427 |
| Secret | vmauth-platform-admin | vmauth용 OAuth client_credentials |
### 4.1 데이터소스 인증 — OAuth client_credentials (전면 JWT/OIDC)
`victoriametrics`/`victorialogs` 데이터소스는 vmauth(`:8427`)를 향하며, HTTPProxy `secret`으로 **Keycloak service-account 토큰**(client_credentials)을 사용한다.
```json
{ "kind": "Secret", "metadata": {"name": "vmauth-platform-admin", "project": "monitoring"},
"spec": { "oauth": {
"clientID": "perses-vmauth",
"clientSecret": "perses-vmauth-secret-changeme",
"tokenURL": "https://keycloak.example.org/realms/paasup/protocol/openid-connect/token",
"scopes": ["openid"] } } }
```
Perses가 토큰을 자동 발급·갱신하며, 해당 토큰의 `vm_access` 클레임이 vmauth에서 테넌트 라우팅을 결정한다.
> ⚠️ Perses는 **로그인 사용자의 OIDC 토큰을 업스트림 데이터소스로 전달하지 않는다.** 데이터소스 쿼리는 항상 위 service-account 토큰(서버사이드)으로 나간다. 사용자 단위 데이터 격리가 필요하면 Project별 데이터소스+service-account를 분리한다.
## 5. 배포 검증
```sh
kubectl port-forward -n monitoring svc/perses 8080:8080
# 브라우저: http://localhost:8080 → Keycloak 로그인 → monitoring 프로젝트 대시보드 확인
```