# Crossplane trong 40 ngày

## PHASE 0 - Tuần 0: Nền tảng bắt buộc trước khi học Crossplane (3 ngày)

### Ngày 0.1 - Kubernetes API machinery

*   CRD là gì thực sự: OpenAPI v3 schema, `apiVersion`/`kind`/`group`, cách `kube-apiserver` lưu trữ resource tuỳ biến trong etcd.
    
*   Cách hoạt động của Admission Webhooks (Validating/Mutating) - Crossplane dùng chúng để validate Composition, XRD.
    
*   `CustomResourceDefinition` versioning, conversion webhook - vì XRD của bạn sẽ có nhiều version theo thời gian.
    

**Thực hành**: viết một CRD tay (không dùng framework), apply vào kind, quan sát OpenAPI schema qua `kubectl explain`.

### Ngày 0.2 - Mẫu hình Controller (controller-runtime)

*   Reconciler interface: `Reconcile(ctx, req) (Result, error)` - vòng lặp *level-triggered*, không phải *edge-triggered*. Đây là khái niệm quan trọng nhất bạn cần nội tâm hoá.
    
*   Informer/Lister cache, work queue, rate limiting/backoff khi reconcile lỗi.
    
*   Owner References và Garbage Collection - vì XR "compose" ra MR bằng owner reference, không phải bằng một cơ chế bí ẩn nào khác.
    
*   Finalizers - vì sao xoá một Managed Resource đôi khi bị "stuck Terminating".
    

**Thực hành**: viết một controller tối giản bằng `controller-runtime` (Go) reconcile một ConfigMap giả lập - không liên quan Crossplane, chỉ để hiểu vòng lặp.

### Ngày 0.3 - OCI & Package registry cơ bản

*   Crossplane Package (`xpkg`) thực chất là gì: một OCI image chứa CRD + metadata, không phải Helm chart.
    
*   `docker manifest`, layer, digest, image signing (cosign) - vì bạn sẽ ký và verify Provider package ở tuần 5.
    

**Thực hành**: build một OCI image tối giản bằng `crane`/`docker buildx`, push lên registry cá nhân (ghcr.io), inspect layer.

## PHASE 1 - Tuần 1: Kiến trúc Crossplane & Package Manager

### Ngày 1 - Tổng quan kiến trúc của Crossplane

*   Crossplane core = 1 Deployment gồm: **Package Manager** (cài/gỡ Provider, Configuration, Function packages) + **Composition Engine** (reconcile XR → composed resources).
    
*   Provider = một Deployment riêng, mỗi Provider chạy controller riêng cho từng loại Managed Resource (MR) nó hỗ trợ.
    
*   Function = một Deployment/Pod chạy như gRPC server, được Composition Engine gọi qua `RunFunctionRequest`/`RunFunctionResponse` (giao thức **KRM Functions**).
    
*   Cài Crossplane v2.3 lên kind bằng Helm, dùng CLI mới: `crossplane xpkg`, `crossplane beta trace`, `crossplane render`.
    

**Bài tập:**

1.  Vẽ sơ đồ luồng dữ liệu: `kubectl apply XR` → Composition Engine → gọi Function pipeline → tạo MR → Provider controller → gọi cloud API.
    
2.  Cài `crossplane-cli` v2, chạy `crossplane version` để xác nhận CLI và control plane cùng version.
    
3.  Kiểm tra Pod của core Crossplane, đọc log để thấy chính xác controller nào đang chạy (`kubectl logs -n crossplane-system deploy/crossplane -f`).
    

### Ngày 2 - xpkg format & Package Manager internals

*   Cấu trúc 1 package: `package.yaml` (meta) + CRD YAMLs, đóng gói trong OCI image theo `xpkg` spec.
    
*   3 loại package: `Provider`, `Configuration` (bundle nhiều XRD+Composition), `Function`.
    
*   Dependency resolution: `Configuration` khai báo `dependsOn`, Package Manager tự cài Provider/Function phụ thuộc.
    
*   `ImageConfig` (từ v1.18, mở rộng ở v2.2): cấu hình registry auth, image rewrite, và - mới trong v2.2 - gán `DeploymentRuntimeConfig` theo prefix ảnh, áp dụng cả cho package cài gián tiếp qua dependency.
    
*   v2 bỏ default registry: mọi package reference **bắt buộc phải fully-qualified** (`xpkg.upbound.io/...` hoặc registry riêng).
    
*   Ký & verify package bằng cosign; `Provider` deletion protection (alpha v2.3) chặn xoá nhầm Provider khi còn MR đang tồn tại.
    

**Bài tập:**

1.  Cài `provider-aws-s3` bằng địa chỉ image fully-qualified, quan sát `ProviderRevision` được tạo ra.
    
2.  Tạo một `ImageConfig` để trỏ registry mirror nội bộ cho mọi package có prefix `xpkg.upbound.io/upbound`.
    
3.  Đọc source `package.yaml` của một Configuration public trên GitHub, xác định `dependsOn` của nó.
    

### Ngày 3 - Managed Resources & Provider architecture

*   Vòng đời MR: `Observe → Create/Update/Delete` - pattern `managed.ExternalClient` trong `crossplane-runtime`.
    
*   `ExternalName` annotation - cách Crossplane map 1 K8s object với 1 resource cloud thật.
    
*   Deletion policy (`Delete`/`Orphan`), Management policy (`ObserveOnly` để import tài nguyên có sẵn mà không quản lý full lifecycle).
    
*   Late initialization: Provider tự điền field còn thiếu từ giá trị cloud trả về sau khi Create.
    
*   `ProviderConfig` vs `DeploymentRuntimeConfig` - cái đầu là credential/config gọi cloud API, cái sau là cấu hình runtime cho chính Pod của Provider (resource limits, env vars, service account).
    

**Bài tập:**

1.  Tạo S3 bucket qua MR, sau đó set `managementPolicies: ["ObserveOnly"]` và quan sát Crossplane ngừng ghi đè.
    
2.  Tạo `DeploymentRuntimeConfig` giới hạn CPU/memory cho Provider AWS, gán qua `spec.runtimeConfigRef`.
    
3.  Với 1 MR đã tạo, dùng `crossplane beta trace` để xem chuỗi Observe/Ready/Synced hiện tại.
    

### Ngày 4 - Managed Resource Definitions (MRD)

*   Vấn đề MRD giải quyết: Provider lớn (AWS có hàng trăm loại MR) cài hết CRD gây phình etcd/apiserver.
    
*   MRD cho phép **activate có chọn lọc** - chỉ cài CRD của MR bạn thực sự dùng.
    

**Bài tập:**

1.  Cài `provider-aws` phiên bản hỗ trợ MRD, activate chỉ `Bucket` và `RDSInstance`, xác nhận CRD khác không tồn tại trong cluster.
    
2.  So sánh số lượng CRD/dung lượng etcd trước và sau khi dùng MRD.
    

### Ngày 5 - Ôn tập + Lab tích hợp tuần 1

*   Lab: cài Crossplane v2.3, cài Provider AWS + GCP với MRD chọn lọc, tạo 1 S3 bucket và 1 Cloud SQL bằng MR thuần (chưa dùng Composition).
    

## PHASE 2 - Tuần 2: Composition v2 bằng Functions

### Ngày 6 - XRD v2: namespaced XR

*   XRD v2 có `spec.scope: Namespaced | Cluster | LegacyCluster`. Mặc định XR giờ **namespaced** - không còn cần khái niệm `Claim (XRC)` để có namespace-scoping riêng như v1.
    
*   `[v1 legacy]` Ghi chú: v1 dùng `XR` (cluster-scoped) + `Claim/XRC` (namespaced) làm hai resource riêng. v2 hợp nhất lại: bản thân XR đã namespaced.
    
*   Thiết kế schema XRD tốt: OpenAPI validation, default values, `status` subresource cho output.
    

**Bài tập:**

