YAML سالهاست که به عنوان روش استاندارد نگارش مانیفستهای Kubernetes استفاده میشود، اما آزادی بیش از حد YAML باعث شده انتخابهای مختلفی پیش بیاید که همیشه برای نوشتن manifestهای قابلخواندن و قابلاطمینان مناسب نیستند. بعضی ویژگیها خوانایی را کم میکنند، بعضیها استفاده را پیچیده میکنند و بعضیها حتی باعث رفتار غیرمنتظره میشوند. 🧭
نکته این است که Kubernetes در عمل به بخش کوچکتری از YAML وابسته است. سوال ساده این شد: اگر فقط زیرمجموعهای از YAML لازم است، چرا آن زیرمجموعه را استاندارد و بقیه را کنار نگذاریم؟ به جای ساختن یک زبان جدید، SIG CLI راهکاری به نام KYAML را پیشنهاد کرد — یک گویش سختگیرانه و سازگارتر از YAML که هدفش کاهش انتخابهای آزادِ نویسنده و افزایش یکنواختی است. ✨
KYAML چیست؟ KYAML یک زیرمجموعه سختگیرانه از YAML استاندارد است که طوری طراحی شده که ابزارهای موجود بدون تغییر قادر به پارس کردن آن باشند. به عبارت دیگر، هر چیزی که در KYAML معتبر باشد، در نتیجه YAML معتبر است. هدف صرفاً کم کردن دامنه انتخابها هنگام نوشتن YAML است تا تیمها و مخازن بزرگتر سازگاری بیشتری داشته باشند.
مشکلاتی که KYAML حل میکند: YAML استاندارد چند تله شناختهشده دارد. برای مثال، ساختار بر اساس تورفتگی تعریف میشود؛ بنابراین فایلهایی با تورفتگی اشتباه ممکن است از نظر نحوی معتبر بمانند اما معنای متفاوتی داشته باشند — این موضوع در ابزارهای template مثل Helm که عملاً از بیرون با تورفتگی بازی میکنند بسیار دردسرساز است. ⚠️
یک مشکل دیگر نوعبندی ضمنی است: در YAML نقلقول رشتهها اختیاری است و بعضی مقادیر ظاهراً رشتهای بدون هشدار به نوع دیگری تبدیل میشوند. مثال کلاسیک، مقدار country: NO است که در YAML استاندارد ممکن است به عنوان boolean تفسیر شود نه رشته “NO” — و این برای خیلیها غافلگیرکننده است. در مقابل، JSON هم مشکلات خودش را دارد: فقدان نظرات، حساسیت به کاماهای انتهایی و نیاز به نقلقول زدن همه کلیدها تجربهٔ خوبی برای نویسندگی پیکربندی ایجاد نمیکند.
KYAML با صراحتبخشیدن به ساختار و نوعها این مسائل را حل میکند: کمتر به فاصلهها و تورفتگی وابسته است، از نظرات پشتیبانی میکند، و در عین حال ظاهر کلی YAML را حفظ میکند. اگر بخواهید آن را بین YAML و JSON قرار دهید، KYAML شفافتر از YAML پیشفرض و دوستانهتر از JSON است. 💡
برای مقایسه، اینجا یک Pod manifest در هر دو سبک نشان داده شده است (برای خوانایی هر بخش به صورت نمونه):
apiVersion: "v1"
kind: "Pod"
metadata: { name: "my-pod", labels: { app: "demo", }, }
spec: { containers: [{ name: "nginx", image: "nginx:1.20", }], }
در این نمونه به استفاده از علامتگذاریهای رشتهای دوقلو و کاماها دقت کنید؛ این علامتگذاریِ ساختار را واضحتر میکند و تکیهٔ کمتری بر تورفتگی دارد. این سبک از نظر نحوی صریحتر است و احتمال خطا در خواندن و ویرایش را کاهش میدهد.
چگونه KYAML را به صورت زیبا چاپ کنیم؟ چند راه معمول وجود دارد: 🛠️
گزینه 1: استفاده از kubectl با خروجی kyaml
برای کاربرانی که از Kubernetes 1.34 به بعد استفاده میکنند، kubectl خروجی kyaml را بهصورت بومی پشتیبانی میکند. مثال:
kubectl get deployment my-app -o kyaml
اگر میخواهید خروجی را در فایل ذخیره کنید، کافی است خروجی را به فایل هدایت کنید. همچنین در برخی نسخهها امکان تنظیم KYAML بهعنوان فرمت خروجی پیشفرض وجود دارد (بسته به نسخه kubectl و سازوکارتان ممکن است روش تنظیم متفاوت باشد) — این کار کمک میکند که همیشه خروجی consistent و KYAML-سازگار بگیرید.
گزینه 2: استفاده از yamlfmt (ابزار Go)
ابزار yamlfmt میتواند فایلها یا یک دایرکتوری را به KYAML تبدیل کند و نیز امکان نشان دادن تفاوت (diff) بین فرمتها را دارد. نمونه دستورات:
go install github.com/google/yamlfmt/cmd/yamlfmt@latest yamlfmt -o=kyaml my-deployment.yaml yamlfmt -o=kyaml -d my-deployment.yaml
گزینه 3: قالبدهندهٔ اختصاصی Google yamlfmt
نسخههای باینری و روشهای نصب در صفحهٔ release موجود است و میتوانید آن را بهعنوان pre-commit hook یا تصویر Docker در CI استفاده کنید. مثالهایی برای استفاده در پروژه:
yamlfmt -dry my-deployment.yaml yamlfmt my-deployment.yaml yamlfmt ./k8s/
نکته مهم: قالبدهندهٔ KYAML معمولاً پیکربندیهای اضافی را نمیپذیرد تا نتایج همیشه یکنواخت بماند؛ ترکیب گزینههای مختلف قالبدهنده با هم ممکن است خطا ایجاد کند. 🔧
چند نکته عملی و نهایی برای SRE/DevOpsها:
– KYAML همان YAML است: پس ابزارهای موجود (kubectl، CI pipelines و غیره) نیازی به تغییر ندارند. میتوانید KYAML را حتی به نسخههای قبلی kubectl هم پاس دهید چون در نهایت YAML معتبر است.
– KYAML اجباری نیست؛ ادامهٔ نوشتن به سبک بلوک YAML کاملاً کار میکند. اما انتخاب KYAML بهعنوان یک قرارداد تیمی باعث کاهش خطا، افزایش خوانایی و سازگاری در مخزنهای بزرگ میشود — چیزی که در کارهای نگهداری و عملیات روزمره واقعاً ارزشمند است. 🙂