- Published on
Triển khai GitOps và có cấu trúc với Kro, Kargo, Argo CD và RGD
- Authors
- Name
- Bạch Đăng Tuấn
- Occupation
- Kỹ sư công nghệ thông tin
- Zalo: 0934.01.07.04
🚀 From Kro RGD to Full GitOps: How I Built a Clean Deployment Flow with Argo CD
Nếu bạn từng phải sửa ba file YAML chỉ để đổi version Docker image, thì bài viết này chính là dành cho bạn.
📑 Mục lục
- Tại sao tôi cần RGD
- Giới thiệu Kro và RGD là gì
- Viết RGD đầu tiên
- Template hóa tài nguyên Kubernetes
- Tạo file instance.yaml
- Tích hợp với Argo CD và Kargo
- Vấn đề thực tế và cách tôi xử lý
- Vị trí của Kro trong kiến trúc GitOps
- Bonus: Setup theo môi trường
- Tiếp theo: Cấu trúc GitOps repo clean
🧩 Tại sao tôi cần RGD
Trước đây, tôi phải:
- Sửa 3 file YAML để cập nhật một tag image.
- Mỗi lần sửa lại phải mở PR, review, merge, Argo CD mới sync.
Tôi muốn một cách đơn giản hơn:
✅ Chỉ cần chỉnh 1 file, mọi thứ còn lại tự render.
✅ Không còn cảnh copy-paste cấu hình giữa các dự án.
🧠 Giới thiệu Kro và RGD là gì
Kro là một GitOps templating engine đơn giản nhưng mạnh mẽ.
Khác với Helm:
- Không có
values.yaml
lồng nhau rối rắm. - Không có
_helpers.tpl
khó đọc. - Không cần đóng gói chart.
👉 Cốt lõi của Kro là ResourceGraphDefinition (RGD).
RGD định nghĩa:
- Cấu trúc schema
- Template tạo ra gì (Deployment, Service,...)
- Giá trị lấy từ đâu (instance.yaml)
🛠 Viết RGD đầu tiên
Tôi bắt đầu với một service frontend đơn giản:
- 1 ConfigMap (chứa API URL)
- 1 Deployment (image, replicas)
- 1 Service (port)
Schema mẫu:
spec:
name: string | default=frontend
namespace: string | default=develop
values:
configMap:
data:
API_HTTP_URL: string
TIME_ZONE: string | default="XXX/XXX"
deployment:
image: string
tag: string
replicas: integer | default=1
service:
port: integer | default=3000
targetPort: integer | default=3000
📄 Template hoá tài nguyên Kubernetes
Sau khi có schema, tôi định nghĩa các template mà nó sẽ sinh ra.
Ví dụ với Deployment:
- id: deploy
template:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${schema.spec.name}
namespace: ${schema.spec.namespace}
spec:
replicas: ${schema.spec.values.deployment.replicas}
template:
spec:
containers:
- image: ${schema.spec.values.deployment.image}:${schema.spec.values.deployment.tag}
✅ Không có logic phức tạp.
✅ Không có templating kiểu Helm.
✅ Chỉ là tham chiếu trực tiếp đến schema.
📦 Tạo file instance.yaml
instance.yaml
là nơi cung cấp giá trị thực tế để Kro render manifests.
apiVersion: kro.run/v1alpha1
kind: FrontendAppV2
metadata:
name: wsp-frontend
namespace: develop
spec:
name: wsp-frontend
namespace: develop
values:
configMap:
data:
API_HTTP_URL: https://example.com/api
TIME_ZONE: Asia/Bangkok
deployment:
image: docker.io/wsp-frontend
tag: "1.0.1"
replicas: 1
service:
port: 3000
targetPort: 3000
Tôi commit file này vào Git. Argo CD tự sync.
🔁 Tích hợp với Argo CD và Kargo
Workflow GitOps hoàn chỉnh:
- Push image mới lên registry
- Kargo detect → tạo Freight
- Stage thực hiện
yaml-update
lên instance.yaml - Commit thay đổi vào Git
- Argo CD sync cluster
- Kro detect instance mới → apply
yaml-update snippet:
- key: spec.values.deployment.tag
value: ${{ quote(imageFrom(vars.imageRepo, warehouse(vars.warehouseName)).Tag) }}
Tự động hoàn toàn từ image tag → cluster update.
💥 Vấn đề thực tế và cách tôi xử lý
1️⃣ Resource không apply, không báo lỗi
→ Do thiếu type
trong schema.
2️⃣ Tag bị biến thành số (1.0.1 → 1)
→ Dùng quote()
trong Kargo để ép về chuỗi.
3️⃣ Kro không apply vì không khác biệt
→ Log: Skipping update due to unchanged generation
4️⃣ Debug phải xem log controller
→ Kro không có giao diện UI mạnh, nên cần xem log để biết có apply hay không.
🧭 Vị trí của Kro trong kiến trúc GitOps
Docker push → Kargo → Git commit (instance.yaml) → Argo CD → Kro render → K8s apply
Kro cho phép:
- Schema hoá rõ ràng
- Template hoá chuẩn
- Instance control qua Git
Tôi không cần Helm, không cần values.yaml
, không cần overlay Kustomize.
🔎 Bonus: Setup theo môi trường
- Mỗi env có 1
instance.yaml
riêng - Dùng ApplicationSet cho Argo CD
develop/
,staging/
,production/
là các path Git tách biệt
🔜 Tiếp theo: Cấu trúc GitOps repo clean
Ở phần tiếp theo, tôi sẽ:
- Chia sẻ layout Git cho GitOps (theo env + service)
- Cách dùng ApplicationSet
- Tạo automation pipeline từ image push → cluster sync