1.  Viết một XRD `scope: Namespaced` cho resource `XDatabase` với field `engine`, `size`.
    
2.  So sánh với 1 XRD `scope: LegacyCluster` có `claimNames` - apply cả hai, quan sát khác biệt khi tạo instance.
    

### Ngày 7 - Composition Function pipeline & giao thức KRM Functions

*   Một Composition = `spec.mode: Pipeline` + danh sách `pipeline[].functionRef` - mỗi bước nhận `RunFunctionRequest` (observed/desired state) và trả `RunFunctionResponse`.
    
*   Function chính thức thay thế P&T: `function-patch-and-transform` (do Crossplane maintain) - hoạt động giống P&T cũ nhưng chạy như 1 function trong pipeline, không phải native engine.
    
*   Các function cộng đồng phổ biến: `function-go-templating`, `function-kcl`, `function-cue`, `function-auto-ready`.
    
*   `RequiredResources`/`RequiredSchemas` (mới v2.2) - function có thể yêu cầu Crossplane cung cấp thêm resource/schema trước khi chạy tiếp - nền tảng cho logic phức tạp (vd: đọc 1 Secret trước khi tạo MR).
    

**Bài tập:**

1.  Viết 1 Composition dùng `function-patch-and-transform` để tạo `RDSInstance` (MySQL) + `EKSCluster` từ 1 XR duy nhất.
    
2.  Chuyển đổi thử 1 Composition `mode: Resources` cũ (nếu có mẫu) sang Pipeline bằng lệnh `crossplane beta convert pipeline-composition old.yaml -o new.yaml`.
    

### Ngày 8 - Viết Composition Function bằng Go (function-sdk-go)

*   Kiến trúc 1 Function: gRPC server implement `RunFunction`, input/output là Unstructured KRM object.
    
*   Scaffold bằng `function-sdk-go`, build local, test bằng `crossplane render` (không cần deploy).
    

**Bài tập:**

1.  Viết Function Go: tự động gắn tag `managed-by: crossplane`, `env: <namespace>` vào mọi resource được compose.
    
2.  Viết Function Go tạo thêm 1 DNS record (giả lập) khi phát hiện resource `LoadBalancer` trong desired state.
    
3.  Viết unit test cho Function bằng cách mock `RunFunctionRequest`.
    

### Ngày 9 - Viết Composition Function bằng Python (function-sdk-python)

*   Tương tự Go nhưng dùng SDK Python, phù hợp khi team quen Python hơn (vd: cần gọi thư viện ML/data để tính toán trước khi tạo resource).
    

**Bài tập:**

1.  Viết lại Function "auto-tag" ở Ngày 8 bằng Python, so sánh cold-start latency giữa 2 bản Go/Python.
    
2.  Viết Function Python gửi Slack notification khi 1 bước pipeline fail (dùng `webhook`).
    

### Ngày 10 - Testing & debugging Function pipeline

*   `crossplane render xr.yaml composition.yaml functions.yaml` - engine render "high-fidelity" ở v2.3 chạy **chính reconciler thật** thay vì bản giả lập riêng, nên output khớp 100% với hành vi in-cluster.
    
*   `crossplane beta validate` - validate Composition/XRD trước khi apply (dùng trong CI).
    
*   **Pipeline Inspector** (alpha, v2.2): sidecar nhận bản sao mọi `RunFunctionRequest/Response` giữa các bước - dùng để debug logic phức tạp nhiều bước mà không cần sửa code function.
    

**Bài tập:**

1.  Chạy `crossplane render` cho Composition WordPress ở Ngày 7, so sánh output khi đổi input.
    
2.  Bật Pipeline Inspector cho 1 Composition nhiều bước, quan sát request/response giữa từng function.
    
3.  Viết 1 CI job (GitHub Actions) chạy `crossplane beta validate` + `crossplane render` + so sánh snapshot (golden file testing).
    

## PHASE 3 - Tuần 3: Namespaced XR, Connection Details, Secrets, Runtime Config

### Ngày 11 - Compose bất kỳ Kubernetes resource nào

