بلاگ/راه‌اندازی Horizontal Pod Autoscaler در Kubernetes خودمیزبان: مقیاس‌پذیری خودکار Pod بر اساس مصرف CPU و Memory
به‌روز شده

راه‌اندازی Horizontal Pod Autoscaler در Kubernetes خودمیزبان: مقیاس‌پذیری خودکار Pod بر اساس مصرف CPU و Memory

1405/08/130 بازدید
راه‌اندازی Horizontal Pod Autoscaler در Kubernetes خودمیزبان: مقیاس‌پذیری خودکار Pod بر اساس مصرف CPU و Memory

راه‌اندازی Horizontal Pod Autoscaler در Kubernetes خودمیزبان: مقیاس‌پذیری خودکار Pod بر اساس مصرف CPU و Memory

نمودار مقیاس‌پذیری خودکار Pod با Horizontal Pod Autoscaler در Kubernetes

روی یک کلاستر Kubernetes خودمیزبان، چیزی به اسم مقیاس‌پذیری خودکار از قبل آماده نیست. در Kubernetes مدیریت‌شده مثل GKE یا EKS یک سری قطعه از قبل سر هم شده، اما روی کلاستری که خودتان بالا آورده‌اید، باید هر تکه را دستی وصل کنید. این مقاله همان مسیر را قدم‌به‌قدم نشان می‌دهد: از نصب Metrics Server تا راه‌اندازی Horizontal Pod Autoscaler بر اساس مصرف CPU و Memory.

Horizontal Pod Autoscaler چیست

Horizontal Pod Autoscaler (یا HPA) یک کنترلر داخل Kubernetes است که تعداد replica‌های یک Deployment را بر اساس مصرف واقعی منابع بالا و پایین می‌برد. وقتی مصرف CPU از آستانه‌ای که تعیین کرده‌اید بالاتر برود، HPA چند Pod تازه اضافه می‌کند؛ وقتی بار کم شود، بعد از مدتی همان Pod‌ها را حذف می‌کند.

تفاوتش با مقیاس‌پذیری دستی همین جاست: با kubectl scale شما باید مدام وضعیت را چک کنید و خودتان عدد replica را تغییر دهید. HPA این کار را با یک حلقهٔ کنترل خودکار انجام می‌دهد، به شرطی که منبع داده‌ای برای مصرف CPU و Memory در اختیارش بگذارید. همین «منبع داده» روی کلاستر خودمیزبان از پیش وجود ندارد و باید آن را خودتان نصب کنید.

پیش‌نیازها

قبل از شروع این‌ها را آماده کنید:

  • یک کلاستر Kubernetes در حال اجرا (با kubeadm، k3s یا هر روش دیگر) با دسترسی kubectl از ماشین خودتان.
  • حداقل یک Deployment که resources.requests روی آن تعریف شده باشد؛ بدون این مقدار، HPA نمی‌داند درصد مصرف را نسبت به چه عددی حساب کند.
  • ظرفیت آزاد کافی روی node‌ها برای این‌که Pod‌های جدید جایی برای اجرا شدن داشته باشند.

نصب Metrics Server در کلاستر خودمیزبان

Metrics Server همان چیزی است که داده‌های مصرف CPU و Memory را از kubelet هر node جمع می‌کند و از طریق Metrics API (metrics.k8s.io) در دسترس بقیهٔ کلاستر می‌گذارد. بدون آن نه kubectl top کار می‌کند و نه HPA چیزی برای خواندن دارد.

نصب با یک دستور:

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

رفع خطای گواهی kubelet

روی کلاستر خودمیزبان، معمولا گواهی TLS کوبلت self-signed است و Metrics Server با خطای گواهی crash می‌شود. راه‌حل، اضافه کردن یک آرگومان به Deployment آن است:

kubectl -n kube-system patch deployment metrics-server \
  --type='json' \
  -p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-insecure-tls"}]'

این گزینه بررسی گواهی کوبلت را غیرفعال می‌کند. در یک محیط production که از PKI داخلی استفاده می‌کنید بهتر است به‌جایش گواهی معتبر صادر کنید، اما برای شروع کار همین کافی است.

تست نصب

بعد از یک تا دو دقیقه که Metrics Server آمد بالا:

kubectl top nodes
kubectl top pods -A

