Rightsizing ב-Kubernetes: מדריך מעשי לחיסכון של 40-70% בעלויות הענן

מדריך מעשי לחיסכון של 40-70% בעלויות Kubernetes באמצעות rightsizing. כולל הגדרת VPA, Goldilocks, Karpenter ודוגמאות קוד מלאות שאפשר ליישם כבר היום.

למה אתם כנראה משלמים יותר מדי על Kubernetes

בכנות? כשראיתי את הנתונים לראשונה, לא האמנתי. לפי סקר CNCF עדכני, כ-68% מהארגונים משלמים על Kubernetes בין 20% ל-40% יותר מהנדרש. וזה עוד מעט — בביקורות שנערכו ב-2026 מגלים ש-80-90% מה-Pods מוגדרים עם בקשות CPU וזיכרון מנופחות לגמרי. מחקר אחד אפילו מצא פער של פי 8 בין ה-CPU המבוקש לבין השימוש בפועל. פי שמונה.

אז איך זה קורה? ברוב המקרים, מפתחים מגדירים ערכי requests גבוהים כדי להימנע מ-throttling או מקריסות OOMKill. זו גישה שמובנת לחלוטין — עדיף בטוח מאשר מצטער, נכון? — אבל מבחינה כלכלית, היא שורפת כסף. כשה-Pod מבקש יותר משאבים ממה שהוא באמת צריך, ה-scheduler של Kubernetes שומר את הקיבולת הזו גם אם היא לא מנוצלת. התוצאה? Nodes שנראים "מלאים" בעוד שהשימוש בפועל נמוך, וה-Cluster Autoscaler מוסיף Nodes מיותרים בשמחה.

דוגמה קטנה שעושה את זה מוחשי: Node עם 4 ליבות שמריץ 4 Pods, כל אחד מבקש ליבה אחת אבל צורך בפועל 0.2 ליבות — מבזבז 68% מהקיבולת. הכפילו את זה ב-50 או 100 Nodes ומקבלים בזבוז של אלפי דולרים. בחודש.

המדריך הזה יראה לכם בדיוק איך לזהות את הבזבוז, למדוד את השימוש האמיתי, וליישם rightsizing בצורה בטוחה — עם כלים ודוגמאות קוד שאפשר להפעיל כבר היום.

מה זה Rightsizing ולמה זו ההשקעה הכי משתלמת ב-FinOps

Rightsizing בהקשר של Kubernetes הוא בעצם התהליך של התאמת הקצאות המשאבים — CPU, זיכרון, ואחסון — לצריכה האמיתית של כל workload. לא יותר, לא פחות. המטרה היא למצוא את נקודת האיזון בין ביצועים, יעילות, ועלות.

ולמה זו ההשקעה הכי משתלמת? כי אפילו הפחתה קטנה של 5-15% בהקצאות לכל Pod יכולה להצטבר לחיסכון של 30-60% ברמת ה-Cluster, הודות ל-bin packing יעיל יותר. ארגונים שמיישמים rightsizing שיטתי מדווחים על חיסכון של 40-70% בעלויות Kubernetes — בלי לפגוע בביצועים. מספרים שקשה להתווכח איתם.

לפני שממשיכים, חשוב להבין שני מושגים מרכזיים:

  • Requests — כמות המשאבים המינימלית שה-Pod מבקש. ה-scheduler משתמש בערך הזה כדי להחליט על איזה Node לשבץ את ה-Pod.
  • Limits — התקרה המקסימלית. אם ה-Pod חורג מגבול הזיכרון, הוא נהרג (OOMKill). חורג מ-CPU? מקבל throttling.

הגדרת requests נכונה היא הצעד הקריטי ביותר — כי זה מה שקובע כמה Nodes תצטרכו, ובסופו של דבר כמה תשלמו.

שלב 1: זיהוי בזבוז — כמה באמת מנוצל?

