שינוי גודל של עומסי עבודה ב-GKE לאפס ומאפס באמצעות HPA

במדריך הזה נסביר איך לבצע אופטימיזציה של ניצול המשאבים ב-Google Kubernetes Engine ‏(GKE) על ידי הגדרת עומסי עבודה (workload) כך שיתבצע שינוי גודל אוטומטי לאפס רפליקות כשהם לא פעילים, ושינוי גודל בחזרה כשהביקוש גדל. בגישה הזו, התאמה אופקית של קבוצות Pod לעומס (HPA) משולבת עם תשתית מנוהלת של התאמת גודל ב-GKE, כדי לנהל את ההתאמה על סמך מדדים חיצוניים.

כדי להגדיר את הפריסה כך שתצטמצם לאפס, צריך להגדיר את הערך של השדה minReplicas ל-0 ולהגדיר מדד עם הסוג External או Object בקובץ המניפסט של HPA. ‫GKE מנטר את המדדים האלה באמצעות המשאב המותאם אישית AutoscalingMetric, שעוזר להבטיח ניהול יעיל של משאבים לאפליקציות שלכם.

בשיטה הזו לא צריך להשתמש במתאמי מדדים של צד שלישי, כמו KEDA, כדי לשנות את גודל עומסי העבודה ב-GKE. הפתרון הזה מנהל את ההטמעה של מדדים ואת המלצות ההתאמה ישירות במישור הבקרה של GKE, וכך מצמצם את התקורה של ניהול האשכול.

במדריך הזה נפרס אפליקציית worker אסינכרונית לדוגמה שמבצעת עיבוד של הודעות מתור Pub/Sub. מגדירים את הכלי Horizontal Pod Autoscaler כדי לעקוב אחרי עומק התור (pubsub.googleapis.com:num_undelivered_messages) באמצעות משאב מותאם אישית AutoscalingMetric:

  • כשהודעות מגיעות למינוי: מערכת GKE מגדילה את מספר ה-Pods של העובדים כדי לעבד את התור.
  • כשהתור ריק:‏ GKE מקטין אוטומטית את מספר הרפליקות של פריסת העובדים לאפס.

המדריך הזה מיועד למפתחי אפליקציות, לאדמינים ולמפעילים של פלטפורמות ולמומחי DevOps שרוצים לייעל את השימוש במשאבים ב-GKE על ידי שינוי קנה המידה של עומסי עבודה לאפס כשהם לא פעילים.

לתשומת ליבכם

לפני שמגדירים את עומסי העבודה כך שניתן יהיה להקטין את קנה המידה שלהם לאפס, כדאי לעיין בשיקולים הבאים:

  • כדי לשנות את גודל עומסי העבודה (workloads) לאפס ומאפס באמצעות HPA, צריך שרמת הבקרה והצמתים של אשכול GKE יפעלו בגרסה 1.37 ואילך באשכולות חדשים ובאשכולות קיימים ששודרגו. אם אתם משתמשים באשכול קיים, אתם צריכים לוודא מה הגרסה שלו או לשדרג את האשכול או את הצמתים שלו לגרסה 1.37 ואילך.
  • בקובץ המניפסט של HPA צריך להשתמש בהגדרה apiVersion: autoscaling/v2 כדי לתמוך בהגדרה minReplicas: 0 ובמדדים חיצוניים.
  • לפני שמבצעים שדרוג לאחור של מאגרי צמתים לגרסה מוקדמת יותר מ-1.37, צריך לעדכן את כל מניפסטים של HPA שהוגדרו להרחבה לאפס ומאפס, ולהגדיר את השדה minReplicas לערך 1 או יותר. גרסאות קודמות ל-1.37 לא תומכות בהגדרה minReplicas: 0, ולכן עומסי עבודה יכולים להיתקע על אפס רפליקות.
  • צריך להגדיר לפחות מדד אחד של External או Object (כמו עומק התור) במנגנון האוטומטי לשינוי גודל של ה-Pod האופקי. ‫GKE לא יכול לאסוף מדדים של CPU או זיכרון (Resource) כשעומס עבודה כולל אפס Pods, ולכן מדדי משאבים בלבד לא יכולים להפעיל הגדלה מאפס.
  • המדד AutoscalingMetric,‏ HorizontalPodAutoscaler ופריסת היעד חייבים להיות באותו מרחב שמות של Kubernetes.

לפני שמתחילים

  1. התקינו את ה-CLI של Google Cloud.

  2. הגדירו שה-CLI של gcloud ישתמש בזהות המאוחדת שלכם.

    איך נכנסים ל-CLI של gcloud באמצעות הזהות המאוחדת?

  3. כדי לאתחל את ה-CLI של gcloud, הריצו את הפקודה הבאה:

    gcloud init
  4. יוצרים או בוחרים Cloud de Confiance פרויקט.

    תפקידים שנדרשים כדי לבחור או ליצור פרויקט

    • Select a project: כדי לבחור פרויקט לא צריך תפקיד IAM ספציפי – אפשר לבחור כל פרויקט שקיבלתם בו תפקיד.
    • יצירת פרויקט: כדי ליצור פרויקט, צריך את התפקיד Project Creator (roles/resourcemanager.projectCreator), שכולל את ההרשאה resourcemanager.projects.create. איך מקצים תפקידים
    • יוצרים Cloud de Confiance פרויקט:

      gcloud projects create PROJECT_ID

      מחליפים את PROJECT_ID בשם של פרויקט Cloud de Confiance שיוצרים.

    • בוחרים את הפרויקט שיצרתם: Cloud de Confiance

      gcloud config set project PROJECT_ID

      מחליפים את PROJECT_ID בשם הפרויקט ב- Cloud de Confiance .

  5. מוודאים שהחיוב מופעל בפרויקט Cloud de Confiance .

  6. מפעילים את ממשקי ה-API של GKE ו-Pub/Sub, אם הם עדיין לא מופעלים:

    תפקידים שנדרשים להפעלת ממשקי API

    כדי להפעיל ממשקי API, נדרשת ההרשאה serviceusage.services.enable. אם יצרתם את הפרויקט, סביר להניח שכבר יש לכם את ההרשאה הזו דרך התפקיד 'בעלים' (roles/owner). אחרת, תוכלו לקבל את ההרשאה הזו דרך התפקיד 'אדמין בממשק Service Usage' (roles/serviceusage.serviceUsageAdmin). איך מקצים תפקידים

    gcloud services enable container.googleapis.com pubsub.googleapis.com

התפקידים הנדרשים

כדי לקבל את ההרשאות שדרושות להשלמת המדריך הזה, צריך לבקש מהאדמין להקצות לכם בפרויקט את תפקידי ה-IAM הבאים:

להסבר על מתן תפקידים, ראו איך מנהלים את הגישה ברמת הפרויקט, התיקייה והארגון.

יכול להיות שאפשר לקבל את ההרשאות הנדרשות גם באמצעות תפקידים בהתאמה אישית או תפקידים מוגדרים מראש.

מגדירים את הסביבה

כדי לפשט את התהליך, הפקודות במדריך הזה יוצרות את כל המשאבים (אשכול GKE, נושא Pub/Sub והמינוי) ב Cloud de Confiance by S3NS פרויקט אחד (PROJECT_ID).

כדי להגדיר את הסביבה:

  1. הגדרת משתני סביבה:

    export PROJECT_ID=PROJECT_ID
    export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format 'get(projectNumber)')
    export LOCATION=LOCATION
    

    מחליפים את מה שכתוב בשדות הבאים:

    • ‫PROJECT_ID: מזהה הפרויקט ב- Cloud de Confiance by S3NS.
    • ‫LOCATION: האזור או האזור שבו רוצים ליצור את אשכול GKE, למשל us-central1. במקרים של אשכולות Autopilot, מציינים אזור.
  2. יוצרים אשכול GKE בגרסה 1.37 ואילך עם איחוד זהויות של עומסי עבודה ל-GKE מופעל. מומלץ להשתמש באשכול Autopilot כדי ליהנות מחוויית Kubernetes מנוהלת באופן מלא ולמקסם את החיסכון בעלויות כשעומסי העבודה מצטמצמים לאפס. כדי לבחור את מצב הפעולה שהכי מתאים לעומסי העבודה שלכם, אפשר לעיין במאמר בחירת מצב פעולה של GKE.

    טייס אוטומטי

    יצירת אשכול Autopilot:

    gcloud container clusters create-auto scale-to-zero \
        --project=${PROJECT_ID} \
        --location=${LOCATION}
    

    איחוד זהויות של עומסי עבודה ל-GKE מופעל כברירת מחדל באשכולות Autopilot.

    רגילה

    יוצרים אשכול Standard עם איחוד זהויות של עומסי עבודה ל-GKE:

    gcloud container clusters create scale-to-zero \
        --project=${PROJECT_ID} \
        --location=${LOCATION} \
        --workload-pool=${PROJECT_ID}.s3ns.svc.id.goog
    
  3. מגדירים את kubectl כדי לתקשר עם האשכול:

    gcloud container clusters get-credentials scale-to-zero \
        --project=${PROJECT_ID} \
        --location=${LOCATION}
    

יצירת משאבי Pub/Sub

במדריך הזה נשתמש בעומק התור של Pub/Sub כדוגמה למקור חיצוני של מדדים.

כדי ליצור נושא ומינוי Pub/Sub:

  1. יוצרים נושא Pub/Sub:

    gcloud pubsub topics create my-worker-topic \
        --project=${PROJECT_ID}
    
  2. יוצרים מינוי שמצורף לנושא:

    gcloud pubsub subscriptions create my-worker-subscription \
        --topic=my-worker-topic \
        --project=${PROJECT_ID}
    

הגדרת איחוד זהויות של עומסי עבודה ל-GKE

מגדירים איחוד זהויות של עומסי עבודה ל-GKE כדי לאפשר לאפליקציית העובד לבצע אימות באמצעות ממשקי API של Cloud de Confiance ולצרוך הודעות מ-Pub/Sub.

‫GKE מטפל אוטומטית באימות עם Cloud Monitoring עבור משאבי AutoscalingMetric באותו פרויקט. מידע נוסף על הגדרת מדדים לצורך שינוי גודל אוטומטי זמין במאמר אחזור מדדים מותאמים אישית או חיצוניים מ-Cloud Monitoring.

כדי להגדיר איחוד זהויות של עומסי עבודה ל-GKE עבור עומס העבודה של העובד, מבצעים את השלבים הבאים:

  1. יוצרים חשבון שירות של Kubernetes לאפליקציית העובד במרחב השמות default:

    kubectl create serviceaccount async-worker-sa \
        --namespace default
    
  2. מקצים את התפקיד roles/pubsub.subscriber לחשבון השירות של Kubernetes כדי שהאפליקציה תוכל לקבל הודעות מהמינוי שלכם ל-Pub/Sub:

    gcloud projects add-iam-policy-binding projects/${PROJECT_ID} \
        --role=roles/pubsub.subscriber \
        --member=principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.s3ns.svc.id.goog/subject/ns/default/sa/async-worker-sa
    

מידע נוסף זמין במאמר הגדרת אפליקציות לשימוש באיחוד שירותי אימות הזהות של עומסי עבודה ב-GKE.

יצירת פריסה לדוגמה

כדי ליצור אובייקט HPA, צריך קודם ליצור את עומס העבודה שהוא ינטר.

כדי ליצור את פריסת הדוגמה, מבצעים את השלבים הבאים:

  1. שומרים את קובץ המניפסט הבא בשם async-worker.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: async-worker
      namespace: default
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: async-worker
      template:
        metadata:
          labels:
            app: async-worker
        spec:
          containers:
          - name: async-worker
            image: nginx:latest
            ports:
            - containerPort: 80
            resources:
              limits:
                memory: 100Mi
              requests:
                cpu: 50m
                memory: 100Mi
    
  2. מחילים את הפריסה async-worker.yaml:

    kubectl apply -f async-worker.yaml
    

הגדרת עומס עבודה להרחבה לאפס ומאפס

בקטע הזה מגדירים את async-worker הפריסה כך שהיא תצטמצם לאפס כשהתור של Pub/Sub ריק, ותתרחב מחדש כשהודעות חדשות יגיעו.

יצירת משאב AutoscalingMetric

כדי להגדיר את האות החיצוני שמנוטר על ידי GKE, יוצרים את המשאב המותאם אישית AutoscalingMetric. במניפסט לדוגמה הבא, המדד שולח שאילתה ל-Cloud Monitoring כדי לקבל את מספר ההודעות ב-Pub/Sub שלא נמסרו במינוי my-worker-subscription.

כדי ליצור את משאב AutoscalingMetric, פועלים לפי השלבים הבאים:

  1. שומרים את קובץ המניפסט הבא כקובץ pubsub-metric.yaml:

    apiVersion: autoscaling.gke.io/v1beta1
    kind: AutoscalingMetric
    metadata:
      name: pubsub-queue-depth
      namespace: default
    spec:
      metrics:
      - promql:
          name: pubsub-undelivered
          query: >
              {
                "pubsub.googleapis.com/subscription/num_undelivered_messages",
                subscription_id="my-worker-subscription"
              }
    
  2. החלת המניפסט pubsub-metric.yaml:

    kubectl apply -f pubsub-metric.yaml
    
  3. מאמתים את סטטוס המדד ומאחזרים את מזהה המדד:

    kubectl describe autoscalingmetric pubsub-queue-depth
    

    בקטע Status של הפלט, מוודאים שלא מופיעות שגיאות ורושמים את הערך Hpa Name בפורמט autoscaling.gke.io|CUSTOM_RESOURCE_NAME|METRIC_NAME. תצטרכו להשתמש במזהה הזה של המדד החיצוני כשתיצרו את אובייקט HorizontalPodAutoscaler בקטע הבא. אם בקטע Status מדווח על שגיאות בהגדרות או שהמדדים לא מאוחזרים כצפוי, אפשר לעיין במאמר פתרון בעיות שקשורות למדדים שמאוחזרים לצורך שינוי גודל אוטומטי.

הגדרת Horizontal Pod Autoscaler

כדי להגדיר את ההתנהגות של התאמה אוטומטית לעומס, יוצרים משאב HorizontalPodAutoscaler שמטרגט את הפריסה.

כדי להגדיר את הכלי האוטומטי לשינוי גודל של Pod אופקי:

  1. שומרים את קובץ המניפסט הבא כקובץ worker-hpa.yaml:

    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
      name: async-worker-hpa
      namespace: default
    spec:
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: async-worker
      minReplicas: 0
      maxReplicas: 20
      metrics:
      - type: External
        external:
          metric:
            name: autoscaling.gke.io|pubsub-queue-depth|pubsub-undelivered
          target:
            type: AverageValue
            averageValue: "10"
    

    קובץ המניפסט הזה מגדיר את שדות המפתח הבאים:

    • ‫minReplicas: 0: מאפשרת את התכונה scale-to-zero (שינוי קנה מידה לאפס) בכך שהיא מאפשרת לבקר לשנות את קנה המידה של הפריסה ל-0 רפליקות כשהביקוש יורד לאפס.
    • ‫type: External: מגדיר מקור חיצוני של מדדים כדי שה-HPA יוכל להפעיל הגדלה כשאין פודים בעומס העבודה.
    • ‫name: autoscaling.gke.io|pubsub-queue-depth|pubsub-undelivered: ממפה את ה-HPA ישירות למשאב AutoscalingMetric שנוצר בשלב הקודם באמצעות פורמט המזהה autoscaling.gke.io|CUSTOM_RESOURCE_NAME|METRIC_NAME.
  2. החלת המניפסט worker-hpa.yaml:

    kubectl apply -f worker-hpa.yaml
    

אימות ההתנהגות והתנאים של אפס משקל

אחרי שכל ההודעות במינוי Pub/Sub מעובדות, המערכת Horizontal Pod Autoscaler (HPA) מעריכה את הביקוש לאפס ומקטינה את הפריסה ל-0 רפליקות.

כדי לוודא שהמידרוג האוטומטי האופקי של ה-Pod הפעיל את מצב האפס, בודקים את תנאי הסטטוס של async-worker-hpa המשאב על ידי הרצת הפקודה הבאה:

kubectl describe hpa async-worker-hpa

הפלט אמור להיראות כך:

Name:             async-worker-hpa
Namespace:        default
Reference:        Deployment/async-worker
Metrics:          ( current / target )
  "autoscaling.gke.io|pubsub-queue-depth|pubsub-undelivered" (external metric):  0 / 10
Min replicas:     0
Max replicas:     20
Deployment pods:  0 current / 0 desired
Conditions:
  Type            Status  Reason               Message
  ----            ------  ------               -------
  AbleToScale     True    SucceededGetScale    the HPA controller was able to get the target's current scale
  ScalingActive   True    ValidMetricFound     the HPA was able to successfully calculate a replica count from external metric
  ScaledToZero    True    ScaledToZero         the HPA has scaled the target resource to 0 replicas due to zero metric demand

הסבר על התנאי ScaledToZero

תנאי ScaledToZero מציין אם המערכת Horizontal Pod Autoscaler (HPA) שינתה את קנה המידה של עומס העבודה לאפס רפליקות:

  • ‫ScaledToZero: True (Reason: ScaledToZero): מציין שבקר ה-HPA שינה את קנה המידה של עומס העבודה ל-0 רפליקות כי הביקוש למדד חיצוני ירד לאפס. ה-HPA נשאר פעיל (ScalingActive: True) ומבצע כל הזמן בדיקות ב-GKE כדי לזהות מתי הביקוש לעומס העבודה גדל.
  • ‫ScaledToZero: False: מציין שעומס העבודה הורחב לשכפול אחד או יותר.

אם משנים את קנה המידה של פריסה באופן ידני לאפס רפליקות, למשל באמצעות הפקודה kubectl scale --replicas=0, ה-HPA משהה את ההתאמה האוטומטית לעומס (ScalingActive: False) כדי למנוע שינויים סותרים. כדי להפעיל מחדש את ההתאמה האוטומטית לעומס, צריך להגדיל את מספר הרפליקות של הפריסה לאחת או יותר (kubectl scale deployment async-worker --replicas=1).

לתרחישי פתרון בעיות שבהם עומסי עבודה לא מצליחים להצטמצם לאפס או לא מצליחים להתרחב מאפס, אפשר לעיין במאמר פתרון בעיות בהרחבת עומסי עבודה ב-GKE לאפס ומאפס באמצעות HPA. אם מופיע דיווח על מדדים חיצוניים חסרים או לא תקינים ב-Horizontal Pod Autoscaler, אפשר לעיין במאמר פתרון בעיות שקשורות למדדים שנשלפים לצורך שינוי גודל אוטומטי של פודים.

הסרת המשאבים

כדי להימנע מחיובים בחשבון Cloud de Confiance by S3NS על המשאבים שבהם השתמשתם במדריך הזה, פועלים לפי השלבים הבאים:

  1. מחיקת אשכול GKE:

    gcloud container clusters delete scale-to-zero \
        --project=${PROJECT_ID} \
        --location=${LOCATION}
    
  2. מחיקת המינוי והנושא ב-Pub/Sub:

    gcloud pubsub subscriptions delete my-worker-subscription \
        --project=${PROJECT_ID}
    gcloud pubsub topics delete my-worker-topic \
        --project=${PROJECT_ID}
    

המאמרים הבאים