اگر این دو دستور عدد نشان دادند، یعنی مسیر داده آماده است و می‌توانید سراغ HPA بروید.

تعریف Resource Requests روی Deployment

HPA درصد مصرف را نسبت به requests حساب می‌کند، نه نسبت به limits. اگر requests تعریف نشده باشد، HPA اصلا نمی‌تواند هدف درصدی را محاسبه کند. یک نمونه:

resources:
  requests:
    cpu: "250m"
    memory: "256Mi"
  limits:
    cpu: "500m"
    memory: "512Mi"

عدد 250m یعنی یک‌چهارم یک هسته. این عدد را واقعی تنظیم کنید، نه خیلی کم (که HPA را زودتر از لازم فعال کند) و نه خیلی زیاد (که node جا برای Pod‌های تازه نداشته باشد).

راه‌اندازی Horizontal Pod Autoscaler

دو راه برای ساخت HPA وجود دارد.

روش اول، یک دستور ساده:

kubectl autoscale deployment myapp --cpu-percent=70 --min=2 --max=10

این یعنی وقتی میانگین مصرف CPU همهٔ replica‌ها از ۷۰٪ بگذرد، Kubernetes replica تازه اضافه می‌کند، حداقل ۲ و حداکثر ۱۰ عدد.

روش دوم، نوشتن یک منیفست که هم خواناتر است و هم قابل نگه‌داری در Git:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: myapp-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70

برای اعمال آن:

kubectl apply -f hpa.yaml

مقیاس‌پذیری بر اساس Memory

همان منیفست را می‌شود با یک متریک دوم تکمیل کرد تا Memory هم بررسی شود:

  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80

وقتی چند متریک با هم تعریف شود، HPA همیشه بر اساس متریکی عمل می‌کند که بیشترین تعداد replica را پیشنهاد بدهد. نکته‌ای که این‌جا باید در نظر بگیرید: مصرف Memory معمولا بعد از افت بار به همان سرعت CPU پایین نمی‌آید، چون خیلی از برنامه‌ها حافظه را نگه می‌دارند و زود آزاد نمی‌کنند. اگر مقیاس‌پذیری فقط بر اساس Memory تنظیم شده باشد، ممکن است Pod‌ها دیرتر از انتظار کاهش پیدا کنند.

تست عملی: ایجاد بار و مشاهده مقیاس‌پذیری

برای دیدن HPA در عمل، یک بار مصنوعی روی سرویس بسازید:

kubectl run load-generator --image=busybox --restart=Never -- \
  /bin/sh -c "while true; do wget -q -O- http://myapp; done"

و در یک پنجرهٔ دیگر وضعیت را زنده نگاه کنید:

kubectl get hpa -w

ظرف چند ثانیه تا چند دقیقه، ستون REPLICAS باید بالا برود. بعد از این‌که load-generator را پاک کنید، منتظر بمانید؛ HPA به‌صورت پیش‌فرض یک پنجرهٔ پایداری ۳۰۰ ثانیه‌ای برای کاهش replica دارد تا با هر نوسان کوچک بار، Pod‌ها مدام بالا و پایین نشوند.

افزایش تعداد Pod توسط Horizontal Pod Autoscaler هنگام بالا رفتن بار روی کلاستر Kubernetes

مقایسهٔ روش‌های مقیاس‌پذیری روی کلاستر خودمیزبان

قبل از این‌که فقط به HPA تکیه کنید، خوب است بدانید در کنارش چه گزینه‌های دیگری هست و کدام‌شان روی یک کلاستر خودمیزبان در دسترس است.

روشنحوهٔ کارزمان واکنشمحدودیت روی کلاستر خودمیزبان
مقیاس‌پذیری دستی (kubectl scale)تغییر دستی تعداد replicaفوری، ولی نیاز به دخالت انسانبرای بار پیش‌بینی‌نشده عملا دیر می‌رسد
Horizontal Pod Autoscalerافزایش یا کاهش خودکار replica بر اساس CPU/Memoryچند ثانیه تا چند دقیقهنیاز به Metrics Server، و node باید ظرفیت خالی داشته باشد
Vertical Pod Autoscalerتغییر میزان CPU/Memory تخصیصی به هر Podکندتر، معمولا با ریستارت Pod همراه استهم‌زمان با HPA روی همان متریک قابل استفاده نیست
Cluster Autoscalerاضافه یا کم کردن خود node‌هاچند دقیقهروی VPS یا سرور اختصاصی خودمیزبان معمولا در دسترس نیست؛ اضافه کردن node دستی انجام می‌شود

