به گزارش از وبسایت cncf

پروژه‌هایی که در این مطلب معرفی شده‌اند نشان می‌دهند که وقتی مکانیسم‌های بررسی سلامت پشتیبانی می‌شوند، مقیاس تا صفر می‌تواند بی‌اثر شود. با ProbeResponse در KubeElasti بیاموزید چگونه به متعادل‌کننده‌های بار و مانیتورهای uptime پاسخ دهید در حالی که سرویس‌های Kubernetes واقعاً بیکار باقی می‌مانند.

مقیاس تا صفر روی کاغذ جذاب است: سرویس بیکار، بدون مصرف منابع و بدون صورتحساب. اما در عمل مشکل رایجی وجود دارد که اغلب نادیده گرفته می‌شود: متعادل‌کننده بار شما از اینکه پادها عمداً حذف شده‌اند باخبر نیست و با ارسال چک‌های دوره‌ای سلامت باعث بیدار شدن خودکار آن‌ها می‌شود.

سناریوی معمول این‌گونه است: شما سرویس را طوری پیکربندی می‌کنید که بعد از 10 دقیقه بی‌کاری به صفر برسد؛ در همان زمان متعادل‌کننده بار هر 30 ثانیه یکبار یک health check ارسال می‌کند. لحظه‌ای که آخرین پاد خاتمه می‌یابد، متعادل‌کننده یک GET /healthz می‌فرستد، حل‌کننده (solver) آن را دریافت می‌کند و برای KubeElasti هر درخواست ورودی سیگنالی است مبنی بر اینکه «کسی به سرویس نیاز دارد». اپراتور آغاز به مقیاس کردن می‌کند و پادها دوباره بالا می‌آیند — در نتیجه عملاً هیچ‌گاه سرویس واقعاً در صفر نمی‌ماند.

این موضوع یک اشکال در KubeElasti نیست، بلکه تنشی اساسی میان دو نیاز زیرساختی است: متعادل‌کننده‌های بار باید بدانند سرویس در دسترس است و سیستم‌های مقیاس‌دهی باید بدانند سرویس غیرفعال است. از زمانی که تیم‌ها خواستند استقرارهای scale-to-zero را پشت یک load balancer ابری اجرا کنند، این تقابل وجود داشته است.

این مشکل در سه لایه معمولاً خودش را نشان می‌دهد:

1) Cloud Load Balancers — مانند AWS ALB، GCP Load Balancer و Azure Application Gateway — که برای مسیریابی ایمن به چک‌های سلامت دوره‌ای وابسته‌اند؛ این چک‌ها مفهوم «عمداً بیکار» بودن را درک نمی‌کنند.

2) Probes (Liveness و Readiness) — حتی زمانی که کاوشگرها روی پادها پیکربندی شده‌اند، نسخه‌هایی از این بررسی‌ها اغلب در لایه ورودی تکرار می‌شوند و منجر به راه‌اندازی مجدد پادها می‌شوند.

3) Monitoring — پلتفرم‌های داخلی، سرویس‌مش‌ها مثل Istio و ابزارهای مشاهده‌پذیری مانند Prometheus Blackbox Exporter به‌طور مستمر نقاط پایانی را بررسی می‌کنند و معمولاً بین یک سرویس down و یک سرویس عمداً بیکار تفاوتی قائل نمی‌شوند.

چرا راهکار معمول شکست می‌خورد؟ توصیه متداول این است که endpoint چک سلامت را از مسیریابی اصلی برنامه جدا کنید؛ اما این راه سه مشکل دارد: اول اینکه همیشه کنترل کامل تنظیمات health check را در اختیار ندارید (مثلاً نمی‌توانید به AWS ALB بگویید از یک backend متفاوت برای /healthz استفاده کند). دوم اینکه جداسازی مسیریابی پیچیدگی عملیاتی ایجاد می‌کند که در طول زمان حفظ نمی‌شود. سوم و مهم‌تر اینکه endpoint سلامت در حقیقت همان endpoint برنامه است؛ تغییر مسیر آن هدف را شکست می‌دهد.

برخی ابزارها این مسئله را با قرار دادن یک پروکسی دائم در مسیر حل می‌کنند تا همیشه بتوانند چک‌ها را رهگیری کنند، اما این رویکرد هزینه‌هایی دارد: افزایش تاخیر و سربار نگهداری یک پروکسی همیشه روشن.

ProbeResponse چگونه این مسأله را حل می‌کند؟ این ویژگی یک لایه تطبیق‌گر را مستقیماً به حل‌کننده اضافه می‌کند. وقتی سرویس شما به صفر می‌رود، حل‌کننده تمام ترافیک ورودی را رهگیری می‌کند و قوانین ProbeResponse را قبل از تصمیم‌گیری درباره افزایش مقیاس ارزیابی می‌کند. اگر درخواست با یکی از قوانین مطابقت داشته باشد، حل‌کننده مستقیماً به آن پاسخ می‌دهد (با کد وضعیت و بدنه‌ای که شما تعریف می‌کنید) و اپراتور مطلع نمی‌شود — در نتیجه حجم کار روی صفر می‌ماند و چک سلامت یک 200 OK یا پاسخ مناسب را دریافت می‌کند.

نمونه پیکربندی به شکل زیر است:

