Config Sync Sources & Hierarchical Repository — Tổ Chức Cấu Hình Ở Scale
Tại Sao Quan Trọng Trong Production
Config Sync có thể đọc từ ba nguồn khác nhau: Git repository, OCI container image, và Helm chart. Quyết định chọn source type ảnh hưởng đến: cách team versioning configs, thời gian sync, authentication mechanism, và khả năng audit trail. Tổ chức repository ảnh hưởng đến: khả năng phân quyền giữa platform team và app teams, tính rõ ràng của "config nào apply lên cluster nào", và scalability khi fleet lớn lên.
Hai quyết định này (source type và repo structure) phải được đưa ra sớm vì khó thay đổi về sau mà không có migration effort lớn.
Git Source — Cơ Chế Pull và Authentication
Cơ Chế Polling Git
Config Sync không dùng webhook để nhận thông báo từ Git (dù một số implementations khác như Flux dùng cách này). Thay vào đó, reconciler source container poll Git repository theo interval:
apiVersion: configsync.gke.io/v1beta1
kind: RootSync
metadata:
name: root-sync
namespace: config-management-system
spec:
sourceType: git
git:
repo: https://github.com/myorg/fleet-config.git
branch: main
dir: clusters/prod-us-east1 # Thư mục trong repo
period: 15s # Poll interval (default 15s)
auth: gcpserviceaccount # Authentication method
gcpServiceAccountEmail: config-sync@my-project.iam.gserviceaccount.comQuá trình pull:
- Source container chạy
git fetch(không phảigit cloneđầy đủ mỗi lần) - So sánh remote commit SHA với local cached SHA
- Nếu khác:
git checkoutbranch/commit mới, cập nhật local cache - Signal cho reconciler container rằng có nội dung mới để process
Git source dùng shallow clone và sparse checkout khi có thể để giảm bandwidth và thời gian pull. Với large repo (thousands of files), chỉ fetch diff của commits mới, không re-fetch toàn bộ.
Authentication Cho Git
Config Sync hỗ trợ nhiều authentication methods:
gcpserviceaccount (khuyên dùng cho GCP-hosted repos như Cloud Source Repositories):
git:
auth: gcpserviceaccount
gcpServiceAccountEmail: config-sync@project.iam.gserviceaccount.comConfig Sync sử dụng Workload Identity của reconciler pod để authenticate. Service account cần có Source Repository Reader role trên repo.
token (username/password hoặc Personal Access Token):
git:
auth: token
secretRef:
name: git-credentials # Secret với keys: username, tokenToken được store trong Kubernetes Secret trong config-management-system namespace. Không khuyến khích vì secret rotation phức tạp.
ssh (SSH key pair):
git:
auth: ssh
secretRef:
name: git-ssh-key # Secret với key: sshPrivate key stored trong Secret. SSH fingerprint của Git server phải được xác nhận trước hoặc noSSLVerify: true (không khuyến khích production).
none (public repo):
git:
auth: noneChỉ dùng cho public repos, không phù hợp production.
Branch, Tag, và Commit Pinning
git:
branch: main # Track HEAD của branch (default)
# HOẶC
revision: v1.2.3 # Pin vào specific tag
# HOẶC
revision: a1b2c3d4 # Pin vào specific commit SHABranch tracking (dynamic): Mỗi push lên branch được apply tự động sau polling interval. Phù hợp cho GitOps flow liên tục.
Tag pinning (semi-static): Sync theo tag. Để update, phải update spec.git.revision. Phù hợp khi muốn explicit "release" process.
Commit SHA pinning (fully static): Không bao giờ thay đổi trừ khi explicit update. Phù hợp cho environments cần audit trail chặt chẽ (có thể trace chính xác commit nào đang chạy trên cluster).
Commit SHA pinning đặc biệt có giá trị trong regulated environments: bạn có thể prove "tại thời điểm audit, cluster X đang run commit SHA Y, tương ứng với change Z được approved bởi engineer W".
OCI Source — Container Image Làm Config Bundle
Tại Sao OCI Source
OCI (Open Container Initiative) source là cơ chế pull Kubernetes configs từ container image registry thay vì Git. Ý tưởng: đóng gói configs vào container image và distribute như container images thông thường.
Lợi thế so với Git:
- Versioning rõ ràng hơn: Container image tags (v1.2.3) là immutable (với digest), không như Git tags có thể bị move
- Access control tốt hơn: Container Registry/Artifact Registry có fine-grained IAM, không cần SSH keys hay PATs
- Integration với CI/CD pipeline: Pipeline build Helm chart → render → đóng gói thành OCI image → push → Config Sync pull. Toàn bộ flow là container-native
- Performance với large configs: OCI layer caching giảm bandwidth so với Git clone cho large repos
Hạn chế:
- Audit trail kém hơn Git: Git có commit history tự nhiên, OCI images cần additional tools để track history
- Không thể xem diff "ở giữa": Phải compare layer-by-layer hoặc unpack images
- Config Sync chỉ support
tarhoặctar+gzipformat cho OCI layers — không phải mọi OCI image đều work
Cấu Hình OCI Source
apiVersion: configsync.gke.io/v1beta1
kind: RootSync
metadata:
name: root-sync
namespace: config-management-system
spec:
sourceType: oci
oci:
image: us-docker.pkg.dev/my-project/config-registry/fleet-config:v1.2.3
dir: / # Thư mục trong image để mount configs
auth: gcpserviceaccount
gcpServiceAccountEmail: config-sync@my-project.iam.gserviceaccount.comOCI image structure cần chứa configs theo flat hoặc hierarchical structure. Config Sync unpack image và read configs từ dir path được chỉ định.
Để push config image:
# Đóng gói configs
tar -czvf configs.tar.gz -C ./k8s-configs .
# Build OCI image từ configs
crane append -f configs.tar.gz \
-t us-docker.pkg.dev/my-project/config-registry/fleet-config:v1.2.3
# Hoặc dùng ko tool của Google
ko build ./config-bundle --image-refs=outputDigest vs Tag Reference
Khuyến nghị production: dùng digest thay vì tag:
oci:
image: us-docker.pkg.dev/my-project/config-registry/fleet-config@sha256:abc123...Image digest là immutable — cùng digest luôn trỏ đến cùng content. Tag có thể bị overwrite (mutable tags như latest là anti-pattern đặc biệt nguy hiểm). Dùng digest đảm bảo predictability và audit trail rõ ràng.
Helm Source — Chart Rendering Bên Trong Config Sync
Helm Pipeline Trong Config Sync
Config Sync có thể pull Helm charts và render chúng thành Kubernetes manifests trước khi apply. Khác với helm install truyền thống, Config Sync render Helm chart thành static manifests rồi manage chúng như bình thường — không dùng Helm tiller hay Helm release state.
apiVersion: configsync.gke.io/v1beta1
kind: RootSync
metadata:
name: monitoring-sync
namespace: config-management-system
spec:
sourceType: helm
helm:
repo: https://prometheus-community.github.io/helm-charts
chart: kube-prometheus-stack
version: "55.5.0" # Phải pin version cho reproducibility
releaseName: monitoring
namespace: monitoring
values:
prometheus:
retention: 30d
grafana:
adminPassword:
secretKeyRef:
name: grafana-credentials
key: password
auth: none # Public chart repos thường là noneHydration pipeline cho Helm:
- Source container fetch chart từ Helm repo (OCI hoặc HTTP)
- Hydration container run
helm templatevới values - Output: rendered Kubernetes manifests (plain YAML)
- Reconciler apply manifests như bình thường
Lưu ý quan trọng: Theo documentation, "Config Sync doesn't support configuring helm as the source type using the Google Cloud console or the Google Cloud CLI." Phải dùng kubectl apply trực tiếp với RootSync/RepoSync manifest.
Giới Hạn Của Helm Source
Không có Helm hooks: helm.sh/hook annotations bị ignored. Config Sync không chạy pre-install, post-upgrade hooks. Nếu chart phụ thuộc vào hooks (ví dụ database migration), cần giải quyết theo cách khác.
Không có Helm rollback: Config Sync không có concept "helm rollback". Rollback = cập nhật version trong RootSync spec và commit lên Git.
Values complexity: Helm values phức tạp (nested references, conditional values) có thể gây khó khăn khi quản lý qua RootSync spec. Khuyến nghị: dùng valuesFileRefs trỏ đến ConfigMap chứa values thay vì inline values khi values phức tạp.
Chart version pinning là bắt buộc: Không dùng version: "*" hay version: "latest" — không phải Helm repo concept. Phải pin exact version. Thiếu version pinning = non-deterministic sync behavior.
Hierarchical vs Unstructured Repository
Unstructured Repository
Đơn giản nhất: tất cả Kubernetes manifests nằm trong một thư mục (hoặc ít thư mục), Config Sync apply tất cả lên cluster.
fleet-config-repo/
├── cluster-a/
│ ├── namespaces.yaml
│ ├── clusterroles.yaml
│ └── apps/
│ ├── payments.yaml
│ └── auth.yaml
└── cluster-b/
├── namespaces.yaml
└── apps/
└── payments.yamlRootSync của cluster-a point vào cluster-a/, cluster-b point vào cluster-b/. Simple, nhưng không scale tốt khi:
- Nhiều clusters share config (duplicate YAML)
- Platform config và app config cần different RBAC (ai được edit gì)
Hierarchical Repository
Hierarchical repo của Config Sync là một khái niệm cụ thể: directory structure phản ánh Kubernetes resource hierarchy, cho phép Config Sync áp dụng special semantics:
hierarchical-repo/
├── cluster/ # Cluster-scoped resources
│ ├── clusterroles.yaml
│ └── clusterrolebindings.yaml
├── namespaces/ # Namespace-level configs (apply cho mọi namespace)
│ ├── default/
│ │ └── limitrange.yaml
│ └── _hierarchy/ # Templates áp cho tất cả namespaces (nếu dùng HNC)
└── system/ # System configs (ví dụ Config Sync configuration itself)Trong hierarchical mode, files trong namespaces/ được automatically scoped đến namespace tương ứng, và một số configs trong namespaces/_default/ được apply như default cho tất cả namespaces.
Tuy nhiên, theo Config Sync documentation, hierarchical mode có limitations và Google hiện khuyến nghị unstructured mode cho hầu hết use cases vì linh hoạt hơn. Hierarchical mode chủ yếu useful khi tích hợp với Hierarchical Namespace Controller.
Pattern Tổ Chức Cho Fleet Ở Scale
Pattern 1: Mono-Repo Với Cluster Directories
Phù hợp với: fleet nhỏ đến trung bình (< 20 clusters), platform team trung tâm quản lý tất cả.
fleet-config-repo/
├── base/ # Shared configs
│ ├── networking/
│ │ ├── network-policies.yaml
│ │ └── pod-security.yaml
│ └── rbac/
│ └── common-roles.yaml
├── clusters/
│ ├── prod-us-east1/
│ │ ├── kustomization.yaml # Extends base + regional overrides
│ │ └── overrides/
│ │ └── resource-limits.yaml
│ ├── prod-eu-west1/
│ │ ├── kustomization.yaml
│ │ └── overrides/
│ │ └── gdpr-policies.yaml
│ └── staging-us-central1/
│ └── kustomization.yaml
└── teams/
├── payments/ # App team configs (managed by payments team)
│ └── ...
└── auth/
└── ...Mỗi cluster có RootSync trỏ vào clusters/{cluster-name}/. Kustomize overlays cho phép base configs được reused với cluster-specific overrides.
Limitation: Với 50+ clusters, clusters/ directory trở nên khó navigate. Cross-cluster diffs phức tạp.
Pattern 2: Policy Repo Riêng + App Repos Riêng (Delegation Model)
Phù hợp với: fleet lớn, platform team và app teams tách biệt, clear ownership boundaries.
Platform Repo (managed by platform team):
fleet-platform-config/
├── cluster-policies/ # Apply cho mọi cluster
│ ├── psp-restricted.yaml
│ ├── network-policies-default.yaml
│ └── opa-constraints/
└── namespaces/ # Tạo namespaces, tạo RepoSync delegation
├── payments/
│ ├── namespace.yaml
│ └── reposync.yaml # RepoSync trỏ vào payments team repo
└── auth/
├── namespace.yaml
└── reposync.yaml # RepoSync trỏ vào auth team repo
App Repos (managed by app teams):
payments-config/ # Payments team quản lý
├── deployment.yaml
├── service.yaml
└── configmap.yaml
auth-config/ # Auth team quản lý
├── deployment.yaml
└── ...Platform team's RootSync sync fleet-platform-config/ lên mọi cluster — bao gồm cả reposync.yaml objects. Kubernetes apply những RepoSync objects này, sau đó Config Sync operator tạo reconciler pods cho chúng, và payments-config được synced bởi reconciler đó.
Đây là "meta-GitOps": dùng Config Sync để deploy Config Sync configuration. Platform team control namespace và RepoSync creation; app teams control content của namespace.
# Ví dụ reposync.yaml được platform team manage
apiVersion: configsync.gke.io/v1beta1
kind: RepoSync
metadata:
name: payments-sync
namespace: payments
spec:
sourceType: git
git:
repo: https://github.com/myorg/payments-config.git
branch: main
auth: gcpserviceaccount
gcpServiceAccountEmail: payments-config-sync@my-project.iam.gserviceaccount.comPattern 3: OCI-Based Fleet Config Distribution
Phù hợp với: tổ chức đã có container registry infrastructure mạnh, muốn immutable config bundles.
CI Pipeline:
1. Platform team commit policy changes → trigger CI
2. CI build Kustomize overlays cho mọi cluster variant
3. Render thành static YAML
4. Bundle thành OCI image: config-registry/fleet-policies:v1.2.3@sha256:...
5. Push đến Artifact Registry
RootSync Configuration:
spec:
sourceType: oci
oci:
image: us-docker.pkg.dev/platform/config-registry/fleet-policies@sha256:abcUpdate cluster config = update image digest trong RootSync spec. Audit trail: xem Artifact Registry image history.
Trade-off: Immutability và performance tốt, nhưng "git history" của configs phức tạp hơn — phải track image builds, không phải git commits trực tiếp.
Kết Hợp Sources Trên Cùng Cluster
Một cluster có thể có nhiều RootSync và RepoSync objects, mỗi cái pull từ source khác nhau:
cluster-prod-us-east1:
├── RootSync "platform-policies" → Git: fleet-platform-config (platform team)
├── RootSync "monitoring-stack" → Helm: kube-prometheus-stack (infra team)
├── RepoSync "payments" (namespace) → Git: payments-config (payments team)
└── RepoSync "auth" (namespace) → OCI: auth-config-image (auth team)Config Sync operator quản lý independent reconciler pods cho mỗi sync. Chúng chạy song song, không phụ thuộc vào nhau. Nếu payments-config sync fail, monitoring-stack không bị ảnh hưởng.
Conflict resolution khi nhiều syncs: Nếu RootSync "platform-policies" apply một NetworkPolicy trong namespace payments, và RepoSync "payments" cũng try apply NetworkPolicy với cùng name — SSA conflict sẽ xảy ra. Platform team phải thiết kế clear ownership boundary để tránh overlap.