پرش به محتویات

آموزش کوبرنتیز؛ شب یازدهم: Request، Limit و QoS منابع

امشب می‌بینیم کوبرنتیز CPU و Memory را چگونه Schedule می‌کند، کلاس QoS یک Pod را تشخیص می‌دهیم و به‌شکلی امن خطای کمبود حافظه را ایجاد و عیب‌یابی می‌کنیم.

Request و Limit

  • Request مقداری است که Scheduler برای جای‌گذاری Pod در نظر می‌گیرد.
  • Limit سقف زمان اجراست که روی Container اعمال می‌شود.
  • CPU فشرده‌پذیر است؛ عبور از CPU Limit معمولاً باعث Throttling می‌شود.
  • Memory فشرده‌ناپذیر است؛ عبور از Memory Limit می‌تواند به OOMKilled منجر شود.

واحد CPU تعداد Core است: 1000m برابر یک CPU و 100m برابر یک‌دهم آن است. واحد Memory از جنس Byte است و Mi و Gi واحدهای دودویی هستند. وقتی منظورتان ۱۲۸ مِبی‌بایت است، 128Mi بنویسید نه 128M. همچنین اگر نیم Core می‌خواهید، 500m بنویسید؛ 0.5m معنای دیگری دارد.

Scheduler مقدار Request را با ظرفیت Allocatable Node مقایسه می‌کند، نه مصرف لحظه‌ای. یک Pod کم‌مصرف با Request بزرگ می‌تواند مانع Schedule شدن Pod دیگری شود.

کلاس‌های QoS

کلاس شرایط
Guaranteed همهٔ Containerها CPU Request/Limit برابر و Memory Request/Limit برابر دارند
Burstable دست‌کم یک Request یا Limit وجود دارد، اما شرایط Guaranteed برقرار نیست
BestEffort هیچ Containerای Request یا Limit مربوط به CPU و Memory ندارد

QoS هنگام فشار روی Node بر اولویت Eviction اثر می‌گذارد، اما تضمین کامل دسترس‌پذیری نیست.

Manifest آزمایش Memory

apiVersion: apps/v1
kind: Deployment
metadata:
  name: resource-demo
  namespace: course-night-11
spec:
  replicas: 1
  selector:
    matchLabels:
      app: resource-demo
  template:
    metadata:
      labels:
        app: resource-demo
    spec:
      containers:
        - name: memory-demo
          image: polinux/stress
          command: ["stress"]
          args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
          resources:
            requests:
              cpu: 25m
              memory: 50Mi
            limits:
              cpu: 200m
              memory: 100Mi

بررسی ظرفیت پیش از آزمایش

kubectl get node playground-mj \
  -o custom-columns='NAME:.metadata.name,CPU:.status.capacity.cpu,ALLOCATABLE_CPU:.status.allocatable.cpu,MEMORY:.status.capacity.memory,ALLOCATABLE_MEMORY:.status.allocatable.memory'
kubectl describe node playground-mj
kubectl top node 2>/dev/null || echo "metrics-server is not available; continue with API status"

اگر نام Node شما متفاوت است، playground-mj را با نام واقعی خروجی kubectl get nodes جایگزین کنید.

ایجاد امن خرابی OOM

در این آزمایش Process می‌کوشد با Limit برابر ۱۰۰ MiB، مقدار ۱۵۰ MiB حافظه اختصاص دهد:

kubectl create namespace course-night-11
kubectl apply -f app.yaml
kubectl get pods --namespace course-night-11 --watch

پس از مشاهدهٔ Restart، Watch را متوقف و شواهد را جمع کنید:

kubectl get pod --namespace course-night-11 \
  -o custom-columns='NAME:.metadata.name,PHASE:.status.phase,RESTARTS:.status.containerStatuses[0].restartCount,LAST_REASON:.status.containerStatuses[0].lastState.terminated.reason,LAST_EXIT:.status.containerStatuses[0].lastState.terminated.exitCode'
kubectl describe pod --namespace course-night-11 -l app=resource-demo
kubectl get pod --namespace course-night-11 -l app=resource-demo \
  -o jsonpath='{.items[0].status.qosClass}{"\n"}'

ممکن است Pod وضعیت CrashLoopBackOff نشان دهد، اما وضعیت Container قبلی ریشهٔ اصلی را مشخص می‌کند: OOMKilled و معمولاً Exit Code برابر ۱۳۷.

تعمیر و مقایسه

مقدار --vm-bytes را در app.yaml از 150M به 50M تغییر دهید:

kubectl diff -f app.yaml
kubectl apply -f app.yaml
kubectl rollout status deployment/resource-demo --namespace course-night-11
kubectl get pods --namespace course-night-11

برای مقایسهٔ QoS، مقدار CPU Request را با CPU Limit و Memory Request را با Memory Limit برابر کنید. Apply کنید و مطمئن شوید کلاس به Guaranteed تغییر می‌کند.

مقدارهای تعمیرشده توصیهٔ Sizing برای محیط تولید نیستند. مقدار درست باید از مصرف اندازه‌گیری‌شده، رفتار در Peak، Load Test و Headroom موردنیاز به دست بیاید. Memory Limit نزدیک به مصرف عادی ناپایداری می‌سازد؛ نبود Limit هم اجازه می‌دهد یک Workload تمام Node را تهدید کند.

مشاهدهٔ اختیاری CPU

اگر Metrics Server نصب است، موقتاً یک CPU Stressor با Limit کوچک اجرا و مصرف را بررسی کنید:

kubectl top pod --namespace course-night-11 --containers

مصرف نزدیک Limit به‌تنهایی Throttling را ثابت نمی‌کند. Metricهایی مانند Throttled Seconds از Runtime یا cAdvisor شواهد قوی‌تری هستند و در بخش Observability دوره بررسی می‌شوند.

چک‌لیست پایان

  • Request، Limit، Scheduling، Throttling و خاتمهٔ OOM را توضیح می‌دهم.
  • OOMKilled را از وضعیت Container قبلی تشخیص داده‌ام.
  • Workload را تعمیر و ثابت ماندن Restartها را مشاهده کرده‌ام.
  • پیکربندی‌های QoS از نوع Burstable و Guaranteed را تشخیص داده‌ام.
  • ثبت کرده‌ام چرا مقدارهای این آزمایش، مقدار خودکار محیط تولید نیستند.
kubectl delete namespace course-night-11