probeResponse:
  - method: GET
    path:
      type: PathPrefix
      value: /healthz
    response:
      status: 200
      body: '{"ok":true}'
  - method: HEAD
    path:
      type: Exact
      value: /
    response:
      status: 204
      body: "Supports: HPOST, matching method"

قوانین می‌توانند از نوع Exact، PathPrefix یا RegularExpression باشند و با فیلترهای header و query ترکیب شوند (همه با عمل AND). قوانین از بالا به پایین ارزیابی می‌شوند؛ اگر هیچ‌کدام منطبق نشود، رفتار عادی دنبال می‌شود — یعنی درخواست در صف قرار گرفته و باعث افزایش مقیاس می‌شود. این طراحی عمدی است: ProbeResponse یک دروازه است، نه جایگزینی برای مقیاس‌دهی واقعی.

یک نکته معماری کلیدی این است که ProbeResponse از لایه رهگیری‌ای استفاده می‌کند که حل‌کننده از پیش دارد؛ بنابراین اضافه کردن matching کاوشگر بار معماری اضافی ایجاد نمی‌کند — هیچ پرش اضافی، هیچ کامپوننت جدید و هیچ پروکسی دائمی مورد نیاز نیست. وقتی سرویس دارای پادهای فعال است، حل‌کننده کاملاً از مسیر درخواست خارج می‌شود؛ قوانین ProbeResponse فقط وقتی حل‌کننده فعال است اعمال می‌شوند، یعنی زمانی که سرویس در حد صفر قرار دارد. به عبارت دیگر: وقتی سرویس شما فعال است، هیچ تاخیر یا سربار اضافی ندارید.

پیامدهای دنیای واقعی: چند سناریو که اقتصاد هزینه را تغییر می‌دهند:

• خدمات داخلی توسعه (CI previews، داشبوردهای داخلی) — می‌توانند بین جلسات واقعی در صفر بمانند هرچند پلتفرم هر 30 ثانیه آن‌ها را بررسی کند. 🙂

• بارهای کاری GPU — پادهای GPU گران‌قیمت هستند؛ ProbeResponse اجازه می‌دهد GPUها واقعاً خاموش بمانند تا زمانی که ترافیک واقعی وارد شود، و از هزینه‌های start-up جلوگیری می‌کند. 🚀

• نرم‌افزار Enterprise با لایسنس بر مبنای نمونه — نمونه‌ها تا وقتی واقعاً نیاز نیستند خاموش می‌مانند؛ چک‌های سلامت «نیاز» محسوب نمی‌شوند و ProbeResponse این تمایز را اعمال می‌کند. 💼

• ترافیک East–West — میکروسرویس‌ها و سرویس‌مش‌ها اغلب چک‌های دوره‌ای به نقاط پایانی می‌زنند؛ ProbeResponse می‌تواند این بررسی‌ها را بدون به‌راه‌انداختن افزایش زودرس کنترل کند.

توصیه‌های عملی قبل از فعال‌سازی ProbeResponse:

1) منابع چک سلامت را شناسایی کنید — مسیر، روش و فرکانس چک متعادل‌کننده بار ابری را بررسی کنید.

2) پیکربندی ingress و ورودی‌های Kubernetes را مرور کنید — NGINX، Traefik و Istio گزینه‌های قابل تنظیمی دارند.

3) نظارت uptime را بررسی کنید — اگر از Prometheus Blackbox Exporter، مانیتورهای مصنوعی Datadog یا ابزارهای بیرونی استفاده می‌کنید، بدانید چه endpoints ای را چک می‌کنند.

4) مش سرویس را مرور کنید — Istio، Linkerd و ابزارهای مشابه ممکن است چک‌های سایدکار داشته باشند.

5) برای هر منبع چک سلامت، یک قانون ProbeResponse مناسب بسازید — از PathPrefix برای پوشش گسترده و Exact برای نقاط دقیق استفاده کنید؛ بدنه پاسخ را محافظه‌کارانه تنظیم کنید تا با انتظار پشته مانیتورینگ شما تطابق داشته باشد؛ از تطبیق‌کننده‌های header و query برای تمایز میان چک‌های سلامت و ترافیک واقعی بهره ببرید.

دیدگاه مقیاس تا صفر: KubeElasti همیشه یک مشکل دو‌بخشی داشته است — بخش اول: کاهش تا صفر و راه‌اندازی مجدد بر مبنای درخواست قابل مشاهده است؛ بخش دوم: ماندن در صفر در برابر نویز زیرساختی است که تعیین‌کننده صرفه‌جویی واقعی است. ProbeResponse پاسخ KubeElasti به بخش دوم است. در ترکیب با یک Cooldown Period مناسب، ProbeResponse «زمان بی‌حرکتی واقعی» را فعال می‌کند — فاصله‌هایی که سرویس واقعاً خاموش است و نه فقط بین چرخه‌های health check.

نتیجه‌گیری: چک‌های سلامت قابل حذف نیستند؛ متعادل‌کننده‌های بار ابری به آن‌ها نیاز دارند، اما با ابزارهایی مثل ProbeResponse می‌توان میان پاسخ‌دهی به چک‌های سلامت و حفظ مزایای واقعی scale-to-zero تعادل برقرار کرد. 😊