7.6 KiB
Argo CD architecture
Control-plane ownership
Controller 설치 후 다음 두 bootstrap object를 순서대로 수동 seed합니다.
bootstrap/argocd/control-plane-project.yamlbootstrap/argocd/root-application.yaml
gitops-control-plane AppProject는 canonical Gitea repository와 in-cluster
argocd namespace, AppProject/ApplicationSet kind만 허용합니다. 단일 root
Application은 이 Project를 사용하고 다음 control-plane 구성을 source로
사용합니다.
platform/control-plane/argocd
├── projects
│ ├── platform-addons.yaml
│ ├── platform-services.yaml
│ ├── systems.yaml
│ └── workloads.yaml
└── application-sets
├── platform-addons.yaml
├── platform-services.yaml
├── systems.yaml
└── workloads.yaml
Root는 AppProject와 ApplicationSet까지만 직접 소유합니다. 각
ApplicationSet의 list inventory가 실제 child Application을 생성합니다.
Routine 변경에 category별 root나 직접 kubectl apply를 추가하지 않습니다.
AppProject boundary
| AppProject | 소유 범위 | 허용 destination |
|---|---|---|
platform-addons |
Sealed Secrets, Vault Agent Injector 같은 외부 cluster addon | kube-system, vault |
platform-services |
저장소가 소유하는 Vault shared service | vault |
systems |
Project Auth 전용 PostgreSQL, Keycloak, sync job | auth-system-dev |
workloads |
first-party auth-server, api-server |
auth-dev, api-dev |
Project는 ApplicationSet 파일마다 고정하며 inventory 값으로 template하지 않습니다. 이렇게 해야 element 변경으로 권한 경계를 넘을 수 없습니다. 각 Project는 필요한 source repository, destination, resource kind만 allowlist합니다.
ApplicationSet contract
ApplicationSet은 strict Go template와 list generator를 사용합니다.
goTemplate: truegoTemplateOptions: ["missingkey=error"]- 공통 element:
component,cluster,server,namespace, quoted stringautoSync - Git source element: ownership grammar를 따르는
path;targetRevision은 template의main으로 고정 - Helm addon element: allowlisted
repoURL,chart, chartrevision,helmValues - 파일별 고정 project
필수 key가 빠지면 빈 문자열로 잘못 배포하지 않고 render가 실패해야 합니다.
Application 이름, destination, source path는 같은 element에서 파생하되
project와 Git repository/revision trust boundary는 template하지 않습니다.
외부 addon의 Helm repoURL은 element에서 template되지만 고정 AppProject의
sourceRepos allowlist 밖 URL은 sync할 수 없습니다.
autoSync stage gate
autoSync는 bootstrap 준비 상태와 routine reconciliation을 분리합니다.
Inventory schema는 Go template 비교를 위해 boolean이 아닌 quoted string
"true"/"false"를 사용합니다. Template patch는 값이 "true"인
element에만 다음 정책을 추가합니다.
syncPolicy:
automated:
enabled: true
prune: true
selfHeal: true
초기 gate는 다음과 같습니다.
| Application | 초기 autoSync |
열기 전 확인 |
|---|---|---|
| Sealed Secrets | "true" |
Argo가 chart source를 읽을 수 있음 |
| Vault | "true" |
dev PVC와 NetworkPolicy 변경 검토 |
| Vault Agent Injector | "false" |
Vault init, vault-foundation, vault-workloads, runtime secret seed 완료 |
auth-system |
"false" |
Injector Healthy와 Vault login/secret capability 확인 |
auth-server |
"false" |
PostgreSQL Healthy, vault-database, Keycloak/sync 준비 완료 |
api-server |
"false" |
auth-server Healthy와 호출 경로 확인 |
Gate는 단계별 PR로 하나씩 엽니다. false여도 Application 생성과 diff
표시는 계속되며 수동 Sync 자체를 기술적으로 막지는 않습니다. 따라서
Argo RBAC에서 sync 권한을 제한하고, 수동 Sync에는 명시적 change record를
요구합니다.
비활성 기간 동안 쌓인 모든 diff가 gate를 여는 순간 함께 반영됩니다.
autoSync: "true" PR은 현재 live-to-desired 전체 diff를 검토한 뒤
승인해야 합니다.
Ordering과 failure handling
Control-plane sync wave는 AppProject(-10)를 ApplicationSet(-5)보다
먼저 생성합니다. 네 ApplicationSet은 모두 같은 wave이고 element별
stage/wave field는 없습니다. Generated Application의 실제 readiness
순서는 autoSync 전환과 health 확인이 담당합니다.
Vault Agent, workload와 hook은 선행 API가 늦게 준비될 때 retry할 수 있어야
합니다. auth-system의 Keycloak client sync와 auth-server의 database
migration은 idempotent Sync hook입니다. Hook을 사용하는 Application에는
ApplyOutOfSyncOnly=true를 설정하지 않습니다.
Generated Application은 automated 상태에서 PruneLast=true와
FailOnSharedResource=true를 사용합니다. ApplicationSet은
applicationsSync: create-update와 preserveResourcesOnDeletion: true를
사용합니다. Parent prune과 Application 삭제에는 확인을 요구합니다.
CRD와 cluster-wide RBAC를 포함할 수 있는 platform-addons는
Application-level Prune=confirm도 사용하므로 chart upgrade의 삭제는
별도 승인이 필요합니다.
Stateful path rename이나 ownership 이동은 별도 migration으로 수행하며
ApplicationSet element를 먼저 삭제하지 않습니다.
create-update에서는 generator element를 제거해도 기존 generated
Application이 자동 삭제되지 않고 stale 상태로 남습니다. Element 제거와
Application/resource decommission은
application decommission runbook의
inventory, gate, backup, 명시적 삭제 절차를 따릅니다.
Generator 확장 기준
현재는 cluster가 dev-k3s 하나이므로 네 ApplicationSet의 explicit List
generator가 가장 쉽게 검토됩니다. 존재하지 않는 production이나 미래
cluster를 위해 Matrix abstraction을 미리 만들지 않습니다.
두 번째 실제 cluster가 생겨 cluster, server와 cluster별 gate를 여러
component에서 반복하게 될 때 clusters/<cluster>/config.yaml을 Git files
generator로 읽고 component inventory와 Matrix generator로 결합합니다.
그때도 AppProject는 ApplicationSet template에 고정하고, cluster별
autoSync는 quoted string과 승인 gate로 유지합니다.
Further reading
- Argo CD: cluster bootstrapping, ApplicationSet modification policy, ApplicationSet deletion, automated sync semantics
- Kubernetes: Kustomize
- Terraform: state refactoring,
terraform_remote_statesecurity warning, write-only arguments - Vault: JWT/OIDC authentication
Repository-only change
이 구조와 gate 설계는 2026-07-26 현재 Git에서만 작성·검증했습니다. 실제 cluster migration이나 sync는 이 리팩터링 리뷰 범위에 포함되지 않습니다.