*   Điểm khác biệt lớn của v2: XR có thể compose **Deployment, Service, hoặc CRD của bên thứ ba** (vd: CloudNativePG Cluster) - không bắt buộc phải là Managed Resource.
    
*   Cần cấp quyền RBAC rõ ràng cho Crossplane compose resource ngoài Crossplane API.
    

**Bài tập:**

1.  Viết Composition tạo XR `App` compose ra: 1 `Deployment`, 1 `Service`, 1 `RDSInstance` - trong cùng namespace với XR.
    
2.  Cấp Role/RoleBinding tối thiểu để Crossplane compose được `apps/v1 Deployment`.
    

### Ngày 12 - Migration path: XRC (Claim) → namespaced XR

*   v1: người dùng cuối tạo `Claim` (namespaced) → Crossplane tạo `XR` (cluster-scoped) tương ứng.
    
*   v2: người dùng cuối tạo thẳng `XR` (đã namespaced) - bỏ tầng trung gian Claim.
    
*   **Chưa có tool tự động migrate** resource v1 cluster-scoped sang v2 namespaced (tính đến v2.3) - phải làm thủ công hoặc chờ tooling từ cộng đồng.
    
*   Best practice khi bắt đầu dự án mới: dùng namespaced XR ngay từ đầu, không cần thiết kế theo mô hình Claim cũ nữa.
    

**Bài tập:**

1.  So sánh 1 project mẫu viết theo style Claim (v1) và style namespaced XR (v2) cho cùng 1 use case WordPress.
    
2.  Đọc kỹ output của `crossplane beta upgrade check` trên 1 cluster v1 giả lập, liệt kê các resource cần sửa trước khi lên v2.
    

### Ngày 13 - Connection Details

*   v2 **xoá native connection-details support ở cấp XR** (chỉ MR vẫn giữ `writeConnectionSecretToRef`).
    
*   Cách tái tạo tính năng: dùng `function-patch-and-transform` - nó tự động compose 1 `Secret` gộp connection details của các resource con, đặt tên/namespace theo `spec.writeConnectionSecretToRef` trên XR.
    

**Bài tập:**

1.  Viết Composition có 2 MR đều publish connection detail (endpoint DB + password), gộp thành 1 Secret ở namespace của XR.
    
2.  Viết 1 Deployment (compose cùng XR) đọc Secret đó qua `envFrom.secretRef`.
    

### Ngày 14 - Quản lý secret thực tế: External Secrets Operator + Vault

*   Vì external secret store **bị xoá khỏi Crossplane native** ở v2, cách chuẩn production hiện nay: dùng **External Secrets Operator (ESO)** đọc từ Vault/AWS Secrets Manager, đồng bộ vào K8s Secret mà Crossplane compose tham chiếu tới - Crossplane không tự nói chuyện với Vault nữa.
    

**Bài tập:**

1.  Cài ESO, tạo `SecretStore` trỏ tới Vault, đồng bộ 1 secret DB password vào cluster.
    
2.  Compose XR tham chiếu Secret do ESO tạo (không phải Crossplane tạo).
    

### Ngày 15 - DeploymentRuntimeConfig chi tiết

*   Thay thế hoàn toàn `ControllerConfig` (deprecated từ v1.11, xoá ở v2).
    
*   Cấu hình: replica count, resource requests/limits, `serviceAccountName`, extra env var, args cho Provider pod (vd `--max-reconcile-rate`).
    
*   `ImageConfig` (Ngày 2) có thể gán `DeploymentRuntimeConfig` tự động theo prefix image - hữu ích khi Configuration cài Provider gián tiếp qua dependency mà bạn không apply trực tiếp.
    

**Bài tập:**

1.  Convert 1 `ControllerConfig` mẫu (nếu có từ hệ thống cũ) sang `DeploymentRuntimeConfig` bằng `crossplane beta convert deployment-runtime`.
    
2.  Set `--max-reconcile-rate=50` cho Provider AWS qua DeploymentRuntimeConfig, quan sát tốc độ reconcile tăng lên.
    

## PHASE 4 - Tuần 4: Viết Provider từ đầu bằng Go + crossplane-runtime

### Ngày 16 - Kiến trúc 1 Provider

*   `managed.ExternalConnecter.Connect()` → trả về `managed.ExternalClient` với 4 method: `Observe`, `Create`, `Update`, `Delete`.
    
*   Đọc source code thật của `provider-aws-s3` hoặc `provider-template` để thấy pattern thực tế (không lý thuyết suông).
    
*   Reconciler wrapper của `crossplane-runtime` tự lo: retry/backoff, status condition (`Ready`, `Synced`), event recording - bạn chỉ cần implement 4 method trên.
    

**Bài tập:**

1.  Clone `crossplane/provider-template`, đọc kỹ `internal/controller/.../reconciler.go`, vẽ lại sequence diagram Observe→Create.
    
2.  Xác định chỗ nào trong code xử lý `ExternalName`, chỗ nào xử lý late-init.
    

### Ngày 17 - Scaffold Provider bằng code generation

*   `provider-template` + `angryjet` (code-gen tool tạo `DeepCopy`, `ResourceSpec/Status` boilerplate từ struct Go).
    
*   Thiết kế API type cho resource tuỳ chỉnh "CoffeeShop" (`name`, `location`, `menu`) theo convention `ForProvider`/`AtProvider`.
    

**Bài tập:**

1.  Scaffold provider "provider-coffeeshop" từ template, generate CRD YAML từ Go struct.
    
2.  Viết `ProviderConfig` type cho provider này (credential tới 1 REST API giả lập).
    

### Ngày 18 - Implement CRUD cho external API

*   Viết `Observe`: gọi API, so sánh spec vs trạng thái thật, set `ResourceUpToDate`/`ResourceExists`.
    
*   Viết `Create`/`Update`/`Delete`, xử lý lỗi 404/409 đúng convention (không panic, trả `errors.Wrap`).
    
*   Xử lý idempotency: `Create` gọi 2 lần không được tạo trùng.
    

**Bài tập:**

1.  Dựng 1 REST API giả (Express/FastAPI) làm "cloud" cho CoffeeShop, implement đủ 4 method.
    
2.  Test toàn bộ vòng đời: apply → update field `menu` → xoá, xác nhận API backend phản ánh đúng.
    

### Ngày 19 - Testing Provider

*   Unit test: mock HTTP client, test riêng từng method `Observe/Create/Update/Delete` không cần cluster thật.
    
*   Integration test: chạy `envtest` (etcd + apiserver giả lập) + provider binary + backend giả lập, apply MR thật, assert trạng thái.
    
*   Test `crossplane render` cho Composition dùng resource "CoffeeShop" này.
    

**Bài tập:**

1.  Viết unit test coverage ≥ 80% cho `internal/controller`.
    
2.  Viết 1 integration test bằng `envtest` mô phỏng full lifecycle.
    

### Ngày 20 - Đóng gói & publish Provider

*   Build multi-arch OCI image, đóng gói theo `xpkg` spec (`crossplane xpkg build`), ký bằng cosign.
    
*   Semantic versioning cho Provider - vì `ProviderRevision` giữ lịch sử, breaking change API phải bump major.
    
*   Publish lên `ghcr.io`, viết `Provider` manifest fully-qualified để người khác cài.
    

**Bài tập:**

1.  Build và push `provider-coffeeshop:v0.1.0` lên ghcr.io cá nhân, cài vào cluster test bằng `Provider` manifest.
    
2.  Ký image bằng cosign, verify chữ ký trước khi cài (`crossplane xpkg verify` hoặc `cosign verify`).
    

## PHASE 5 - Tuần 5: CI/CD, GitOps, Multi-tenancy đúng cách, Policy

### Ngày 21 - GitOps với Argo CD/Flux

*   Pattern chuẩn: Git repo chứa XR/Composition/XRD YAML → Argo CD/Flux sync vào cluster → Crossplane reconcile.
    
