این مقاله به بررسی اصول پیکربندی با YAML در Kubernetes می‌پردازد و نکات کلیدی برای استفاده بهینه از YAML در مدیریت پیکربندی کلاستر را توضیح می‌دهد.

پیکربندی و بهترین شیوه‌های configuration در Kubernetes


کلیدواژهٔ اصلی این مطلب configuration است که به معنای پیکربندی، تنظیمات و مدیریت پیکربندی در Kubernetes می‌باشد.

Configuration یکی از آن چیزهای Kubernetes است که اول کوچک به نظر می‌آید تا وقتی بزرگ می‌شود. پیکربندی در قلب هر workload روی Kubernetes قرار دارد و یک نقل‌قول جاافتاده، نسخه API نادرست یا یک indentation اشتباه در YAML می‌تواند کل استقرار را به هم بزند. 🙂

این مطلب مجموعه‌ای از بهترین شیوه‌های پیکربندی است که در عمل آزموده شده‌اند — عادت‌های کوچک که باعث می‌شوند تنظیمات Kubernetes شما تمیز، مطابق قاعده و ساده برای مدیریت باقی بماند. چه تازه‌کار باشید و چه روزانه اپ‌ها را deploy کنید، همین جزئیات کوچک هستند که خوش‌ثباتی کلاستر و آرامش ذهن شما را حفظ می‌کنند. 🧭

عمومی‌ترین نکات پیکربندی

از آخرین نسخه پایدار API استفاده کنید. Kubernetes خیلی سریع تکامل پیدا می‌کند و APIهای قدیمی در نهایت deprecated می‌شوند و کار نخواهند کرد. هر وقت resource تعریف می‌کنید، مطمئن شوید از آخرین stable API استفاده می‌کنید. برای بررسی می‌توانید از این فرمان استفاده کنید:

kubectl api-resources

این قدم ساده شما را از مشکلات سازگاری در آینده نجات می‌دهد. ✅

پیکربندی را در version control نگه دارید. هیچ‌وقت manifest را از دسکتاپ مستقیم اعمال نکنید. همیشه آن‌ها را در Git یا سیستم مشابه ذخیره کنید؛ این مثل جان‌پناه شماست. اگر چیزی به‌هم خورد، می‌توانید سریع به commit قبلی برگردید، تغییرات را مقایسه کنید یا بدون استرس setup کلاستر را بازسازی کنید.

فایل‌ها را با YAML بنویسید، نه JSON. هر دو از نظر فنی کار می‌کنند، اما YAML برای انسان خواناتر و کم‌سر‌و‌صداتر است و در جامعه رایج‌تر است. یک نکته مهم در YAML مربوط به مقادیر Boolean است: فقط از true یا false استفاده کنید؛ از yes، no، on یا off پرهیز کنید چون ممکن است در نسخه‌ای کار کند و در نسخه‌ای دیگر بشکند. اگر چیزی به نظر Boolean می‌آید و احتمال خطا هست، آن را درون نقل‌قول قرار دهید، مثلا “yes”. 🔧

پیکربندی را ساده و حداقلی نگه دارید. مقداردهی پیش‌فرضی که Kubernetes خودش انجام می‌دهد را دوباره تنظیم نکنید مگر نیاز باشد. manifests مینیمال راحت‌تر debug می‌شوند، بازبینی‌شان ساده‌تر است و احتمال خرابی در آینده کمتر است.

اشیاء مرتبط را کنار هم قرار دهید. اگر Deployment، Service و ConfigMap متعلق به یک اپ هستند، آن‌ها را در یک فایل manifest قرار دهید. این کار دنبال‌کردن تغییرات و apply کردن را به‌عنوان یک واحد ساده‌تر می‌کند. می‌توانید کل دایرکتوری را هم اعمال کنید:

kubectl apply -f configs/

فقط با یک فرمان همه چیز داخل آن پوشه اعمال می‌شود — سریع و منظم. 📦

annotationهای مفید اضافه کنید. فایل‌های manifest فقط برای ماشین‌ها نیستند بلکه برای آدم‌ها هم هستند؛ از annotations برای توضیح چرایی وجود یک resource یا عملکرد آن استفاده کنید. یک تک‌خط توضیح می‌تواند ساعت‌ها در زمان دیباگ ذخیره کند و همکاری تیمی را بهتر کند. یکی از مفیدترین annotationها kubernetes.io/description است چون مثل کامنت است اما در API هم ذخیره می‌شود و بعد از deploy در دسترس همه خواهد بود.

مدیریت Workloads: Pods، Deployments و Jobs

اشتباه رایج ابتدایی این است که مستقیم Pod بسازید. Podها کار می‌کنند ولی اگر بدون controller باشند خودشون reschedule نمی‌شوند. Naked Pods برای تست خوب هستند، ولی در محیط واقعی ریسک بالایی دارند: اگر نودی که Pod روی آن بود از کار بیفتد، Pod هم می‌میرد و Kubernetes آن را بازنمی‌گرداند.

برای اپ‌هایی که باید همیشه در حال اجرا باشند از Deployment استفاده کنید. Deployment یک ReplicaSet ایجاد می‌کند تا تعداد مطلوب Podها همیشه در دسترس باشد و strategyهایی مانند RollingUpdate را تعیین می‌کند تا Podها به‌صورت مرحله‌ای جایگزین شوند. با Deployment می‌توانید rollout نسخه جدید داشته باشید و در صورت مشکل rollback فوری انجام دهید.

از Jobs برای کارهایی که باید تمام شوند استفاده کنید. Job برای کارهای one-off مثل migration دیتابیس یا پردازش batch مناسب است؛ اگر Podها fail کنند retry انجام می‌دهد و وقتی کار تمام شد موفقیت را گزارش می‌دهد.

پیکربندی Service و شبکه

Serviceها نحوه صحبت workloads با هم در داخل (و گاهی خارج) کلاستر را فراهم می‌کنند. بدون Service، Podها ممکن است وجود داشته باشند اما نتوانند به هم دسترسی داشته باشند — پس مطمئن شویم چنین چیزی رخ ندهد. یک قاعده خوب: Service را قبل از workloads that use them بسازید. وقتی Kubernetes یک Pod را start می‌کند، متغیرهای محیطی را برای Serviceهای موجود تزریق می‌کند. پس اگر Pod به Service وابسته است، Service را قبل از backend workloads (Deployment یا StatefulSet) ایجاد کنید.

مثال: اگر یک Service با نام foo وجود داشته باشد، کانتینرها متغیرهای زیر را در محیط اولیه دریافت می‌کنند:

FOO_SERVICE_HOST=<the host the Service runs on>
FOO_SERVICE_PORT=<the port the Service runs on>

دیسکاوری مبتنی بر DNS این مشکل را ندارد، ولی این قاعده هنوز هم عادت مفیدی است. اگر کلاستر شما add-on DNS را دارد (بیشتر کلاسترها دارند)، هر Service به‌طور خودکار یک رکورد DNS خواهد داشت و می‌توانید آن را با نام صدا بزنید، مثلا:

curl http://my-service.default.svc.cluster.local

این یکی از ویژگی‌هایی است که شبکه Kubernetes را جادویی می‌کند. ✨

hostPort و hostNetwork را مگر در مواقع ضروری استفاده نکنید. این گزینه‌ها Podها را به نودهای خاص قفل می‌کنند و برنامه‌ریزی و مقیاس‌پذیری را سخت می‌کنند چون هر ترکیب <hostIP, hostPort, protocol> باید یونیک باشد. اگر hostIP و protocol مشخص نشود، Kubernetes از 0.0.0.0 و TCP به‌عنوان پیش‌فرض استفاده می‌کند. مگر برای دیباگ یا ساخت plugin شبکه، اینها را دوری کنید. برای دسترسی محلی فقط برای تست از kubectl port-forward استفاده کنید:

kubectl port-forward deployment/web 8080:80

یا اگر نیاز واقعی به دسترسی خارجی دارید، از نوع Service: NodePort استفاده کنید — راه امن‌تر و native به Kubernetes است.

برای دیسکاوری داخلی که نمی‌خواهید load balancing انجام شود از headless Service استفاده کنید. این کار با تنظیم clusterIP: None انجام می‌شود؛ در این حالت به‌جای یک IP واحد، DNS لیستی از IPهای همه Podها برمی‌گرداند که برای اپ‌هایی که خودشان مدیریت اتصال را انجام می‌دهند مفید است.

