Chấm dứt nỗi ám ảnh Template: Hướng dẫn thực tiễn về Kustomize

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

Thảm họa Production lúc 2:14 sáng

2:14 sáng. Chiếc điện thoại trên bàn cạnh giường rung lên với cảnh báo từ PagerDuty, cảm giác như một cú đấm vào bụng. Production API đang “đổ máu” với hàng loạt lỗi 503. Tôi mở log, nheo mắt nhìn qua ánh sáng xanh chói mắt của màn hình. Thủ phạm là gì? Một URI database của môi trường staging bị ghi cứng (hardcoded)—db-staging.internal:5432—đã lẻn vào cluster production thông qua một phiên ‘kubectl apply’ thủ công.

45 phút tiếp theo tôi phải loay hoay gỡ rối một Helm chart vốn đã biến tướng thành một “cơn ác mộng” lồng ghép 12 lớp. Chỉ một lỗi thụt lề sai trong file YAML đã khiến cấu hình bị sai lệch (drift). Đêm đó, mọi thứ trở nên rõ ràng: Helm là quá thừa thãi cho dự án này. Chúng tôi không cần một trình quản lý package cồng kềnh. Chúng tôi cần một cách sạch sẽ, tự nhiên để quản lý sự thay đổi giữa các môi trường mà không phải rơi vào “địa ngục template”. Đó là lúc tôi chuyển toàn bộ stack sang Kustomize.

Quick Start: Từ con số 0 đến khi triển khai trong 5 phút

Kustomize nằm ngay bên trong binary kubectl hiện có của bạn. Không cần tải thêm gì cả. Không cần quản lý các tiến trình ‘Tiller’ phía server. Nó hoạt động theo một logic đơn giản: bạn định nghĩa một Base (những thành phần chung) và các Overlays (những thay đổi riêng for từng môi trường).

Đây là cấu trúc thư mục tiêu chuẩn mà tôi sử dụng cho mọi microservice mới:

myapp/
├── base/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── kustomization.yaml
└── overlays/
    ├── dev/
    │   └── kustomization.yaml
    └── prod/
        └── kustomization.yaml

Đầu tiên, hãy soạn một file base/deployment.yaml tinh gọn:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web-server
  template:
    metadata:
      labels:
        app: web-server
    spec:
      containers:
      - name: main
        image: my-repo/api:latest
        ports:
        - containerPort: 8080

Tiếp theo, sử dụng base/kustomization.yaml để khai báo các file tài nguyên của bạn:

resources:
- deployment.yaml
- service.yaml

Để scale môi trường production lên 10 replica, file overlays/prod/kustomization.yaml của bạn chỉ cần chứa phần khác biệt:

resources:
- ../../base

patches:
- target:
    kind: Deployment
    name: web-server
  patch: |-
    - op: replace
      path: /spec/replicas
      value: 10

Triển khai chỉ với một dòng lệnh:

kubectl apply -k overlays/prod/

Không cần nạp biến phức tạp. Không có logic ‘if-else’. Chỉ là file YAML Kubernetes thuần túy được patch vào lúc thực thi.

Mô hình Overlay thực sự hoạt động như thế nào

Trong thực tế, mô hình này buộc bạn phải coi hạ tầng là các lớp chồng lên nhau thay vì một kịch bản nguyên khối. Helm thường để lại cho bạn một file values.yaml dài 1.500 dòng, nơi bạn chẳng biết một biến cụ thể thực sự nằm ở đâu cho đến khi chạy dry-run. Kustomize thay đổi điều đó.

Bằng cách sử dụng Strategic Merge Patching, Kustomize trộn các thay đổi của bạn vào base. Đây là một điểm cộng lớn cho bảo mật. Tôi có thể khóa chặt một deployment base với các giới hạn tài nguyên doanh nghiệp và header bảo mật nghiêm ngặt, cho phép các developer chỉ tập trung vào các biến môi trường của họ trong các overlay.

Bẫy “Cấu hình cũ”: ConfigMap Generators

