4 phút đọcCập nhật

YAML trên Kubernetes: mười hai lỗi khiến apply gãy lúc hai giờ sáng

Tác giả: Biên tập Safe Local Tools

YAML thân thiện cho đến khi thụt dòng sai một khoảng trắng làm sập production. Kubernetes đặt YAML làm mặt nạ mặc định; mọi kỹ sư giờ phải sửa định dạng nhạy khoảng trắng dưới áp lực, thường dán từ Stack Overflow hoặc template Helm còn {{ }}.

Bài viết liệt kê mười hai lỗi sống sót qua review, giải thích API server chuyển YAML sang JSON, và khi nào nên dùng Safe Local Tools để soi cấu trúc mà không upload manifest nội bộ.

OG illustration

YAML là giao diện cho con người, không phải ngôn ngữ dễ tha thứ

yes/no đôi khi thành boolean tùy parser. Chuỗi số dẫn đầu 0 có thể gây hiểu nhầm cơ số. Literal nhiều dòng với dấu hai chấm trong shell dễ vỡ. Kubernetes nhận YAML rồi map sang JSON—nếu kiểu JSON bất ngờ, bạn gặp hành vi runtime chứ không phải lỗi cú pháp sớm.

Tab thay vì space

YAML cấm tab cho thụt dòng cấu trúc. “found character that cannot start any token” xuất hiện. Dùng .editorconfig và hook từ chối tab trong *.yaml.

Thụt lệch làm env gắn nhầm container

Một khoảng trắng thừa dưới containers: làm field lọt nhánh khác. Triệu chứng: biến môi trường biến mất, probe dính object khác. Thu gọn nhánh trong IDE và bật schema Kubernetes nếu có.

Scalar không trích dẫn trở thành boolean

env:
  - name: DEBUG
    value: off   # một số parser hiểu thành false
# sửa: value: "off"

Script nhiều dòng: dùng block scalar

Dán shell có dấu hai chấm vào args dễ làm parser lạc. Dùng | hoặc > và trích dẫn khi cần.

Khóa trùng: thắng bản sau im lặng

Một số loader YAML cho phép key lặp; người sau thắng mà không báo. Chuyển sang JSON tạm để lộ trùng nếu tool hỗ trợ.

Helm chưa render

Template còn {{ .Values.foo }} không phải object hợp lệ của cluster đã render. Luôn chạy helm template hoặc kubectl apply --dry-run=server trong CI.

Sai apiVersion/kind và manifest khổng lồ

YAML đúng cú nhưng cặp phiên bản không tồn tại trong cluster vẫn fail. Theo dõi ma trận phiên bản một file dài năm nghìn dòng mời lỗi thụt dòng—tách Deployment/Service/Ingress hoặc dùng Kustomize.

Bí mật thô trong git và các bẫy quantity

Secret base64 commit là sự cố tuân thủ chờ bật. Quantity CPU dạng "500m" là chuỗi, không phải float—in sai kiểu schedule im lặng sai. Separator --- giữa tài nguyên tránh merge nhầm. Anchor YAML không tồn tại trong JSON—nếu cần round-trip sang JSON để học máy chủ.

Vì sao JSON giúp debug

JSON không cho comment và ít ép kiểu hơn; vòng YAML→JSON chỉ ra boolean hoá không mong muốn. Safe Local Tools trong trình duyệt là lớp kính chiếu khi bạn không thể paste manifest lên formatter công khai.

Quy trình trước apply

Format + lint trong CI; chuyển JSON kiểm tra cấu trúc; kubectl apply --dry-run=server; rollout canary; theo dõi fieldManager conflict. Cron trên kube vẫn là thực thi mã có lịch—kiểm soát ai chỉnh và egress của job.

kubectl apply, three-way merge và các bất ngờ từ field manager

server-side apply và ownership field giúp nhiều controller cùng sử một object, nhưng cũng tạo xung đột khi các patch YAML tay đè các trường mà Helm release quản trị khác nhau các tag. Việc kubectl explain không thay được việc kiểm duyệt các diff của Argo hoặc Flux trước khi reconcile.

Một sai lầm phổ biến của người mới là chỉ nhìn kubectl get -o yaml sau khi apply mà không lưu bản được API server hydrate thực tế—in ra JSON sau round-trip YAML→JSON trong CI có thể bắt các coerced boolean không hiện trong diff con người vì các defaultValue.

Đừng dùng | block scalar chứa lệnh shell phức tạp mà không gắn set -euo pipefail ngay trong khối: pod fail không rõ chỉ vì pipefail thiếu, không phải vì YAML sai tinh thần của manifest.

Độ an toàn, policy-as-code và bước chuyển sang JSON không thay các review con người

Kyverno hay OPA Gatekeeper có thể vô hiệu latest và buộc request/limit—but policy không biết các ý định kinh doanh ẩn trong comment YAML (vì YAML production strip comment khi marshal). Việc ghi các quyết định vào README bên các manifest không thay các policy object.

Khi bạn dùng Kustomize, patch strategic merge không phải lúc nào cũng theo intuition; patchesJson6902 yêu cầu chỉ báo cực cụ thể. Một sai phím có thể thay sai container name trong một list dài không ai đọc hết trong review nhanh.

Safe Local Tools chỉ là lớp gương: nếu team không ép helm template --debugkubectl diff trong ít nhất một chi nhánh staging, không công cụ JSON nội địa nào thay các bài học thụt dòng bằng tay.

YAML trên Kubernetes là một phần của “hạ tầng dưới áp lực”. Ghi chú dialect, cấm tab, trích dẫn scalar mơ hồ, render template trước khi merge, và khi nghi ngờ hãy nhìn JSON trung gian. Safe Local Tools chỉ là bước soi trong tab—văn hoá đội là phần còn lại.