*   App-of-apps pattern: tách repo "platform" (Composition/XRD, do platform team quản lý) khỏi repo "workload" (XR instance, do dev team quản lý).
    
*   Xử lý drift: Argo CD self-heal vs Crossplane tự sửa lại resource - tránh 2 controller "đánh nhau".
    

**Bài tập:**

1.  Setup Argo CD trỏ vào 1 Git repo chứa Composition WordPress, sync tự động.
    
2.  Tạo repo thứ hai chỉ chứa XR instance, để dev team tự tạo PR mà không cần quyền vào repo platform.
    

### Ngày 22 - CI pipeline cho Function & Provider

*   Pipeline chuẩn: `go test`/`pytest` → `crossplane beta validate` → `crossplane render` (golden-file diff) → build OCI → cosign sign → push → (optional) deploy staging.
    
*   Dùng `crossplane-diff` (dựa trên render engine mới ở v2.3) để preview thay đổi Composition trước khi merge - giống `terraform plan`.
    

**Bài tập:**

1.  Viết GitHub Actions pipeline đầy đủ các bước trên cho `provider-coffeeshop`.
    
2.  Thêm bước `crossplane-diff` vào PR check để reviewer thấy trước resource nào sẽ thay đổi.
    

### Ngày 23 - Multi-tenancy

1.  **Namespace isolation** (nhẹ nhất): mỗi team 1 namespace, XR namespaced (v2) tự nhiên cô lập theo namespace, RBAC giới hạn theo namespace.
    
2.  **Composition-level self-service**: platform team sở hữu Composition/XRD (cluster-scoped resource, cần quyền cao), dev team chỉ có quyền tạo XR trong namespace của họ - không được sửa Composition.
    
3.  **Control-plane-per-tenant** (cô lập mạnh nhất): mỗi tenant/BU có 1 Crossplane control plane riêng (self-hosted cluster riêng, hoặc dùng Upbound Spaces nếu dùng bản thương mại) - tránh "noisy neighbor" ở tầng controller.
    

**Bài tập:**

1.  Thiết kế RBAC: Role cho phép team A tạo/sửa XR `XDatabase` trong namespace `team-a`, nhưng không được sửa `Composition`/`XRD`.
    
2.  So sánh chi phí vận hành giữa pattern 1 và pattern 3 cho tổ chức 5 team.
    

### Ngày 24 - RBAC, ResourceQuota, NetworkPolicy cho control plane

*   RBAC 2 lớp: (a) ai được tạo XR/Claim, (b) `ProviderConfig` nào Crossplane dùng để nói chuyện với cloud - tách quyền dev khỏi credential cloud thật.
    
*   `ResourceQuota` theo namespace giới hạn số XR một team được tạo.
    
*   `NetworkPolicy` giới hạn Provider pod chỉ gọi ra ngoài internet tới cloud API cần thiết, chặn lateral movement.
    

**Bài tập:**

1.  Viết ClusterRole/Role tách biệt: `platform-admin` (sửa Composition/XRD) vs `app-developer` (chỉ tạo XR).
    
2.  Viết ResourceQuota giới hạn 10 XR `XDatabase` mỗi namespace.
    
3.  Viết NetworkPolicy chỉ cho phép Provider pod egress tới CIDR của AWS API endpoint.
    

### Ngày 25 - Policy enforcement thực tế bằng Kyverno/OPA Gatekeeper

*   Vì Crossplane **không có Policy Engine built-in**, policy validate ở tầng admission dùng Kyverno hoặc Gatekeeper - áp lên chính XR hoặc lên Composition.
    
*   Ví dụ policy thật: chặn XR tạo RDS instance class lớn hơn `db.t3.medium` ở namespace `dev`; bắt buộc mọi XR có label `cost-center`.
    

**Bài tập:**

1.  Viết 1 Kyverno ClusterPolicy validate field `spec.size` của XR `XDatabase` không vượt giới hạn theo namespace.
    
2.  Viết 1 policy bắt buộc mọi `Composition` mới phải có `mode: Pipeline` (chặn ai đó cố dùng lại `mode: Resources` đã deprecated).
    

## PHASE 6 - Tuần 6: Observability, Performance, Security, Nâng cấp

### Ngày 26 - Metrics của Crossplane

*   Tên metric: `engine_controllers_*`, `engine_watches_*`, `crossplane_composition_run_function_*`
    
*   Dashboard Grafana: reconcile rate, reconcile error rate theo Provider, function pipeline latency theo step.
    

**Bài tập:**

1.  Cài Prometheus ServiceMonitor scrape Crossplane core + Provider pods.
    
2.  Xây 1 Grafana dashboard: top 5 MR reconcile chậm nhất, error rate theo Provider trong 1h qua.
    

### Ngày 27 - Debug production incident

*   `crossplane beta trace <kind>/<name>` - công cụ số 1 khi debug: hiển thị cây XR → composed resources → trạng thái Synced/Ready của từng cái.
    
*   Pipeline Inspector (Ngày 10) khi lỗi nằm trong logic Function, không phải trong Provider.
    
*   Log pattern thường gặp: "cannot resolve resource references", "composed resource is not yet ready", credential lỗi ProviderConfig.
    

**Bài tập:**

1.  Cố tình tạo 1 lỗi (typo field, credential sai), dùng `crossplane beta trace` để định vị nguyên nhân trong < 2 phút.
    
2.  Viết runbook nội bộ: "5 bước debug khi XR stuck ở Ready=False".
    

### Ngày 28 - Performance & scaling

*   `--max-reconcile-rate` per-provider, số lượng worker/goroutine per controller.
    
*   Sizing control plane: bao nhiêu XR/MR thì cần tách Provider ra node riêng, cần scale etcd.
    
*   Cost của Function pipeline: mỗi bước là 1 gRPC call - pipeline quá nhiều bước làm chậm reconcile toàn hệ thống.
    

**Bài tập:**

1.  Load test: tạo 500 XR cùng lúc, đo reconcile rate trước/sau khi tăng `--max-reconcile-rate`.
    
2.  Đo latency pipeline có 5 function step vs 2 function step, rút gọn nếu có thể.
    

### Ngày 29 - Bảo mật

*   Supply chain: bắt buộc fully-qualified image + cosign verify trước khi Package Manager cài (dùng `ImageConfig` để enforce).
    
*   Provider deletion protection (alpha v2.3): bật để tránh xoá nhầm Provider còn resource sống.
    
*   Least-privilege IAM: mỗi `ProviderConfig` nên map với 1 IAM Role/Service Account hẹp nhất có thể (không dùng 1 credential admin cho toàn bộ Provider).
    
*   Secret hygiene: connection-detail Secret nên có TTL/rotation qua ESO, không để credential tĩnh vĩnh viễn.
    

**Bài tập:**

1.  Bật `--enable-provider-deletion-protection`, thử xoá 1 Provider đang có MR sống, xác nhận bị chặn.
    
2.  Thiết kế IAM Role hẹp cho Provider AWS chỉ được thao tác S3 + RDS, không có quyền IAM/EC2.
    

### Ngày 30 - Nâng cấp & migration production

*   `crossplane beta upgrade check` (CLI v1.20) quét toàn bộ control plane, báo chính xác resource nào cần sửa trước khi lên v2.
    
*   Nguyên tắc nâng cấp: **luôn đi tuần tự từng minor version**, dùng patch mới nhất mỗi bước (vd v1.18 → v1.19 → v1.20 → v2.0 → v2.1 → v2.2 → v2.3).
    
*   Backup/restore trạng thái XR/MR bằng Velero trước khi nâng cấp lớn - vì reconcile sai sau upgrade có thể xoá nhầm tài nguyên cloud thật.
    

**Bài tập:**

1.  Chạy `crossplane beta upgrade check` trên 1 cluster v1.20 giả lập có dùng P&T cũ, đọc báo cáo và sửa từng issue.
    