Cập nhật ConfigMap mà quên khởi động lại Pod là một sai lầm kinh điển của “lính mới”. Kustomize khắc phục điều này thông qua configMapGenerator. Nó tự động thêm một chuỗi hash 10 ký tự duy nhất (ví dụ: api-config-f98h2g6) vào tên ConfigMap. Mỗi khi bạn chỉnh sửa một giá trị, Kustomize sẽ tạo ra một cái tên mới, điều này tự động kích hoạt quá trình rolling update cho Deployment của bạn.

# overlays/dev/kustomization.yaml
configMapGenerator:
- name: api-config
  literals:
  - DB_URL=jdbc:mysql://dev-db:3306/mydb
  - DEBUG=true

Vượt xa những kiến thức cơ bản: Patching cho thực tế

Việc thay thế thô chỉ giúp bạn đi được một đoạn. Khi lưu lượng truy cập tăng lên, bạn sẽ cần hoán đổi image tag thông qua pipeline CI/CD hoặc chèn metadata toàn cục. Kustomize xử lý việc này bằng các transformer tích hợp sẵn, hoạt động như một “con dao mổ” chính xác cho file YAML của bạn.

Tự động gắn Tag cho Image

Chỉnh sửa YAML thủ công cho mỗi lần build là con đường dẫn đến sự kiệt sức. Công cụ CI của bạn (GitHub Actions hoặc GitLab CI) có thể cập nhật image tag một cách linh hoạt trong quá trình build:

# Bên trong overlays/prod/kustomization.yaml
images:
- name: my-repo/api
  newName: my-repo/api
  newTag: v1.4.2

Chuẩn hóa Metadata

Tôi luôn bao gồm trường commonLabels field. Nó giúp việc lọc log hoặc debug với kubectl get pods -l env=prod trở nên tức thì. Bạn cũng có thể áp đặt một namespace cho toàn bộ overlay để ngăn chặn tài nguyên ‘dev’ vô tình rò rỉ vào ‘production-apps’.

namespace: production-apps
commonLabels:
  variant: prod
  team: backend

Những bài học xương máu từ thực tế

Khi bạn đang dập lửa lúc 2 giờ sáng, sự mơ hồ chính là kẻ thù. Đây là bốn quy tắc tôi luôn tuân theo để giữ cho các cluster của mình ổn định:

  • Giữ cho Base tối giản: Base nên là “bộ khung” của ứng dụng. Đừng đưa các giá trị mặc định cụ thể cho môi trường vào đó; hãy đẩy chúng vào overlay ‘default’ hoặc ‘dev’.
  • Xem trước trước khi Apply: Hãy chạy kubectl kustomize overlays/prod trước. Nó sẽ xuất file YAML cuối cùng đã được trộn ra terminal. Điều này đã cứu tôi khỏi việc triển khai các cấu hình bị lỗi không biết bao nhiêu lần.
  • Bảo mật Secret của bạn: Nếu bạn sử dụng secretGenerator, đừng bao giờ commit các file nguồn lên Git. Hãy sử dụng một trình quản lý secret bên ngoài như HashiCorp Vault hoặc SealedSecrets cho bất kỳ thông tin nhạy cảm nào.
  • Tránh địa ngục lồng ghép: Chỉ nên dừng lại ở hai cấp (Base và Overlays). Nếu bạn thấy mình đang xây dựng theo kiểu base -> staging -> prod-region-1 -> prod-region-1-zone-a, bạn đang làm quá phức tạp vấn đề rồi đấy.

Lời kết: Kustomize không phải là sự thay thế hoàn toàn cho Helm. Helm vẫn là “ông vua” trong việc phân phối các công cụ bên thứ ba phức tạp như Prometheus. Nhưng đối với các microservice của riêng bạn? Kustomize mang lại mức độ minh bạch mà các template không thể chạm tới. Nó giúp tôi ngủ ngon hơn khi biết rằng file YAML trên màn hình chính xác là những gì đang chạy trong cluster.

Share: