refactor(gitops): establish platform ownership boundaries
This commit is contained in:
@@ -5,29 +5,71 @@
|
||||
```text
|
||||
Gitea main
|
||||
|
|
||||
+-- Argo CD root -> AppProjects + child Applications -> Kubernetes
|
||||
+-- Argo CD root
|
||||
| -> AppProjects + ApplicationSets
|
||||
| -> generated Applications
|
||||
| -> Kubernetes
|
||||
|
|
||||
+-- approved Terraform runner -> Vault API
|
||||
+-- approved Terraform runner
|
||||
-> one of three Vault states
|
||||
-> Vault API
|
||||
```
|
||||
|
||||
Argo CD는 Kubernetes desired state만 관리합니다. 최초 Argo 설치/root
|
||||
seed와 문서화된 recovery 외에는 직접 cluster mutation을 하지 않습니다.
|
||||
Terraform은 Config Management Plugin이나 Argo hook 안에서 실행하지
|
||||
않습니다.
|
||||
Argo CD는 Kubernetes desired state만 관리합니다. 최초 Argo 설치와
|
||||
bootstrap 전용 AppProject/root seed, 문서화된 recovery 외에는 직접
|
||||
cluster mutation을 하지 않습니다. Terraform은 Config Management
|
||||
Plugin이나 Argo hook 안에서 실행하지 않습니다. GHCR은 image artifact
|
||||
registry이며 desired state source가 아닙니다.
|
||||
|
||||
## Kustomize ownership
|
||||
## Kubernetes ownership
|
||||
|
||||
- `platform/`, `workloads/`: 환경 중립 base
|
||||
- `clusters/dev-k3s/manifests/`: namespace, host, image, Vault role 및
|
||||
NetworkPolicy를 포함하는 최종 cluster composition
|
||||
- Argo CD Application: final composition만 source로 사용
|
||||
| Layer | 역할 |
|
||||
|---|---|
|
||||
| `platform/control-plane/argocd` | AppProject와 ApplicationSet control plane |
|
||||
| `platform/shared-services/*/base` | 환경 중립을 목표로 하는 공유 cluster service base |
|
||||
| `systems/*/base` | 환경 중립을 목표로 하는 bounded-context backing system base |
|
||||
| `workloads/*/base` | first-party 애플리케이션 base |
|
||||
| `clusters/dev-k3s/overlays/*` | dev namespace, host, digest, Vault role/path, NetworkPolicy를 합친 최종 구성 |
|
||||
|
||||
지원하지 않는 production overlay는 존재하지 않습니다. production
|
||||
계약과 승인 경계가 확정될 때 별도로 생성합니다.
|
||||
현재 concrete ownership은 Vault가 platform shared service,
|
||||
PostgreSQL/Keycloak이 `systems/auth-system`, 두 서버가 workload입니다.
|
||||
Argo CD Application은 base가 아니라 최종 cluster overlay만 source로
|
||||
사용합니다.
|
||||
|
||||
현재 Keycloak base의 `start-dev`와 Vault base의
|
||||
TLS-off/single-node identity는 dev-specific 예외입니다. 내부 Service
|
||||
참조는 짧은 DNS로 namespace 중립화했지만, 남은 값을 overlay로 추출하는
|
||||
작업은 후속 리팩터링입니다.
|
||||
|
||||
지원하지 않는 production overlay는 존재하지 않습니다. Production trust,
|
||||
approval, TLS, availability contract가 확정될 때 별도로 설계합니다.
|
||||
|
||||
## Bootstrap progression
|
||||
|
||||
```text
|
||||
Argo root
|
||||
-> Sealed Secrets + Vault autoSync
|
||||
-> Vault init
|
||||
-> vault-foundation
|
||||
-> vault-workloads
|
||||
-> runtime secret seed
|
||||
-> Vault Agent Injector autoSync gate
|
||||
-> auth-system autoSync gate
|
||||
-> PostgreSQL Healthy
|
||||
-> vault-database
|
||||
-> Keycloak/client sync ready
|
||||
-> auth-server autoSync gate
|
||||
-> auth-server Healthy
|
||||
-> api-server autoSync gate
|
||||
```
|
||||
|
||||
이 순서는 Application sync wave로 강제하지 않습니다. 각 전환은 health와
|
||||
plan/diff를 확인한 별도 PR입니다. Gate가 닫힌 동안에도 generated
|
||||
Application은 OutOfSync diff를 보여 줍니다.
|
||||
|
||||
## In-application ordering
|
||||
|
||||
`auth-server`의 한 sync operation 안에서:
|
||||
`auth-server`의 한 sync operation 안에서는 다음 ordering을 사용합니다.
|
||||
|
||||
- generated ConfigMap과 일반 리소스: wave `0`
|
||||
- database migration Sync hook: wave `5`
|
||||
@@ -36,20 +78,40 @@ Terraform은 Config Management Plugin이나 Argo hook 안에서 실행하지
|
||||
|
||||
`auth-system`의 Keycloak client sync도 idempotent Sync hook이며 deadline,
|
||||
backoff, `BeforeHookCreation,HookSucceeded` cleanup을 사용합니다.
|
||||
Application 간 준비 순서와 Application 내부 hook 순서를 혼동하지
|
||||
않습니다.
|
||||
|
||||
## Stateful lifecycle
|
||||
|
||||
Vault와 PostgreSQL PVC는 `Prune=false`로 보호합니다. child Application
|
||||
prune/delete는 확인이 필요합니다. path 이동이나 Application rename 전에는
|
||||
새 owner가 동일 live resource를 정상적으로 추적하는지 확인한 후 이전
|
||||
owner를 non-cascading 방식으로 제거합니다.
|
||||
Vault PVC에는 `Prune=confirm,Delete=confirm`이 명시되어 있습니다.
|
||||
PostgreSQL PVC는 StatefulSet `volumeClaimTemplates`가 생성하며 현재
|
||||
manifest에 별도 Argo prune annotation이 없습니다. Namespace와 generated
|
||||
Application 삭제 보호만 믿지 말고 PostgreSQL retention/backup을 직접
|
||||
확인해야 합니다. Path, namespace, Application 이름을 이동할 때는 다음을
|
||||
별도 migration으로 다룹니다.
|
||||
|
||||
## Image promotion
|
||||
1. 기존 live object와 owner를 inventory합니다.
|
||||
2. 새 owner가 같은 object를 안전하게 추적할 수 있는지 render/diff로
|
||||
확인합니다.
|
||||
3. Stateful data backup과 rollback 지점을 확보합니다.
|
||||
4. 기존 owner를 non-cascading 방식으로 제거한 뒤 새 owner를 연결합니다.
|
||||
|
||||
첫-party image는 애플리케이션 CI가 얻은 정확한 GHCR digest를 Gitea
|
||||
workflow에 전달합니다. workflow는 digest 변경 PR을 만들고, validation과
|
||||
승인을 거쳐 merge된 뒤 Argo CD가 배포합니다.
|
||||
이번 리팩터링에서는 `platform` namespace의 auth-system을
|
||||
`auth-system-dev`로 옮기는 live 작업을 실행하지 않았습니다.
|
||||
|
||||
현재 short-SHA tag는 migration 시점의 예외입니다. private GHCR을 읽을
|
||||
자격증명이 이 저장소 실행 환경에 없으므로 임의 digest로 바꾸지 않았고,
|
||||
다음 정상 promotion에서 `digest:`로 교체됩니다.
|
||||
## Image promotion과 GHCR
|
||||
|
||||
정상 promotion에서 first-party image CI는 검증한 정확한 GHCR digest를
|
||||
Gitea workflow에 전달합니다. Workflow는 전용 branch와 digest 변경 PR을
|
||||
만들고 validation과 승인을 거쳐 merge된 뒤 Argo CD가 배포합니다.
|
||||
Renovate는 외부 chart, third-party image와 Terraform provider만 갱신하며
|
||||
두 first-party GHCR package는 비활성화합니다. 따라서 동일 image field를
|
||||
promotion workflow와 Renovate가 동시에 쓰지 않습니다.
|
||||
|
||||
Private GHCR pull credential만 SealedSecret으로 Git에 저장합니다. 평문
|
||||
credential이나 registry token은 manifest, Actions log, Terraform state에
|
||||
남기지 않습니다.
|
||||
|
||||
현재 short-SHA tag는 migration 시점의 예외입니다. Registry 검증 없이
|
||||
임의 digest를 만들지 않고 다음 정상 promotion에서 immutable digest로
|
||||
교체합니다.
|
||||
|
||||
Reference in New Issue
Block a user