# Project GitOps reference lab Project Auth를 예제로 사용해 작은 팀의 GitOps 운영 경계를 학습하고 검증하는 독립 reference lab입니다. 범용 사내 플랫폼이나 애플리케이션 소스 monorepo가 아닙니다. 현재 지원 대상은 단일 `dev-k3s` 클러스터뿐입니다. 배포 기준 저장소는 내부 Gitea 한 곳입니다. ```text https://git.learn.hyeonworks.com/donghyeon.kang/project-gitops ``` `auth-server`와 `api-server`의 소스 저장소는 이미지를 빌드해 GHCR에 올립니다. 정상 promotion 계약은 검증된 immutable digest를 바꾸는 PR입니다. 현재 overlay에는 이관 전의 짧은 commit tag가 남아 있으며, registry를 검증할 credential 없이 임의 digest로 바꾸지 않았습니다. 다음 정상 promotion workflow가 digest로 전환합니다. Kubernetes desired state는 Argo CD가, Vault API 객체는 Terraform이 각각 관리합니다. KV secret 값은 어느 쪽에도 저장하지 않습니다. ## 지원 범위 | 대상 | 상태 | |---|---| | `dev-k3s` | 지원하는 단일 노드 개발 환경 | | production | 설계되지 않았으며 overlay/Application이 없음 | | Istio | 보류; 향후 ambient mode 도입 조건만 기록 | 현재 Vault, PostgreSQL, ingress는 TLS가 없는 개발 프로파일이며 single-node failure domain을 공유합니다. production 용도로 사용할 수 없습니다. 2026-07-26의 repository/ownership 리팩터링은 Git 작업 트리에만 설계하고 검증했습니다. 실제 클러스터에는 적용하지 않았으며, 기존 리소스의 소유권 이관은 관련 runbook과 별도 승인 없이 실행하면 안 됩니다. ## 제어 흐름 ```text application CI -> GHCR digest -> GitOps PR -> validation -> main | v Argo CD ApplicationSet | v Kubernetes IaC PR -> Terraform plan -> approval -> one Vault state apply -> Vault API ``` Argo CD 최초 설치 뒤 bootstrap 전용 `gitops-control-plane` AppProject와 단일 root Application만 순서대로 직접 적용합니다. 이후 routine deployment는 Git 변경으로만 수행합니다. Terraform은 Argo CD hook이나 Config Management Plugin 안에서 실행하지 않습니다. ## 저장소 분류 ```text bootstrap/ foundation/ 외부 state/identity 선행 조건 문서 gitops/argocd/ controller 버전, 제한된 AppProject와 단일 root seed infrastructure/ components/ 재사용 Vault Terraform component live/dev-k3s/ vault-foundation/ mount/auth와 delegated automation policy vault-workloads/ workload ACL, auth role와 Transit key vault-database/ PostgreSQL connection과 dynamic role gitops/clusters/dev-k3s/ kustomization.yaml Argo CD가 읽는 유일한 cluster root overlays/ platform/ 공유 서비스의 dev-k3s 최종 구성 systems/ bounded-context system의 dev-k3s 최종 구성 workloads/ first-party workload의 dev-k3s 최종 구성 gitops/platform/ control-plane/argocd/ AppProject와 ApplicationSet inventory shared-services/ 여러 system이 쓰는 cluster capability base gitops/apps/ systems/ bounded-context backing system base workloads/ 별도 source repository를 가진 application base scripts/ bootstrap, validation, dev Vault init entrypoint docs/ architecture, ADR, guide와 runbook examples/, tests/ 템플릿 예제와 저장소 수준 검증 영역 ``` 각 catalog의 `_template`은 새 component를 만들 때 사용하는 복사 원본이며 Argo CD가 직접 reconcile하지 않습니다. 분류는 제품 종류가 아니라 소비자, 소유자, 변경 주기로 결정합니다. Vault는 공유 capability이므로 `gitops/platform/`, Project Auth 전용 PostgreSQL과 Keycloak은 `gitops/apps/systems/auth-system/`, 직접 빌드하는 서버는 `gitops/apps/workloads/`에 속합니다. namespace, host, image digest, Vault role, NetworkPolicy 같은 클러스터별 값은 `gitops/clusters/dev-k3s/overlays/`에서 완결합니다. Vault ACL은 소비하는 Terraform state의 `policies/`에 함께 둡니다. 자세한 판단 기준은 [repository taxonomy](docs/architecture/repository-taxonomy.md)와 [ADR 0007](docs/decisions/0007-repository-ownership-boundaries.md)을 따릅니다. ## Argo CD 단계 gate Root Application은 `gitops/clusters/dev-k3s`만 source로 사용합니다. 이 cluster root가 `gitops/platform/control-plane/argocd`의 AppProject와 ApplicationSet을 조립하고, 각 ApplicationSet이 cluster overlay를 reconcile합니다. 각 inventory 항목은 `autoSync`를 quoted string으로 명시해야 합니다. 새 항목이나 외부 준비 조건이 있는 항목은 `autoSync: "false"`로 시작하고, 선행 controller, Vault 구성, runtime secret, database 준비를 확인한 PR에서만 `autoSync: "true"`로 바꿉니다. Control-plane sync wave는 AppProject(`-10`)를 ApplicationSet(`-5`)보다 먼저 생성할 뿐, generated Application의 readiness를 보장하지 않습니다. `autoSync` gate와 workload의 retry/idempotency가 실제 단계 전환을 담당합니다. ## Terraform state | Root | 소유 범위 | routine 실행 권한 | |---|---|---| | `vault-foundation` | mounts, auth backends/config, delegated automation policy와 선택적 CI JWT roles | 없음; bootstrap 또는 보안 관리자 승인 실행 | | `vault-workloads` | workload ACL, Kubernetes auth role, 애플리케이션 Transit key | workload 전용 short-lived identity | | `vault-database` | PostgreSQL connection과 `auth-db-migration-dev` dynamic role | database 전용 short-lived identity | 중요한 규칙은 다음과 같습니다. - Vault API 객체 하나는 정확히 한 state만 소유합니다. - Delegated state는 자신에게 권한을 부여하는 policy/login role을 만들지 않습니다. 그것은 `vault-foundation`이 소유합니다. - State 사이에 `terraform_remote_state`를 사용하지 않습니다. - KV payload, Vault init JSON, token, PostgreSQL password를 Git이나 Terraform state에 저장하지 않습니다. - Backend는 encryption, versioning, access control, locking을 제공해야 합니다. ## 주요 명령 ```bash make validate make bootstrap KUBE_CONTEXT= make terraform-plan \ TF_ROOT=vault-foundation \ BACKEND_CONFIG=.local/terraform-backend/dev-k3s/vault-foundation.s3.hcl ``` `terraform-apply`는 동일 입력과 `APPROVE_APPLY=dev-k3s/`가 모두 있어야 실행되며 `auto-approve`를 사용하지 않습니다. 실제 bootstrap과 state 이동은 먼저 runbook의 중단 조건을 확인합니다. ## 문서 - [Repository taxonomy](docs/architecture/repository-taxonomy.md) - [배포 구조](docs/architecture/deployment.md) - [Argo CD 구조와 stage gate](docs/architecture/argocd.md) - [Secret trust boundary](docs/architecture/secret-trust.md) - [Terraform 사용 경계](docs/architecture/terraform.md) - [빈 dev 클러스터 bootstrap](docs/runbooks/dev-bootstrap.md) - [Application 안전한 decommission](docs/runbooks/application-decommission.md) - [Terraform state 이관](docs/runbooks/terraform-state-migration.md) - [Vault backup/recovery](docs/runbooks/vault-backup-restore.md) - [Sealed Secrets recovery](docs/runbooks/sealed-secrets-recovery.md) - [입문 가이드](docs/guides/intern-guide.md)