Skaffold Integration — Render & Deploy Pipeline
Tại sao Skaffold tồn tại trong Cloud Deploy
Câu hỏi đầu tiên nhiều engineer đặt ra: tại sao Cloud Deploy không trực tiếp dùng kubectl apply? Tại sao cần thêm một layer Skaffold?
Câu trả lời nằm ở vấn đề rendering: Kubernetes manifests hiếm khi là plain YAML tĩnh trong production. Chúng cần được render từ:
- Helm charts với values khác nhau per environment
- Kustomize overlays với patches per environment
- Plain YAML với image substitution (placeholder → actual image digest)
Nếu Cloud Deploy tích hợp trực tiếp với từng rendering tool, nó phải hiểu semantics của Helm, Kustomize, và mọi tool khác. Thay vào đó, Cloud Deploy delegates rendering cho Skaffold — một tool abstraction layer đã hỗ trợ tất cả rendering tools phổ biến.
Điều này tạo ra sự tách biệt rõ ràng:
- Cloud Deploy quản lý promotion workflow (ai deploy gì, khi nào, đến đâu)
- Skaffold quản lý how to render và apply manifests
Theo tài liệu Cloud Deploy: "Cloud Deploy separates rendering tools from the delivery pipeline." Đây là kiến trúc cố ý — pipeline definition không phụ thuộc vào rendering tool, cho phép thay đổi rendering tool mà không cần thay đổi pipeline.
Skaffold trong Cloud Deploy — Không Phải "Toàn Bộ" Skaffold
Điều cần hiểu rõ: Cloud Deploy chỉ dùng một subset các tính năng Skaffold:
skaffold diagnose— validate configskaffold render— render manifestsskaffold apply— apply manifests lên cluster
Cloud Deploy không dùng các tính năng Skaffold khác như local development workflow, file sync, hot reload, hay build. Container images đã được build bởi CI pipeline (Cloud Build hoặc system khác) trước khi đến Cloud Deploy.
Skaffold được pre-installed trong Cloud Build worker environment của Cloud Deploy — không cần cài thêm. Version Skaffold được chọn tự động dựa trên apiVersion trong skaffold.yaml.
Cấu Trúc skaffold.yaml cho Cloud Deploy
Minimal skaffold.yaml (plain YAML)
apiVersion: skaffold/v4beta11
kind: Config
metadata:
name: my-app
manifests:
rawYaml:
- k8s/*.yamlTrường manifests.rawYaml chỉ định glob pattern cho Kubernetes manifest files. Khi render, Skaffold sẽ:
- Load tất cả files matching pattern
- Thực hiện image substitution: thay
image: my-app-image(placeholder) bằng actual image digest được truyền vào qua--imagesflag - Output rendered YAML
skaffold.yaml với Helm
apiVersion: skaffold/v4beta11
kind: Config
metadata:
name: my-app
manifests:
helm:
releases:
- name: my-app
chartPath: charts/my-app
valuesFiles:
- charts/my-app/values.yaml
setValueTemplates:
image.repository: "{{.IMAGE_REPO_my_app}}"
image.tag: "{{.IMAGE_TAG_my_app}}@{{.IMAGE_DIGEST_my_app}}"Với Helm, Skaffold gọi helm template để render chart thành Kubernetes YAML. Image substitution thông qua setValueTemplates — Skaffold inject image info vào Helm values.
skaffold.yaml với Kustomize
apiVersion: skaffold/v4beta11
kind: Config
metadata:
name: my-app
manifests:
kustomize:
paths:
- k8s/baseVới Kustomize, Skaffold gọi kustomize build và thực hiện image substitution sau khi render.
Profiles cho Multi-Environment
Profiles là tính năng quan trọng nhất cho Cloud Deploy integration:
apiVersion: skaffold/v4beta11
kind: Config
metadata:
name: my-app
manifests:
rawYaml:
- k8s/base/*.yaml
profiles:
- name: staging
manifests:
kustomize:
paths:
- k8s/overlays/staging
- name: production
manifests:
kustomize:
paths:
- k8s/overlays/productionPipeline definition reference profiles:
serialPipeline:
stages:
- targetId: dev-gke # Không có profile → dùng base config
- targetId: staging-gke
profiles: [staging] # Dùng Kustomize overlay staging
- targetId: prod-gke
profiles: [production] # Dùng Kustomize overlay productionKhi render Release, Cloud Deploy gọi skaffold render một lần per stage với profile tương ứng. Mỗi stage nhận rendered manifests riêng biệt, stored trong GCS.
Render Phase — Chi Tiết Bên Trong
Khi gcloud deploy releases create được gọi:
Bước 1: skaffold diagnose
skaffold diagnose -f skaffold.yamlValidate Skaffold config: file syntax, referenced files tồn tại, chart dependencies đã download. Nếu fail → Release creation fail ngay, không proceed sang render.
Bước 2: skaffold render (per stage)
skaffold render -f skaffold.yaml \
--images=my-app=us-central1-docker.pkg.dev/project/repo/my-app@sha256:abc... \
--profile=staging \
--output=rendered-manifest.yamlSkaffold:
- Load manifests theo profile
- Thực hiện image substitution: scan tất cả container
image:fields, thay placeholder bằng actual image từ--imagesflag - Nếu dùng Helm: gọi
helm template, inject images vào values - Nếu dùng Kustomize: gọi
kustomize build, sau đó image substitution - Output ra
rendered-manifest.yaml
Output của render phase là pure Kubernetes YAML — không còn Helm templates, không còn Kustomize overlays. Đây là gì sẽ được apply lên cluster sau này.
Cloud Deploy lưu output này vào GCS. Từ thời điểm này, Release đã "frozen" — manifests không thay đổi dù Skaffold config hay Helm chart thay đổi.
Image Substitution Mechanics
Đây là điểm thường gây nhầm lẫn. Skaffold dùng placeholder matching để biết field nào cần substitute:
# Trong manifest (trước render):
containers:
- name: my-app
image: my-app-image # Đây là placeholder name
# Command:
skaffold render --images=my-app-image=repo/my-app@sha256:abc...
# Sau render:
containers:
- name: my-app
image: repo/my-app@sha256:abc... # ReplacedPlaceholder phải match image name được pass qua --images flag. Nếu không match → không substitute, manifest chứa placeholder string → deploy fail hoặc pull image sai.
Deploy Phase — skaffold apply
Khi Rollout vào trạng thái IN_PROGRESS:
skaffold apply rendered-manifest.yaml \
--kube-context=gke_project_us-central1_my-clusterskaffold apply về bản chất là server-side apply với một số logic thêm:
- Load rendered manifests từ GCS
- Gọi
kubectl apply --server-sidelên target cluster - Wait cho Kubernetes resources converge (Deployments rollout hoàn thành)
- Check status của resources
Tại sao server-side apply? Server-side apply (SSA) cho phép multiple controllers quản lý cùng một resource mà không conflict (field ownership). Cloud Deploy sử dụng SSA để không "steal ownership" của fields từ các controllers khác (như HPA managing replicas, hay Cert-Manager managing TLS certs).
Connection đến Target Cluster
Cloud Deploy không access cluster trực tiếp từ control plane của mình. Thay vào đó, Cloud Build worker (khi chạy skaffold apply) cần network connectivity đến cluster API server:
- Public cluster: Cloud Build worker dùng public endpoint → no special config needed
- Private cluster: Cần Private Worker Pool trong cùng VPC với cluster, hoặc PSC endpoint, hoặc VPN/Interconnect
Đây là failure mode phổ biến: deploy fail với "connection refused" hoặc "timeout" khi Cloud Build không thể reach private cluster API server.
Skaffold Modules — Tổ Chức Code Phức Tạp
Với applications có nhiều components (microservices), Skaffold hỗ trợ modules:
# skaffold.yaml
apiVersion: skaffold/v4beta11
kind: Config
metadata:
name: platform
requires:
- configs:
- path: ./services/api/skaffold.yaml
- path: ./services/worker/skaffold.yaml
- path: ./infrastructure/skaffold.yamlMỗi service/component có skaffold.yaml riêng. File cha aggregate chúng. Khi Cloud Deploy render, nó render tất cả modules và merge outputs.
Modules cho phép:
- Teams độc lập maintain Skaffold config của service mình
- Selective rendering (chỉ render module cần thiết)
- Shared base configuration qua inheritance
Execution Environment — Nơi Skaffold Chạy
Cả render và deploy đều chạy trong Cloud Build execution environment. Có thể customize environment này:
# Trong delivery pipeline stage:
stages:
- targetId: prod-gke
executionConfigs:
- usages: [RENDER, DEPLOY]
privatePool:
workerPool: projects/my-project/locations/us-central1/workerPools/private-pool
artifactStorage: gs://my-bucket/artifacts
serviceAccount: deploy-sa@my-project.iam.gserviceaccount.comPrivate Worker Pool là bắt buộc khi:
- Target cluster có private endpoint (không có public IP)
- Muốn isolate build workers trong VPC riêng
- Cần egress qua Cloud NAT hoặc specific routing
serviceAccount trong executionConfigs xác định identity mà Cloud Build jobs chạy với — đây là SA cần có permissions để access cluster, pull images, read GCS.
Giới Hạn và Trade-offs
Giới hạn Skaffold version
Cloud Deploy pin Skaffold version dựa trên apiVersion trong skaffold.yaml. Khi Skaffold release breaking changes, cần update apiVersion để dùng features mới. Không phải tất cả Skaffold features đều được hỗ trợ trong Cloud Deploy context.
Render time và Release creation latency
Render phase chạy Cloud Build job. Với pipeline có nhiều stages, mỗi stage cần riêng Cloud Build job → render time có thể là 2-5 phút per stage. Với pipeline 3 stages, Release creation có thể mất 5-15 phút trước khi Rollout đầu tiên bắt đầu.
Cách giảm latency: parallel rendering (Cloud Deploy tự động render stages song song nếu có thể), optimize Skaffold config để không download dependencies không cần thiết.
Không hỗ trợ runtime generation
Skaffold render là static rendering — không thể generate manifest dynamically dựa trên runtime state (ví dụ: query database để lấy config, call API). Nếu cần dynamic config, phải pre-generate manifests trong CI và pass vào Cloud Deploy.