همین ردیف آخر نکتهٔ اصلی کلاستر خودمیزبان است: HPA تعداد Pod را کم و زیاد می‌کند، اما تعداد node را خودش زیاد نمی‌کند. اگر ظرفیت node‌های فعلی تمام شود، Pod‌های تازه در وضعیت Pending می‌مانند و باید خودتان یک node دیگر اضافه کنید.

نکات عملی برای برنامه‌ریزی ظرفیت

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

  • maxReplicas را بر اساس ظرفیت واقعی node‌ها تعیین کنید، نه یک عدد دلخواه. اگر مجموع requests ده Pod بیشتر از CPU و RAM آزاد کلاستر باشد، HPA عدد ده را هدف می‌گیرد اما بخشی از آن‌ها Pending می‌ماند.
  • فیلد behavior در منیفست HPA امکان تنظیم جداگانهٔ سرعت بالا رفتن و پایین آمدن را می‌دهد؛ برای سرویس‌هایی که نوسان ناگهانی دارند، معمولا scale-up سریع‌تر و scale-down محتاط‌تر تنظیم می‌شود.
  • اگر مصرف منابع کلاستر مدام به سقف می‌رسد، راه‌حل HPA نیست؛ آن موقع باید یک node با CPU و RAM بیشتر به کلاستر اضافه کنید.

برای همین مورد آخر، یک سرور ابری یا VPS با امکان ارتقای سریع پلن یا سفارش یک سرور اختصاصی جدید، کار اضافه کردن node تازه به کلاستر را خیلی سریع‌تر می‌کند؛ کافی است node جدید را بسازید، Kubernetes را روی آن نصب کنید و با kubeadm join به کلاستر وصلش کنید.

جمع‌بندی

راه‌اندازی Horizontal Pod Autoscaler روی یک کلاستر خودمیزبان سه مرحلهٔ اصلی دارد: نصب Metrics Server، تعریف requests درست روی Deployment، و ساخت منیفست HPA با آستانهٔ CPU یا Memory مناسب. بعد از آن، تنها کاری که می‌ماند مانیتور کردن سرور است تا ببینید آستانه‌ها با الگوی واقعی بار سرویستان جور است یا نیاز به تنظیم دوباره دارد.

اگر کلاستر فعلی جا برای Pod‌های تازه‌ای که HPA می‌سازد ندارد، سراغ سرور ابری آریانت بروید و یک node تازه به کلاستر اضافه کنید.

سؤالات متداول

آیا HPA بدون Metrics Server کار می‌کند؟ نه. HPA داده‌های مصرف CPU و Memory را از Metrics API می‌خواند و بدون نصب Metrics Server، دستور kubectl get hpa فقط عبارت <unknown> نشان می‌دهد.

آیا HPA می‌تواند بر اساس متریک سفارشی غیر از CPU و Memory کار کند؟ بله، با نصب چیزی مثل Prometheus Adapter می‌شود متریک‌های سفارشی (مثل تعداد درخواست در ثانیه) را هم به HPA معرفی کرد. در حالت پیش‌فرض Kubernetes فقط CPU و Memory را پشتیبانی می‌کند.

چرا بعد از کم شدن بار، تعداد Pod‌ها فورا کاهش پیدا نمی‌کند؟ HPA یک پنجرهٔ پایداری پیش‌فرض ۳۰۰ ثانیه‌ای برای scale-down دارد تا با هر افت موقت بار، Pod‌ها مدام حذف و دوباره ساخته نشوند. این عدد با فیلد behavior.scaleDown.stabilizationWindowSeconds قابل تغییر است.

آیا HPA روی StatefulSet هم کار می‌کند؟ از نظر فنی بله، چون scaleTargetRef می‌تواند به StatefulSet هم اشاره کند؛ اما چون خیلی از برنامه‌های stateful (مثل دیتابیس‌ها) به‌سادگی قابل مقیاس‌پذیری افقی نیستند، این حالت خیلی کمتر از HPA روی Deployment استفاده می‌شود.