From d1f7c772011330cd0474734addf0cf7d1c74c8be Mon Sep 17 00:00:00 2001 From: wbsong111 Date: Thu, 25 Jun 2026 14:36:58 +0900 Subject: [PATCH] Adjust VM ApplicationSet for test env + per-URL tenant routing rationale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - applicationset: ns argocd→platform, repoURL service-catalog/tenant-catalog @master - vmagent custom-values/CUSTOM-README: per-URL 채택 근거 정정(인라인 가능하나 보안·격리 위해 per-URL) - architecture doc: §5.1 테넌트 라우팅 결정 기록 + monitoring 배포 테스트 문서 Co-Authored-By: Claude Opus 4.8 (1M context) --- doc/monitoring-deploy-test.md | 325 ++++++++++++++++++ doc/victoria-metrics-architecture.md | 18 + .../1.0.0/applicationset.yaml | 12 +- .../0.40.0/CUSTOM-README.md | 4 +- .../0.40.0/custom-values.yaml | 4 + 5 files changed, 356 insertions(+), 7 deletions(-) create mode 100644 doc/monitoring-deploy-test.md diff --git a/doc/monitoring-deploy-test.md b/doc/monitoring-deploy-test.md new file mode 100644 index 0000000..3f08566 --- /dev/null +++ b/doc/monitoring-deploy-test.md @@ -0,0 +1,325 @@ +# VictoriaMetrics 모니터링 스택 배포 테스트 + +카탈로그의 VM 옵저버빌리티 스택(11개 Application)을 **ArgoCD 전체 GitOps 경로**로 배포·검증하는 절차와 기록 문서. 테스트 완료 후 본 문서를 바탕으로 이슈에 결과를 정리한다. + +- 아키텍처: [victoria-metrics-architecture.md](victoria-metrics-architecture.md) +- ApplicationSet: [manifests/applicationset/victoria-metrics/1.0.0/](../manifests/applicationset/victoria-metrics/1.0.0/) +- 카탈로그(테스트 업로드): `https://gitea.example.org/dip/service-catalog` (branch `master`) + +## 표기 규칙 (중요) + +> 🔧 **수동 설정** — dip-console/ArgoCD가 아니라 **사람이 스크립트·명령어로 직접 설정**한 항목. 이 마커가 붙은 내용은 모두 **[§7 수동 설정 목록](#7-수동-설정-목록-이슈자동화-backlog)**에 모이며, 이슈 정리 + 향후 dip-console 자동화 대상이다. 새 수동 작업이 생기면 같은 마커로 표기하고 §7에 추가한다. + +테스트 중 각 단계의 `[ ]` 체크박스와 결과란을 채운다. + +--- + +## 1. 테스트 환경 / 전제 + +| 항목 | 값 / 상태 | +|------|-----------| +| 클러스터 | (기입: context / API 도달 여부) | +| ArgoCD | (기입: 버전 / namespace) | +| StorageClass | longhorn (전제) | +| Ingress / cert-manager | apisix / `root-ca-issuer` (전제) | +| Keycloak | `paasup` realm, 도달 URL (기입) | +| 카탈로그 repo | `gitea.example.org/dip/service-catalog` @ `master` | +| 값(values) repo | (기입: URL @ branch) | +| 사전조건 준비 방식 | **수동 목(mock)** — dip-console 미사용 | + +> 경로: ArgoCD ApplicationSet 이중 소스(카탈로그 + 값 repo) + syncWave 0→1→2. 사전조건은 수동 목으로 준비한다. + +--- + +## 2. 0단계 — 로컬 정적 검증 (클러스터 불필요) + +- [x] 오버레이 `$VAR`를 테스트값으로 치환 후 2단 병합 렌더 확인 — **11/11 PASS** + ```sh + # 차트마다: 베이스(custom-values) + 렌더된 오버레이 + helm template manifests/helm// \ + -f manifests/helm///custom-values.yaml \ + -f /tmp/-overlay-rendered.yaml > /dev/null + ``` +- [x] vmauth 렌더 config에 issuer·`{{.MetricsAccountID}}`·로그 `AccountID` 헤더 포함 확인 — **PASS** +- [x] `applicationset.yaml` / `perses-dashboards.yaml` / `perses-provisioning.yaml` YAML 유효성 — **PASS** + +결과: ✅ **0단계 통과 (2026-06-25)** +- 2단 병합 렌더 11/11 OK (vmcluster·vlogs·ksm·node-exporter·alertmanager·vmauth·vmagent·otelcol·otelcol-events·vmalert·perses). otelcol 로그전용(trace 포트 0), perses ingress 포함(docs=14). +- vmauth 렌더 `auth.yml`: issuer `realms/paasup`, 메트릭 경로 `{{.MetricsAccountID}}`, 로그 헤더 `AccountID: {{.LogsAccountID}}`, `unauthorized_user` accountID 0 모두 확인($VAR 치환 후에도 vmauth 플레이스홀더 보존). +- 매니페스트 3종 YAML 유효(applicationset / perses-dashboards / perses-provisioning). +- 테스트 치환값: `$STORAGE_CLASS=longhorn`, `$KEYCLOAK_URL=https://keycloak.example.org`, `$KEYCLOAK_REALM=paasup`, `$DOMAIN=example.org` (검증용 임시값, 실제 배포는 dip-console 렌더). + +--- + +## 3. 1단계 — 사전조건 수동 목 준비 + +> 🔧 **수동 설정** — 이 단계 전체가 수동 목. dip-console이 대신할 작업들이다. **3.1~3.5 모두 실행 완료(2026-06-25)**. 명령·결과는 각 절 + §7에 집계. +> +> 테스트 환경값: `DOMAIN=example.org`, `KEYCLOAK_URL=https://keycloak.example.org`, `KEYCLOAK_REALM=paasup`, `STORAGE_CLASS=longhorn`. `root-ca-cert` 소스 = `cert-manager/root-ca-secret`(`ca.crt`). + +### 3.1 값(values) repo — ✅ 실행 완료 (2026-06-25) + +- [x] 오버레이 11종을 `$VAR` 치환(문자열 치환만, `{{.MetricsAccountID}}` 등 보존) → `~/project/tenant-catalog/victoria-metrics/`에 생성 후 push + ```sh + # dip-catalog 오버레이 → tenant-catalog 렌더 (sed 문자열 치환) + for f in manifests/applicationset/victoria-metrics/1.0.0/*-values.yaml; do + sed -e 's#$STORAGE_CLASS#longhorn#g' -e 's#$KEYCLOAK_URL#https://keycloak.example.org#g' \ + -e 's#$KEYCLOAK_REALM#paasup#g' -e 's#$DOMAIN#example.org#g' \ + -e 's#$INFISICAL_PERSES_CLIENT_SECRET#perses-mock-secret-changeme#g' \ + -e 's#$INFISICAL_ALERTMANAGER_SECRET#alertmanager-notify#g' "$f" \ + > ~/project/tenant-catalog/victoria-metrics/$(basename "$f") + done + cd ~/project/tenant-catalog && git add -A && git commit -m "Add victoria-metrics values (mock)" && git push origin master + ``` + 결과: `dip/tenant-catalog` @ master `510aa8e`, `victoria-metrics/*-values.yaml` 11개. + +**생성된 값 파일 내용** (환경 고유값 있는 차트만; 나머지 6종 `kube-state-metrics`/`node-exporter`/`otelcol`/`otelcol-events`/`vmagent`/`vmalert`-values.yaml = `{}` — 베이스 custom-values만 사용) + +`vmauth-values.yaml` +```yaml +config: + users: + - jwt: + oidc: + issuer: "https://keycloak.example.org/realms/paasup" + url_map: + - src_paths: ["/api/v1/.*"] + url_prefix: "http://vmcluster-victoria-metrics-cluster-vmselect.monitoring.svc.cluster.local:8481/select/{{.MetricsAccountID}}/prometheus" + - src_paths: ["/select/logsql/.*"] + url_prefix: "http://vlogs-victoria-logs-cluster-vlselect.monitoring.svc.cluster.local:9471" + headers: + - "AccountID: {{.LogsAccountID}}" + - "ProjectID: 0" + unauthorized_user: + url_prefix: "http://vmcluster-victoria-metrics-cluster-vmselect.monitoring.svc.cluster.local:8481/select/0/prometheus" +``` + +`perses-values.yaml` +```yaml +config: + security: + enable_auth: true + authentication: + providers: + oidc: + - slug_id: keycloak + name: Keycloak + client_id: perses + client_secret: "perses-mock-secret-changeme" + issuer: "https://keycloak.example.org/realms/paasup" + redirect_uri: "https://perses.example.org/api/auth/providers/oidc/keycloak/callback" + scopes: [openid, profile, email] +ingress: + enabled: true + ingressClassName: "apisix" + annotations: + cert-manager.io/cluster-issuer: "root-ca-issuer" + hosts: + - host: "perses.example.org" + paths: [{ path: /, pathType: Prefix }] + tls: + - secretName: perses-tls + hosts: ["perses.example.org"] +``` + +`alertmanager-values.yaml` +```yaml +extraSecretMounts: + - name: alertmanager-notify + mountPath: /etc/alertmanager/secrets + subPath: "" + secretName: "alertmanager-notify" + readOnly: true +``` + +`vmcluster-values.yaml` / `vlogs-values.yaml` +```yaml +# vmcluster +vmstorage: { persistentVolume: { storageClass: "longhorn" } } +# vlogs +vlstorage: { persistentVolume: { storageClass: "longhorn" } } +``` + +### 3.2 Keycloak (paasup realm) — ✅ 실행 완료 (2026-06-25) + +확인됨: `paasup` realm 존재(HTTP 200), `perses`/`perses-vmauth` client·`vm-access` scope **없음**(신규 생성 대상). + +```sh +# ── 관리자 토큰 (platform Keycloak) ── +KC=https://keycloak.example.org; REALM=paasup +PW=$(kubectl get secret -n platform keycloak -o jsonpath='{.data.admin-password}' | base64 -d) +TOKEN=$(curl -sk -X POST "$KC/realms/master/protocol/openid-connect/token" \ + -d grant_type=password -d client_id=admin-cli -d username=admin --data-urlencode "password=$PW" | jq -r .access_token) +H="Authorization: Bearer $TOKEN"; JSON="Content-Type: application/json" + +# ── 1) Client Scope vm-access + 매퍼 2종 ── +curl -sk -X POST "$KC/admin/realms/$REALM/client-scopes" -H "$H" -H "$JSON" \ + -d '{"name":"vm-access","protocol":"openid-connect"}' +SID=$(curl -sk "$KC/admin/realms/$REALM/client-scopes" -H "$H" | jq -r '.[]|select(.name=="vm-access").id') +for m in metrics logs; do + curl -sk -X POST "$KC/admin/realms/$REALM/client-scopes/$SID/protocol-mappers/models" -H "$H" -H "$JSON" \ + -d "{\"name\":\"vm-$m-account\",\"protocol\":\"openid-connect\",\"protocolMapper\":\"oidc-usermodel-attribute-mapper\",\"config\":{\"user.attribute\":\"vm_${m}_account_id\",\"claim.name\":\"vm_access.${m}_account_id\",\"jsonType.label\":\"int\",\"access.token.claim\":\"true\",\"id.token.claim\":\"false\"}}" +done + +# ── 2) Client perses (로그인) — secret은 perses-values.yaml의 client_secret과 일치 ── +curl -sk -X POST "$KC/admin/realms/$REALM/clients" -H "$H" -H "$JSON" -d '{ + "clientId":"perses","enabled":true,"publicClient":false,"standardFlowEnabled":true, + "secret":"perses-mock-secret-changeme", + "redirectUris":["https://perses.example.org/api/auth/providers/oidc/keycloak/callback"]}' + +# ── 3) Client perses-vmauth (datasource service-account) ── +curl -sk -X POST "$KC/admin/realms/$REALM/clients" -H "$H" -H "$JSON" -d '{ + "clientId":"perses-vmauth","enabled":true,"publicClient":false, + "standardFlowEnabled":false,"serviceAccountsEnabled":true,"secret":"perses-vmauth-secret-changeme"}' +CID=$(curl -sk "$KC/admin/realms/$REALM/clients?clientId=perses-vmauth" -H "$H" | jq -r '.[0].id') +curl -sk -X PUT "$KC/admin/realms/$REALM/clients/$CID/default-client-scopes/$SID" -H "$H" # vm-access 연결 +SAU=$(curl -sk "$KC/admin/realms/$REALM/clients/$CID/service-account-user" -H "$H" | jq -r .id) +curl -sk -X PUT "$KC/admin/realms/$REALM/users/$SAU" -H "$H" -H "$JSON" \ + -d '{"attributes":{"vm_metrics_account_id":["0"],"vm_logs_account_id":["0"]}}' # 플랫폼 조회(account 0) + +# ── (선택) 테스트 유저 attribute: 테넌트 격리 검증용 ── +# UID=$(curl -sk "$KC/admin/realms/$REALM/users?username=" -H "$H" | jq -r '.[0].id') +# curl -sk -X PUT "$KC/admin/realms/$REALM/users/$UID" -H "$H" -H "$JSON" \ +# -d '{"attributes":{"vm_metrics_account_id":["1"],"vm_logs_account_id":["1"]}}' +``` + +### 3.3 시크릿 (평문 목 — external-secrets/Infisical 대체) — ✅ 실행 완료 (2026-06-25) + +> `monitoring` ns 선생성 필요(ArgoCD `CreateNamespace`는 sync 시점 → 사전 생성). perses OIDC `client_secret`은 perses-values.yaml에 인라인이라 별도 Secret 불필요(목). `root-ca-cert`·`alertmanager-notify`만 필요. + +```sh +kubectl create namespace monitoring --dry-run=client -o yaml | kubectl apply -f - + +# alertmanager 알림 자격증명 (base custom-values가 /etc/alertmanager/secrets/webhook-url 참조) +kubectl create secret generic alertmanager-notify -n monitoring \ + --from-literal=webhook-url='https://discord.com/api/webhooks/' + +# Keycloak TLS 신뢰용 CA (perses base custom-values가 secretName: root-ca-cert, key ca.crt 마운트) +# 사내 CA 소스: cert-manager/root-ca-secret (ca.crt, 1261 bytes) +kubectl get secret root-ca-secret -n cert-manager -o jsonpath='{.data.ca\.crt}' | base64 -d > /tmp/ca.crt +kubectl create secret generic root-ca-cert -n monitoring --from-file=ca.crt=/tmp/ca.crt +``` + +**생성된 Secret** (ns=monitoring) + +| Secret | 키 | 값 / 출처 | +|--------|-----|-----------| +| `alertmanager-notify` | `webhook-url` | `https://discord.com/api/webhooks/MOCK/MOCK` (mock) | +| `root-ca-cert` | `ca.crt` | `cert-manager/root-ca-secret`의 `ca.crt` 복사 (1261 bytes) | + +### 3.4 ConfigMap — ✅ 실행 완료 (2026-06-25) + +vmagent base custom-values가 `vmagent-relabel-configs`(테넌트별 demo01/demo02/platform) 마운트. 목은 빈 규칙으로도 기동 가능. + +```sh +# 테넌트별 write_relabel_configs (예: 최소 빈 규칙). 실제 규칙은 dip-console이 테넌트 온보딩 시 채움. +for t in demo01 demo02 platform; do echo "[]" > /tmp/$t.yaml; done +kubectl create configmap vmagent-relabel-configs -n monitoring \ + --from-file=demo01.yaml=/tmp/demo01.yaml --from-file=demo02.yaml=/tmp/demo02.yaml --from-file=platform.yaml=/tmp/platform.yaml +``` + +**생성된 ConfigMap `vmagent-relabel-configs`** — 3개 키, 각 내용(mock): +```yaml +# demo01.yaml +[] +# demo02.yaml +[] +# platform.yaml +[] +``` + +### 3.5 대시보드 — ✅ 실행 완료 (2026-06-25) + +정적 대시보드 ConfigMap(사이드카 로드). 테스트에선 임시 apply, 정식은 ArgoCD directory 소스 Application. + +```sh +kubectl apply -n monitoring -f manifests/helm/perses/0.21.0/files/perses-dashboards.yaml +# (데이터소스/시크릿은 perses-provisioning.yaml — 환경별이라 dip-console/Infisical 관리) +``` + +**생성된 ConfigMap `perses-dashboards`** — label `perses.dev/resource: "true"`, data 키 4종(대시보드 JSON): `dashboard-k8s-nodes.json`, `dashboard-k8s-pod-diagnostics.json`, `dashboard-k8s-pod-history.json`, `dashboard-k8s-workloads.json`. 원본: [perses-dashboards.yaml](../manifests/helm/perses/0.21.0/files/perses-dashboards.yaml). + +--- + +## 4. 2단계 — ArgoCD 배포 + +- [ ] repo 등록: 카탈로그 repo + 값 repo (`argocd repo add`, 사내 CA insecure) + > 🔧 **수동 설정**: `argocd repo add` 명령 기록 → §7 +- [ ] `applicationset.yaml`의 `repoURL`→`dip/service-catalog`, `targetRevision`→`master`로 수정 확인 +- [ ] `kubectl apply -f manifests/applicationset/victoria-metrics/1.0.0/applicationset.yaml` +- [ ] `argocd app list`로 wave 0→1→2 순서 Synced/Healthy, perses가 vmauth 이후 기동 + +결과 (Application별 Sync/Health): + +| Application | wave | Synced | Healthy | +|-------------|------|--------|---------| +| vmcluster | 0 | | | +| vlogs | 0 | | | +| kube-state-metrics | 0 | | | +| node-exporter | 0 | | | +| alertmanager | 0 | | | +| vmauth | 1 | | | +| vmagent | 1 | | | +| otelcol | 1 | | | +| otelcol-events | 1 | | | +| vmalert | 1 | | | +| perses | 2 | | | + +--- + +## 5. 3단계 — E2E 기능 검증 + +vm-stack `test/` 스크립트(`verify-metrics.sh`/`verify-logs.sh`) 패턴(port-forward + curl) 적응. + +| # | 항목 | 검증 방법 | 결과 | +|---|------|-----------|------| +| 1 | 파드 | `monitoring` 전 파드 Running | | +| 2 | 메트릭 | vmagent targets up>0, vmselect `query=count(up)`>0 | | +| 3 | 인증 라우팅 | Keycloak 토큰으로 vmauth `/api/v1/query` 성공 | | +| 4 | 로그 | otelcol→vlinsert 적재, vmauth `AccountID` 헤더로 vlselect 조회 | | +| 5 | 멀티테넌시 | accountID별 메트릭(경로)·로그(헤더) 격리 | | +| 6 | perses | Keycloak 로그인, 대시보드 4종 로드, datasource 쿼리 | | +| 7 | 알림 | vmalert 규칙 로드, 테스트 알림 → alertmanager → 채널 수신 | | + +> 🔧 **수동 설정**(검증용 임시 토큰 발급/포트포워드 등 일회성 명령): 기록 → §7 + +--- + +## 6. 4단계 — 정리 (teardown) + +- [ ] ArgoCD Application/ApplicationSet 삭제(또는 prune) +- [ ] 비-helm CR(있다면) → helm/Application → `monitoring` ns +- [ ] longhorn PV/volume 명시 삭제(Retain) +- [ ] Keycloak 목 리소스(perses client·테스트 그룹) 삭제 + > 🔧 **수동 설정**: 삭제 명령 기록 → §7 + +--- + +## 7. 수동 설정 목록 (이슈/자동화 backlog) + +> 위 🔧 항목에서 **실제 실행한 명령·스크립트**를 여기에 모은다. 이슈 정리 시 이 표를 그대로 사용하고, 각 항목은 dip-console 자동화 후보다. + +| # | 단계 | 대상 | 상태 | 명령 위치 | dip-console 이관 | +|---|------|------|------|-----------|------------------| +| 1 | 3.1 | 값 repo 렌더·push | ✅ 실행(2026-06-25) `tenant-catalog@510aa8e` | [§3.1](#31-값values-repo--✅-실행-완료-2026-06-25) | ✅ 예정 | +| 2 | 3.2 | Keycloak vm-access scope(+매퍼2) + perses/perses-vmauth client + SA attr(acct 0) | ✅ 실행(2026-06-25) `paasup` realm | §3.2 | ✅ 예정 | +| 3 | 3.3 | `monitoring` ns + `alertmanager-notify` + `root-ca-cert`(←cert-manager/root-ca-secret) | ✅ 실행(2026-06-25) | §3.3 | ✅ 예정(Infisical) | +| 4 | 3.4 | `vmagent-relabel-configs`(demo01/demo02/platform, 빈 규칙) | ✅ 실행(2026-06-25) | §3.4 | ✅ 예정 | +| 5 | 3.5 | `perses-dashboards` ConfigMap apply | ✅ 실행(2026-06-25) | §3.5 | (ArgoCD 경로) | +| 6 | 4 | ArgoCD repo add + ApplicationSet | ⬜ 미수행 (ArgoCD 위치 확인 필요 — platform ns 추정) | §4 | - | +| 7 | 6 | teardown | ⬜ 미수행 | §6 | - | + +> 진행 메모(2026-06-25): **1단계(3.1~3.5) 전부 실행 완료.** 모두 mock 값. client_secret: perses=`perses-mock-secret-changeme`, perses-vmauth=`perses-vmauth-secret-changeme`. alertmanager webhook·relabel은 mock placeholder. 다음은 2단계(ArgoCD) — `platform` ns에 argocd-tls 존재 → ArgoCD 설치 위치부터 확인 필요. + +--- + +## 8. 테스트 결과 요약 (이슈용) + +테스트 완료 후 채운다. + +- **일시 / 수행자**: (기입) +- **환경**: (클러스터/ArgoCD/Keycloak) +- **결과**: 11 Application Synced+Healthy ( / ), E2E ( /7 PASS) +- **발견 이슈 / 개선사항**: + - (예: perses ingress 누락 보강, 시크릿 이름 불일치, `$VAR` 렌더 방식 등) +- **자동화 backlog**: §7 수동 설정 목록 참조 diff --git a/doc/victoria-metrics-architecture.md b/doc/victoria-metrics-architecture.md index 034709d..4036c97 100644 --- a/doc/victoria-metrics-architecture.md +++ b/doc/victoria-metrics-architecture.md @@ -128,6 +128,24 @@ flowchart TB > **비대칭**: 메트릭은 `/select/multitenant/`로 전체 테넌트 집계가 가능하나, VictoriaLogs는 합산 엔드포인트가 없어 `(AccountID, ProjectID)` 단위로만 조회된다. +### 5.1 메트릭 쓰기 경로 테넌트 라우팅 결정 (per-URL) + +위 표는 **조회(read)** 경로다. **쓰기(write)** 경로에서 vmagent가 테넌트를 어떻게 가르는지는 두 가지 선택지가 있고, **per-URL을 채택**한다. + +| 방식 | 동작 | 온보딩 | 격리 | +|------|------|--------|------| +| **per-URL (채택)** | 테넌트마다 별도 remoteWrite `/insert/{accountID}/` + `urlRelabelConfig` keep 필터 | 새 테넌트 = vmagent 값 + relabel 수정 → **Git/PR** | **강** — URL이 테넌시 강제 | +| multitenant+라벨 (대안) | 단일 `/insert/multitenant/` + relabel로 `vm_account_id` 라벨 set | ConfigMap만 수정 | 약 — 라벨(=relabel 규칙)에 의존 | + +**per-URL 채택 근거 (보안·격리 우선)** +- **스푸핑 차단**: 테넌시가 URL로 고정 → 스크레이프 대상이 `vm_account_id` 라벨을 노출해도 테넌트 위장 불가. +- **변경 통제**: 새 테넌트(=새 accountID) 추가가 Git/PR 리뷰·승인을 거침(ConfigMap 한 줄 수정보다 통제 강함). +- **장애·오설정 격리**: remoteWrite 큐가 테넌트별로 분리 → 한 테넌트 문제나 relabel 오타의 cross-tenant 파급 제한. + +**트레이드오프(감수)**: 새 테넌트 추가 시 vmagent 값(remoteWrite)도 함께 수정·재배포해야 한다. (multitenant+라벨은 ConfigMap만으로 온보딩되지만 테넌시가 relabel 규칙에 의존해 격리가 약함 — 채택 안 함.) + +> 같은 테넌트의 새 네임스페이스(`demo01-*`)는 prefix 정규식이 커버하므로 **무변경**. 변경이 필요한 건 **새 accountID(테넌트) 추가** 시뿐이다. 차트는 인라인 `urlRelabelConfig`도 지원하나, 위 근거로 per-tenant URL + 별도 relabel ConfigMap을 쓴다. + ## 6. 인증/인가 (Keycloak `paasup` realm) ```mermaid diff --git a/manifests/applicationset/victoria-metrics/1.0.0/applicationset.yaml b/manifests/applicationset/victoria-metrics/1.0.0/applicationset.yaml index fea63ff..0c503e3 100644 --- a/manifests/applicationset/victoria-metrics/1.0.0/applicationset.yaml +++ b/manifests/applicationset/victoria-metrics/1.0.0/applicationset.yaml @@ -2,7 +2,7 @@ apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: victoria-metrics - namespace: argocd + namespace: platform spec: goTemplate: true goTemplateOptions: ["missingkey=error"] @@ -71,15 +71,15 @@ spec: template: metadata: name: "{{ .name }}" - namespace: argocd + namespace: platform annotations: argocd.argoproj.io/sync-wave: "{{ .syncWave }}" spec: project: default sources: # Source 1: 카탈로그 repo (Helm 차트) - - repoURL: https://gitea.example.org/dip/catalog-test - targetRevision: main + - repoURL: https://gitea.example.org/dip/service-catalog + targetRevision: master path: "{{ .chartPath }}" helm: releaseName: "{{ .name }}" @@ -87,8 +87,8 @@ spec: - "{{ .baseValues }}" # 카탈로그 차트의 정적 베이스값(custom-values) - $values/{{ .valuesPath }} # Source 2의 환경 오버레이 (나중 = 우선) # Source 2: 값(values) repo — dip-console이 렌더한 환경별 값 - - repoURL: https://gitea.example.org/dip/values-test - targetRevision: main + - repoURL: https://gitea.example.org/dip/tenant-catalog + targetRevision: master ref: values destination: server: https://kubernetes.default.svc diff --git a/manifests/helm/victoria-metrics-agent/0.40.0/CUSTOM-README.md b/manifests/helm/victoria-metrics-agent/0.40.0/CUSTOM-README.md index 76dcd2b..9236c1b 100644 --- a/manifests/helm/victoria-metrics-agent/0.40.0/CUSTOM-README.md +++ b/manifests/helm/victoria-metrics-agent/0.40.0/CUSTOM-README.md @@ -30,7 +30,9 @@ helm upgrade vmagent ./ -f custom-values.yaml --install -n monitoring | 9000 | platform (kafka-system, kubeflow 등) | `/relabel/platform.yaml` | | 0 | fallback (미매칭) | 없음 | -> 쓰기 경로는 vmauth를 경유하지 않고 vminsert(`:8480`)에 직접 쓴다. `writeRelabelConfigs`(camelCase)는 CLI 미지원이라 파일 마운트(`urlRelabelConfig`) 방식을 사용한다. +> 쓰기 경로는 vmauth를 경유하지 않고 vminsert(`:8480`)에 직접 쓴다. +> +> **테넌트 라우팅 방식 결정 (per-URL)**: 차트는 `urlRelabelConfig`에 relabel 규칙을 **인라인**으로 줘도 자동으로 ConfigMap을 생성·마운트한다(기술적으로 인라인 가능). 그럼에도 **테넌트마다 별도 remoteWrite URL(`/insert/{accountID}/`) + 별도 relabel 파일**을 쓰는 이유는 **보안·격리** 때문이다: ① 테넌시를 URL이 강제하므로 데이터 라벨 스푸핑이 불가, ② 새 테넌트 추가가 Git/PR 변경(감사·승인)을 거침, ③ remoteWrite 큐가 테넌트별로 분리돼 장애·오설정의 cross-tenant 파급이 제한됨. (대안인 `/insert/multitenant/` + `vm_account_id` 라벨 매핑은 온보딩이 ConfigMap만으로 가능하나 테넌시가 relabel 규칙에 의존 → 격리가 약함. 트레이드오프는 아키텍처 문서 참조.) ### 2.2 scrape_configs diff --git a/manifests/helm/victoria-metrics-agent/0.40.0/custom-values.yaml b/manifests/helm/victoria-metrics-agent/0.40.0/custom-values.yaml index ae549e9..99258cf 100644 --- a/manifests/helm/victoria-metrics-agent/0.40.0/custom-values.yaml +++ b/manifests/helm/victoria-metrics-agent/0.40.0/custom-values.yaml @@ -7,6 +7,10 @@ # accountID 매핑(예시): 0=플랫폼 공통(fallback) / 1=demo01 / 2=demo02 / 9000=platform # 네임스페이스별 분기는 urlRelabelConfig(ConfigMap: vmagent-relabel-configs) 마운트로 처리. # 해당 ConfigMap은 온보딩 시 별도 생성한다(CUSTOM-README 참조). +# +# 테넌트 라우팅 = per-URL 의도적 채택(보안·격리). 차트는 인라인 urlRelabelConfig도 지원하나, +# 테넌시를 URL로 강제(스푸핑 차단)하고 테넌트 추가를 Git/PR로 통제하기 위해 per-tenant URL을 쓴다. +# → 새 테넌트 = remoteWrite 항목 추가(이 파일 수정) + relabel 파일 추가. 상세: CUSTOM-README / 아키텍처 문서. # ============================================================================= # remoteWrite — 최소 1개 필요. accountID별 엔드포인트 + urlRelabelConfig 파일 분기