refactor: reorganize GitOps control plane

This commit is contained in:
donghyeon-ka
2026-07-25 23:55:31 +09:00
parent d507ac6ee9
commit 293ee6fc97
191 changed files with 7046 additions and 9034 deletions
+38
View File
@@ -0,0 +1,38 @@
# Argo CD layout
`bootstrap/argocd/root-application.yaml`이 유일한 수동 seed입니다. 이
Application은 `clusters/dev-k3s`를 source로 사용하고 다음 리소스를
소유합니다.
```text
clusters/dev-k3s
├── projects
└── applications
├── foundation
│ ├── sealed-secrets
│ ├── vault
│ └── vault-agent-injector
├── platform
│ └── auth-system
└── workloads
├── auth-server
└── api-server
```
AppProject는 root sync wave `-10`, foundation은 `0~1`, platform은 `10`,
workload는 `20`입니다. 이 wave는 child Application 객체 생성 순서만
표현하며 서로 다른 Application의 readiness dependency로 사용하지
않습니다. Vault Agent와 workload는 필요한 Vault/DB API가 준비될 때까지
자체 retry 가능한 형태여야 합니다.
모든 child Application은 auto-sync, prune, self-heal을 사용합니다.
Application 삭제와 parent prune은 확인이 필요하며, shared resource
소유권 충돌은 `FailOnSharedResource=true`로 실패시킵니다.
Sync hook이 있는 `auth-server``auth-system`에는 selective sync 옵션을
사용하지 않습니다. DB migration과 Keycloak client sync는 같은
Application 내부 wave로 순서를 제어합니다.
클러스터가 하나이고 child Application 수가 적으므로 현재는 명시적
Application을 사용합니다. 두 번째 클러스터나 실제 production이 생길
때 foundation/platform/workload별 ApplicationSet 도입을 검토합니다.
+55
View File
@@ -0,0 +1,55 @@
# Deployment architecture
## Reconciliation boundaries
```text
Gitea main
|
+-- Argo CD root -> AppProjects + child Applications -> Kubernetes
|
+-- approved Terraform runner -> Vault API
```
Argo CD는 Kubernetes desired state만 관리합니다. 최초 Argo 설치/root
seed와 문서화된 recovery 외에는 직접 cluster mutation을 하지 않습니다.
Terraform은 Config Management Plugin이나 Argo hook 안에서 실행하지
않습니다.
## Kustomize ownership
- `platform/`, `workloads/`: 환경 중립 base
- `clusters/dev-k3s/manifests/`: namespace, host, image, Vault role 및
NetworkPolicy를 포함하는 최종 cluster composition
- Argo CD Application: final composition만 source로 사용
지원하지 않는 production overlay는 존재하지 않습니다. production
계약과 승인 경계가 확정될 때 별도로 생성합니다.
## In-application ordering
`auth-server`의 한 sync operation 안에서:
- generated ConfigMap과 일반 리소스: wave `0`
- database migration Sync hook: wave `5`
- Deployment: wave `10`
- north-south route: wave `20`
`auth-system`의 Keycloak client sync도 idempotent Sync hook이며 deadline,
backoff, `BeforeHookCreation,HookSucceeded` cleanup을 사용합니다.
## Stateful lifecycle
Vault와 PostgreSQL PVC는 `Prune=false`로 보호합니다. child Application
prune/delete는 확인이 필요합니다. path 이동이나 Application rename 전에는
새 owner가 동일 live resource를 정상적으로 추적하는지 확인한 후 이전
owner를 non-cascading 방식으로 제거합니다.
## Image promotion
첫-party image는 애플리케이션 CI가 얻은 정확한 GHCR digest를 Gitea
workflow에 전달합니다. workflow는 digest 변경 PR을 만들고, validation과
승인을 거쳐 merge된 뒤 Argo CD가 배포합니다.
현재 short-SHA tag는 migration 시점의 예외입니다. private GHCR을 읽을
자격증명이 이 저장소 실행 환경에 없으므로 임의 digest로 바꾸지 않았고,
다음 정상 promotion에서 `digest:`로 교체됩니다.
+55
View File
@@ -0,0 +1,55 @@
# Secret trust boundaries
## Dev Vault
`dev-k3s`는 단일 self-hosted Vault를 사용합니다. 동일 workload
클러스터에 별도의 Transit Vault를 두지 않습니다. 단일 Vault는 다음을
소유합니다.
- KV-v2 runtime secret path
- Kubernetes auth와 workload role
- dynamic PostgreSQL credential
- 애플리케이션 JWT signing용 Transit key
dev Vault는 Shamir 1-of-1로 한 번 초기화하고 재시작 시 명시적으로
unseal합니다. 이 방식은 개발 환경 전용입니다. production에서는 managed
Vault 또는 독립 failure domain의 HA integrated-Raft와 KMS/HSM
auto-unseal을 사용해야 합니다.
## Terraform
`vault-core` state는 mounts, auth, policies, roles와 JWT key를 소유하며
제한된 관리자만 적용합니다. `vault-database`는 PostgreSQL connection과
dynamic roles만 소유하고 `vault-database-automation-dev` 정책을 사용합니다.
Terraform variable로 전달되는 token과 PostgreSQL password는 ephemeral/
write-only 경계를 사용합니다. KV payload는 Terraform resource/data
source로 읽거나 쓰지 않습니다.
## Workload authentication
workload는 audience `vault`, TTL 1시간의 projected ServiceAccount token으로
Vault Kubernetes auth에 로그인합니다. token은 Vault Agent가 사용하며
application container에 Kubernetes bearer token을 직접 노출하지 않습니다.
Secret payload는 승인된 운영자가 Vault에 직접 기록합니다. 값은 Git,
Gitea Actions log, Terraform state, Kubernetes manifest에 남기지 않습니다.
## Bootstrap material
Vault init output은 기본적으로 `.local/vault/dev-k3s-init.json`에 mode
`0600`으로 생성됩니다. encrypted custody로 이동한 후 working copy를
제거합니다. initial root token은 `vault-core`와 operator auth 검증 직후
폐기합니다.
Sealed Secrets는 private GHCR pull credential에만 사용합니다. controller
private key는 별도 복구 저장소에 백업해야 합니다.
## Dev limitations
- Vault, PostgreSQL, ingress가 아직 TLS를 사용하지 않음
- single-node Vault와 PostgreSQL
- Kubernetes API egress CIDR가 현재 dev cluster에 종속
- 정적 bootstrap secret은 coordinated rotation 필요
이 제약은 production에서 허용되지 않습니다.