کار با labels به‌صورت موثر

Labels جفت key/value هستند که به اشیاء مثل Podها الصاق می‌شوند. آن‌ها به شما کمک می‌کنند منابع را سازمان‌دهی، query و گروه‌بندی کنید. خود labels کاری انجام نمی‌دهند اما سایر منابع مثل Service و Deployment را به هم متصل نگه می‌دارند.

از semantic labels استفاده کنید. label خوب باید حتی بعد از ماه‌ها به شما بگوید این چیست. برچسب‌هایی تعریف کنید که ویژگی‌های معنایی اپ یا Deployment را شرح دهند، مثلا:

labels:
  app.kubernetes.io/name: myapp
  app.kubernetes.io/component: web
  tier: frontend
  phase: test

توضیح کوتاه: app.kubernetes.io/name نشان‌دهنده اسم اپ است، tier مشخص می‌کند این در چه لایه‌ای است (frontend/backend) و phase نشان‌دهنده مرحله است (test/prod). سپس می‌توانید از این labels برای selectors قوی استفاده کنید، مثلا:

kubectl get pods -l tier=frontend

این دستور همه Podهای frontend را در سراسر کلاستر فهرست می‌کند — شما لازم نیست نام Podها را دستی وارد کنید، فقط مشخص می‌کنید چه چیزی می‌خواهید. هم‌چنین Kubernetes یک مجموعه labelهای پیشنهادی دارد که دنبال کردن آن‌ها سازگاری بین پروژه‌ها و ابزارها را افزایش می‌دهد و باعث می‌شود ابزارهای خارجی مثل monitoring یا dashboardها بهتر بفهمند چه چیزی در حال اجرا است.

می‌توانید برای دیباگ labels را دستکاری کنید. از آنجا که controllerها با labels کار می‌کنند، حذف یک label می‌تواند یک Pod را موقتاً از مدیریت controller جدا کند، برای مثال:

kubectl label pod mypod app-

قسمت app- کلید label با نام app را حذف می‌کند؛ بعد از این کار controller دیگر آن Pod را مدیریت نمی‌کند و شما می‌توانید آن را isolate و برای بازرسی نگه دارید؛ یک حالت quarantine ساده برای دیباگ. پس از بررسی می‌توانید آن را حذف یا دوباره مدیریت کنید.

نکات مفید kubectl

چند ترفند کوچک که کار با تعداد زیادی فایل یا چند کلاستر را ساده می‌کند:

کل دایرکتوری را اعمال کنید — به‌جای apply کردن یک‌به‌یک فایل‌ها، کل پوشه را بزنید. همچنین server-side apply معمولاً گزینه مناسبی است:

kubectl apply -f configs/ --server-side

از label selectors برای گرفتن یا پاک‌کردن منابع استفاده کنید — لازم نیست همیشه نام منابع را تایپ کنید:

kubectl get pods -l app=myapp
kubectl delete pod -l phase=test

این به‌ویژه در CI/CD که می‌خواهید منابع تست را پویا پاک کنید مفید است. برای تجربه سریع، می‌توانید سریعاً Deployment و Service بسازید بدون نوشتن manifest کامل:

kubectl create deployment webapp --image=nginx
kubectl expose deployment webapp --port=80

این برای تست سریع ایده‌آل است قبل از اینکه manifest‌ کامل را بنویسید. 🚀

جمع‌بندی

پیکربندی تمیز به مدیران کلاستر آرامش می‌دهد. اگر چند عادت ساده را رعایت کنید — پیکربندی را ساده و حداقلی نگه دارید، همه چیز را version-control کنید، از labels سازگار استفاده کنید و به naked Pods تکیه نکنید — ساعت‌ها زمان دیباگ را ذخیره خواهید کرد. بهترین بخش این است که پیکربندی‌های تمیز خوانا باقی می‌مانند؛ حتی بعد از ماه‌ها شما یا اعضای تیم‌تان می‌توانید یک نگاه بیندازید و بفهمید چه اتفاقی می‌افتد. 👍