콘텐츠로 이동

GCP 배포

GCP 배포는 Cloud Build, Artifact Registry, GKE Autopilot, Argo CD, External Secrets Operator를 사용합니다. GCP용 저장소 계약은 cloudbuild.yaml과 GCP values/Helm manifest입니다. Cloud Build trigger, GKE cluster, load balancer와 Argo CD Application은 외부 인프라(sohri-gcp-infra)에서 관리하므로 이 저장소만으로 활성 상태를 보장하지 않습니다.


1. 환경

항목 Development Production
Branch staging main
Cloud Build trigger sohri-dev-graph-dev sohri-prd-graph-prd
Values deploy/values-stg.yaml deploy/values-prd.yaml
Project sohri-dev sohri-prd
Cluster sohri-dev-gke sohri-prd-gke
Region asia-northeast3 asia-northeast3
Image repository sohri-dev-docker/sohri-graph-builder sohri-prd-docker/sohri-graph-builder
GSA sohri-dev-graph@sohri-dev.iam.gserviceaccount.com sohri-prd-graph@sohri-prd.iam.gserviceaccount.com
NEG sohri-dev-graph-neg sohri-prd-graph-neg

2. 자동 배포 흐름

sequenceDiagram
    participant Developer
    participant GitHub
    participant Build as cloudbuild.yaml
    participant Registry as Artifact Registry
    participant Argo as Argo CD
    participant GKE
    participant ESO
    participant Secret as Secret Manager

    Developer->>GitHub: push staging (dev) / main (prd)
    GitHub->>Build: start trigger
    Build->>Build: ruff E9 and compileall
    Build->>Registry: push SHORT_SHA and latest
    Build->>GitHub: update _VALUES_FILE image.tag
    Argo->>GitHub: detect desired-state change
    Argo->>GKE: render Helm and sync
    ESO->>Secret: read OPENAI_API_KEY
    ESO->>GKE: refresh Kubernetes Secret

Production image tag 계약

values-prd.yaml의 초기값은 Artifact Registry에 존재하지 않는 sentinel 0.0.0-unset입니다. main push마다 Cloud Build가 이 값을 immutable commit SHA로 치환합니다. 첫 production build 전에 실수로 sync하면 mutable tag가 조용히 배포되는 대신 ImagePullBackOff로 즉시 실패합니다. productionValidation은 비어 있는 필수값을 막지만 mutable tag 자체를 금지하지는 않으므로, rollout 전에 image.tag가 SHA인지 확인합니다.

Cloud Build 입력과 동작

필수 substitutions:

  • _AR_REPOSITORY_URL
  • _IMAGE_NAME
  • _VALUES_FILE (deploy/values-stg.yaml | deploy/values-prd.yaml)
  • _ENV_NAME (development | production)
  • _GITHUB_REPO_SLUG
  • _GITHUB_PUSH_TOKEN_SECRET_VERSION

빌드는 image를 만든 뒤 SHORT_SHA와 latest를 push하고 _VALUES_FILE의 image.tag를 SHORT_SHA로 바꿔 같은 source branch에 push합니다. 동시 build의 non-fast-forward를 최대 5회 재시도하며 마지막 성공 writer의 tag가 남습니다. Kubernetes API는 호출하지 않습니다.

cloudbuild.yaml 자체는 환경 중립이며 환경별 차이는 전부 substitution으로 주입됩니다. 따라서 trigger가 늘어도 이 파일은 수정하지 않습니다. Argo CD Application manifest는 이 저장소에 없으므로 sync policy(auto sync/self-heal)는 인프라 저장소에서 확인해야 합니다.

Runtime manifest

flowchart LR
    LB["External load balancer"] --> NEG["Standalone NEG"]
    NEG --> SVC["ClusterIP :59212"]
    SVC --> POD["FastAPI Pod"]
    KSA["Kubernetes ServiceAccount"] -. "GKE Workload Identity" .-> GSA["Google Service Account"]
    ESO["External Secrets Operator"] --> SM["Secret Manager"]
    ESO --> SECRET["Kubernetes Secret"]
    SECRET --> POD
  • Service는 values의 NEG 이름으로 standalone NEG annotation을 렌더링합니다.
  • ServiceAccount에는 iam.gke.io/gcp-service-account annotation을 붙입니다.
  • SecretStore/ExternalSecret이 OPENAI_API_KEY를 동기화합니다.
  • Deployment는 동기화된 Secret을 environment variable로 읽습니다.
  • Secret 변경 rollout은 cluster에 Stakater Reloader가 설치된 경우에만 발생합니다.

배포 전 확인

  • [ ] 실제 trigger branch와 substitutions
  • [ ] Artifact Registry push와 GitHub push 권한
  • [ ] production image tag가 immutable SHA인지
  • [ ] Project, cluster, GSA, Secret과 NEG가 인프라 output과 일치하는지
  • [ ] ESO, Workload Identity와 선택적 Reloader 설치 여부
  • [ ] Argo CD source path, values 파일과 sync policy
  • [ ] replica 1과 HPA 비활성