לפני שמתחילים לשנות הגדרות, צריך להבין את המצב הקיים. אי אפשר לתקן מה שלא מודדים. הנה פקודת kubectl שתראה לכם את הפער בין מה שמבוקש לבין מה שמנוצל בפועל:

kubectl top pods -n production --containers | \
  awk 'NR==1{print $0, "REQ_CPU", "REQ_MEM"} NR>1{print}' | \
  column -t

לתמונה מפורטת יותר, הנה סקריפט שמשווה בין requests לשימוש אמיתי ומחשב ניצולת:

#!/bin/bash
# pod-utilization-report.sh
# דוח ניצולת משאבים לכל ה-Pods ב-namespace

NAMESPACE=${1:-default}

echo "=== Pod Utilization Report for namespace: $NAMESPACE ==="
echo ""
printf "%-40s %-12s %-12s %-10s %-12s %-12s %-10s\n" \
  "POD" "CPU_REQ" "CPU_USED" "CPU_%" "MEM_REQ" "MEM_USED" "MEM_%"
echo "-----------------------------------------------------------------------------------------------------------"

kubectl get pods -n "$NAMESPACE" -o json | jq -r '
  .items[] |
  .metadata.name as $pod |
  .spec.containers[] |
  "\($pod) \(.resources.requests.cpu // "none") \(.resources.requests.memory // "none")"
' | while read pod cpu_req mem_req; do
  usage=$(kubectl top pod "$pod" -n "$NAMESPACE" --no-headers 2>/dev/null)
  if [ -n "$usage" ]; then
    cpu_used=$(echo "$usage" | awk '{print $2}')
    mem_used=$(echo "$usage" | awk '{print $3}')
    printf "%-40s %-12s %-12s %-10s %-12s %-12s\n" \
      "$pod" "$cpu_req" "$cpu_used" "" "$mem_req" "$mem_used"
  fi
done

הריצו את הסקריפט על כל namespace ותקבלו תמונה ברורה של היכן הבזבוז הגדול ביותר. חפשו Pods שבהם הניצולת מתחת ל-30% — אלו המועמדים הראשונים ל-rightsizing.

שלב 2: הגדרת VPA במצב המלצות בלבד

Vertical Pod Autoscaler (VPA) הוא כלי Kubernetes שמנתח שימוש במשאבים ומספק המלצות — או מיישם אותן אוטומטית — להקצאות CPU וזיכרון. ב-2026, ה-API היציב הוא autoscaling.k8s.io/v1.

ההמלצה שלי? התחילו תמיד במצב Off. ככה אתם מקבלים המלצות בלי שVPA נוגע בשום דבר — אפס סיכון.

התקנת VPA

# התקנה באמצעות Helm
helm repo add cowboysysop https://cowboysysop.github.io/charts/
helm install vpa cowboysysop/vertical-pod-autoscaler \
  --namespace kube-system

# ודאו שכל הרכיבים רצים
kubectl get pods -n kube-system | grep vpa

הגדרת VPA במצב Off

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: myapp-vpa
  namespace: production
spec:
  targetRef:
    apiVersion: "apps/v1"
    kind: Deployment
    name: myapp
  updatePolicy:
    updateMode: "Off"
  resourcePolicy:
    containerPolicies:
    - containerName: myapp-container
      minAllowed:
        cpu: 50m
        memory: 64Mi
      maxAllowed:
        cpu: 4
        memory: 8Gi
      controlledResources:
      - cpu
      - memory

אחרי כמה ימים של איסוף נתונים (אני ממליץ על לפחות 3-5 ימים), בדקו את ההמלצות:

kubectl describe vpa myapp-vpa -n production

בפלט תראו שלושה ערכים שכדאי לשים לב אליהם:

  • Lower Bound — המינימום שנדרש כדי להימנע מ-throttling
  • Target — ההמלצה האופטימלית של VPA
  • Upper Bound — המקסימום שה-Pod עשוי להזדקק לו

כלל אצבע שעובד לי טוב: הגדירו את ה-request לערך ה-Target, ואת ה-limit ל-10-50% מעל (תלוי כמה אתם שמרנים). לגבי זיכרון, מומלץ להשתמש ב-P95 של ה-working set כבסיס.

שלב 3: התקנת Goldilocks — דשבורד ויזואלי להמלצות

אז VPA נותן המלצות, אבל לרוץ בין עשרות פקודות kubectl זה לא כיף. כאן נכנס Goldilocks — כלי קוד פתוח מבית Fairwinds שיושב מעל VPA ומספק דשבורד ויזואלי ממש נוח. פשוט פותחים דפדפן ורואים את כל ה-Deployments עם ההמלצות שלהם במקום אחד.

התקנה

# התקנת Goldilocks באמצעות Helm
helm repo add fairwinds-stable https://charts.fairwinds.com/stable
kubectl create namespace goldilocks
helm install goldilocks --namespace goldilocks \
  fairwinds-stable/goldilocks

הפעלה על namespace

# סמנו את ה-namespace שרוצים לנטר
kubectl label namespace production \
  goldilocks.fairwinds.com/enabled=true

# Goldilocks ייצור אוטומטית VPA objects עבור כל Deployment

גישה לדשבורד

# פתחו port-forward לדשבורד
kubectl -n goldilocks port-forward svc/goldilocks-dashboard 8080:80

# פתחו בדפדפן: http://localhost:8080

הדשבורד מציג שני סוגי המלצות:

  • Guaranteed QoS — requests ו-limits שווים, מבוסס על Target של VPA. מתאים ל-workloads קריטיים שלא רוצים שום הפתעות.
  • Burstable QoS — requests נמוכים מ-limits, מבוסס על Lower Bound ו-Upper Bound. מתאים ל-workloads עם שינויים בעומס.

טיפ חשוב (ולמדתי את זה בדרך הקשה): ככל שה-Pods רצים יותר זמן, הנתונים שVPA אוסף מדויקים יותר. המתינו לפחות שבוע לפני שמיישמים המלצות, ובדקו שוב אחרי חודש.

שלב 4: יישום ההמלצות בצורה בטוחה

אוקיי, אספתם מספיק נתונים ויש לכם המלצות ברורות מ-VPA ו-Goldilocks. הגיע הזמן ליישם. אבל — ולא אלאה לחזור על זה — עשו את זה בהדרגה. לא הכול בבת אחת.

תהליך מומלץ

  1. התחילו מסביבת staging — יישמו את ההמלצות קודם בסביבה שאינה production. תמיד.
  2. עדכנו Deployment אחד בכל פעם — אל תשנו את כל ה-Deployments בבת אחת (כן, גם אם זה מפתה).
  3. עקבו אחרי מדדים — בדקו CPU throttling, OOMKills, ו-latency לפני ואחרי השינוי.
  4. הגדירו התראות — צרו alerts על חריגות בביצועים כדי שלא תגלו בעיות באיחור.

הנה דוגמה לעדכון Deployment עם הערכים החדשים:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-server
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api-server
  template:
    metadata:
      labels:
        app: api-server
    spec:
      containers:
      - name: api
        image: myapp/api-server:latest
        resources:
          requests:
            cpu: 150m      # היה 500m - הופחת על בסיס VPA Target
            memory: 256Mi  # היה 1Gi - הופחת על בסיס P95
          limits:
            cpu: 300m      # 2x requests - מאפשר burst
            memory: 384Mi  # 1.5x requests - מרווח ביטחון

שימו לב לירידה — מ-500m ל-150m ב-CPU ומ-1Gi ל-256Mi בזיכרון. זה חיסכון משמעותי ל-Pod בודד, ומשמעותי בהרבה כשמכפילים את זה ב-replicas ו-deployments.

אחרי העדכון, עקבו אחרי המדדים האלה:

# בדיקת OOMKills
kubectl get events -n production --field-selector reason=OOMKilling

# בדיקת CPU throttling (דורש metrics-server)
kubectl top pods -n production --sort-by=cpu

# בדיקת סטטוס Pods
kubectl get pods -n production -o wide

שלב 5: אופטימיזציה ברמת ה-Node עם Karpenter

Rightsizing ברמת ה-Pod הוא רק חצי מהסיפור. החצי השני? אופטימיזציה ברמת ה-Node.

כאן Karpenter נכנס לתמונה. Karpenter הוא autoscaler קוד פתוח ל-Kubernetes שמספק Nodes בזמן אמת בהתאם לצרכי ה-Pods. בניגוד ל-Cluster Autoscaler המסורתי שעובד עם Node Groups קבועים מראש, Karpenter בוחר את סוג המכונה האופטימלי עבור כל Pod — כולל תמיכה ב-Spot Instances.

למה זה שינוי כללי משחק

  • Just-in-Time Provisioning — יוצר בדיוק את ה-Node שצריך, בגודל הנכון. לא יותר, לא פחות.
  • Consolidation — מזהה Nodes עם ניצולת נמוכה ומחליף אותם ב-Nodes קטנים יותר
  • תמיכה ב-Spot Instances — שילוב אוטומטי של Spot עם On-Demand לחיסכון נוסף של 60-90%
  • פשטות — אין צורך לנהל עשרות Node Groups כמו ב-Cluster Autoscaler. פחות YAML, יותר שקט.

דוגמת NodePool

apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: cost-optimized
spec:
  template:
    spec:
      requirements:
      - key: karpenter.sh/capacity-type
        operator: In
        values: ["spot", "on-demand"]  # מעדיף Spot, fallback ל-On-Demand
      - key: node.kubernetes.io/instance-type
        operator: In
        values:
        - m7i.large
        - m7i.xlarge
        - m6i.large
        - m6i.xlarge
        - c7i.large
        - c7i.xlarge
      - key: topology.kubernetes.io/zone
        operator: In
        values:
        - us-east-1a
        - us-east-1b
        - us-east-1c
  limits:
    cpu: 200
    memory: 400Gi
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized
    consolidateAfter: 30s

ההגדרה consolidationPolicy: WhenEmptyOrUnderutilized היא המפתח כאן — Karpenter ינטר Nodes עם ניצולת נמוכה ויחליף אותם ב-Nodes קטנים וזולים יותר, באופן אוטומטי. זה כמו rightsizing ברמת התשתית.

הגנה מפני בזבוז עתידי: LimitRange ו-ResourceQuota

Rightsizing הוא לא פעולה חד-פעמית — וזה משהו שהרבה צוותים לומדים בדרך הקשה. בלי מדיניות שמונעת בזבוז חוזר, כל deployment חדש עלול לחזור להגדרות מנופחות. למזלנו, Kubernetes מספק שני כלים מובנים בדיוק בשביל זה.

LimitRange — ברירות מחדל וגבולות לכל Pod

apiVersion: v1
kind: LimitRange
metadata:
  name: pod-resource-limits
  namespace: production
spec:
  limits:
  - type: Container
    default:
      cpu: 200m
      memory: 256Mi
    defaultRequest:
      cpu: 100m
      memory: 128Mi
    max:
      cpu: 2
      memory: 4Gi
    min:
      cpu: 50m
      memory: 64Mi

LimitRange מבטיח שכל Container חדש שנוצר ב-namespace יקבל ברירות מחדל סבירות. מפתח שלא הגדיר resources? לא נורא, הוא יקבל אותם אוטומטית. וגם לא יוכל לבקש יותר מהמקסימום המוגדר.

ResourceQuota — תקרת משאבים לכל ה-namespace