2.  Viết runbook nâng cấp production: pre-check → backup Velero → upgrade minor-by-minor → post-check bằng `crossplane beta trace` trên toàn bộ XR.
    

## PHASE 7 - Tuần 7–8: Capstone Projects

### Capstone 1 (Ngày 31–35): Multicloud Kubernetes Platform

**Bài toán**: doanh nghiệp cần self-service tạo cluster K8s trên AWS (EKS), GCP (GKE), Azure (AKS) qua 1 API thống nhất.

**Yêu cầu kỹ thuật:**

1.  XRD namespaced `XCluster` với schema chung (node count, instance type, region, cloud provider).
    
2.  Composition dùng Function pipeline (Go hoặc `function-go-templating`) chọn nhánh tạo EKS/GKE/AKS theo field `provider`.
    
3.  `DeploymentRuntimeConfig` + `ImageConfig` cấu hình runtime cho 3 Provider.
    
4.  GitOps: repo platform (Composition/XRD) tách khỏi repo workload (XR instance), sync qua Argo CD.
    
5.  Policy Kyverno chặn node count > ngưỡng theo namespace/môi trường.
    
6.  Dashboard Grafana theo dõi trạng thái tất cả cluster đang quản lý.
    
7.  Runbook: nâng cấp version K8s của toàn bộ cluster qua CompositionRevision, canary theo namespace trước khi rollout toàn bộ.
    

### Capstone 2 (Ngày 36–40): Internal Developer Platform (IDP) hoàn chỉnh

**Bài toán**: xây self-service platform cho app team tự triển khai infra (DB, queue, cache, LB) cho ứng dụng của họ, nhiều môi trường (dev/staging/prod), nhiều cloud.

**Yêu cầu kỹ thuật:**

1.  Bộ Composition cho từng thành phần (DB, MQ, cache, LB), dùng `EnvironmentConfig` để khác biệt hoá theo dev/staging/prod (kích thước, class, region).
    
2.  Self-service qua namespaced XR: app team chỉ có RBAC tạo XR trong namespace của họ, không đụng vào Composition/XRD.
    
3.  Secret quản lý qua ESO + Vault, connection detail compose qua `function-patch-and-transform`.
    
4.  CI pipeline đầy đủ cho Composition (test, render, diff, publish) theo chuẩn Ngày 22.
    
5.  Observability: metrics + trace + alert khi XR ở trạng thái `Ready=False` quá 10 phút.
    
6.  Disaster recovery: backup Velero định kỳ, tài liệu runbook khôi phục control plane từ backup.
    
7.  Viết tài liệu onboarding cho app team mới: cách tạo XR đầu tiên, cách đọc trạng thái, cách debug lỗi cơ bản bằng `crossplane beta trace`.
    

## Tài nguyên tham khảo

*   Docs chính thức: docs.crossplane.io/latest (luôn xem đúng version bạn đang chạy, có version switcher)
    
*   What's New in v2: docs.crossplane.io/latest/whats-new
    
*   Hướng dẫn nâng cấp v1→v2: docs.crossplane.io/latest/guides/upgrade-to-crossplane-v2
    
*   Blog chính thức (release notes chi tiết từng bản): blog.crossplane.io
    
*   Source code tham khảo: `crossplane/crossplane`, `crossplane/function-sdk-go`, `crossplane/function-sdk-python`, `crossplane/provider-template`
    

## Lưu ý khi học

*   Luôn build lab trên đúng version mục tiêu (v2.3+) - đừng học theo blog/tutorial cũ ghi `mode: Resources` hay `ControllerConfig` mà không kiểm tra ngày viết.
    
*   Ưu tiên đọc source code thật (Provider, Function SDK) hơn là chỉ đọc doc - phần lớn "hiểu sâu internals" nằm ở đây.
    
*   Mỗi tuần nên có ít nhất 1 buổi "phá" có chủ đích: cố tình gây lỗi (credential sai, RBAC thiếu, quota vượt) để luyện phản xạ debug - đây là kỹ năng khác biệt nhất giữa người "biết dùng" và người "vận hành được production".