apiVersion: v1
kind: ResourceQuota
metadata:
  name: production-quota
  namespace: production
spec:
  hard:
    requests.cpu: "20"
    requests.memory: 40Gi
    limits.cpu: "40"
    limits.memory: 80Gi
    pods: "100"

ResourceQuota מגביל את סך המשאבים שכל ה-Pods ב-namespace יכולים לצרוך. בלי זה, צוות אחד יכול "לאכול" את כל הקיבולת של ה-Cluster בלי שאף אחד שם לב.

תהליך Rightsizing שוטף — לוח זמנים מומלץ

אז הגדרתם הכול, הכלים רצים, חסכתם כסף. מעולה. אבל כדי שזה יימשך, צריך להפוך את זה לשגרה. הנה לוח הזמנים שעובד לנו:

  • שבועי — הצצה מהירה לדשבורד Goldilocks לזיהוי חריגות בולטות
  • חודשי — סבב rightsizing לכל ה-Deployments ועדכון requests/limits
  • אחרי כל שינוי משמעותי — עדכוני קוד גדולים, שינויי תנועה, או שדרוגי תלויות דורשים בדיקה מחדש
  • רבעוני — סקירה של מדיניות ה-LimitRange וה-ResourceQuota מול דפוסי השימוש העדכניים

שאלות נפוצות

איך עושים rightsizing ל-Pods ב-Kubernetes?

התהליך מתחיל בניטור צריכת המשאבים בפועל באמצעות כלים כמו metrics-server, VPA, ו-Goldilocks. אחרי איסוף נתונים של לפחות שבוע, משווים בין ה-requests/limits הנוכחיים לבין השימוש האמיתי, ומתאימים את ההגדרות כך שה-requests יהיו קרובים ל-P95 של הצריכה. מומלץ לעשות את זה בהדרגה — namespace אחד בכל פעם — ולעקוב אחרי מדדי ביצועים אחרי כל שינוי.

כמה אפשר לחסוך מ-rightsizing של Kubernetes?

ארגונים שמיישמים rightsizing שיטתי מדווחים על חיסכון של 30-70%. לדוגמה, חברת Trax חסכה 75% בעלויות Kubernetes באמצעות rightsizing אוטומטי, ו-SNCF הפחיתה 30% מהעלויות תוך שיפור היציבות. גם הפחתות קטנות לכל Pod מצטברות לחיסכון גדול ברמת ה-Cluster.

מה עדיף — VPA או HPA?

הם לא מתחרים, הם משלימים. VPA מתאים requests/limits אנכית (יותר CPU/זיכרון לכל Pod), בעוד HPA מוסיף או מפחית Pods אופקית. דפוס נפוץ שעובד טוב: HPA לסקיילינג על בסיס CPU, ו-VPA במצב Off לקבלת המלצות לזיכרון. רק ודאו שהמלצות VPA לא מתנגשות עם טריגרים של HPA.

האם VPA מפיל Pods בזמן עדכון?

תלוי במצב. במצב Off ו-Initial — VPA לא נוגע ב-Pods בכלל. במצב Recreate, VPA מסיר ומייצר Pods מחדש כדי ליישם שינויים. החל מגרסה 1.4, יש מצב InPlaceOrRecreate שמנסה לעדכן משאבים בלי restart — ואם לא מצליח, חוזר ל-eviction. לסביבות production, התחילו עם Off והעלו בהדרגה.

כל כמה זמן צריך לעשות rightsizing?

כשגרה — פעם בחודש. בנוסף לזה, בדקו מחדש אחרי שינויי קוד משמעותיים, שינויים בתבניות תנועה, שדרוגי תלויות, או אירועים חריגים. ארגונים מתקדמים כבר עברו ל-rightsizing אוטומטי מתמשך עם Karpenter ו-VPA במצב Auto, עם guardrails שמגנים מפני הפתעות.

אודות הכותב Editorial Team

Our team of expert writers and editors.