הקצאת קיבולת מחשוב נוספת להתאמה מהירה של Pod לעומס

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

למה כדאי להקצות קיבולת עודפת

באשכולות GKE Autopilot ובאשכולות Standard עם הקצאת צמתים אוטומטית, נוצרים צמתים חדשים כשאין צמתים קיימים עם קיבולת להפעלת Pods חדשים. הפעלה של כל צומת חדש נמשכת בערך 80 עד 120 שניות. מערכת GKE מחכה עד שהצומת יופעל לפני שהיא מציבה את ה-Pods שממתינים בצומת החדש, ואז ה-Pods יכולים להתחיל לפעול. במקום זאת, באשכולות רגילים אפשר ליצור מאגר צמתים חדש באופן ידני עם הקיבולת הנוספת שדרושה להפעלת Pods חדשים. הדף הזה רלוונטי לאשכולות שמשתמשים במנגנון של שינוי גודל אוטומטי של צמתים, כמו Autopilot או הקצאת צמתים אוטומטית (NAP).

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

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

איך פועל הקצאת קיבולת עודפת ב-GKE

כדי להקצות קיבולת עודפת, אפשר להשתמש ב-PriorityClasses של Kubernetes וב-Pods של placeholder. בעזרת PriorityClass אפשר להגדיר ב-GKE שעומסי עבודה מסוימים הם בעדיפות נמוכה יותר מעומסי עבודה אחרים. אפשר לפרוס תרמילי placeholder שמשתמשים ב-PriorityClass עם עדיפות נמוכה ולבקש את קיבולת המחשוב שצריך לשריין. ‫GKE מוסיף קיבולת לאשכול על ידי יצירת צמתים חדשים כדי להכיל את ה-Pods של ה-placeholder.

כשעומסי העבודה של הייצור גדלים, GKE מפנה את מקום הפודים של ה-placeholder בעדיפות נמוכה יותר, ומתזמן במקומם את העותקים החדשים של הפודים של הייצור (שמשתמשים ב-PriorityClass בעדיפות גבוהה יותר). אם יש לכם כמה פודים בעדיפות נמוכה עם רמות עדיפות שונות, GKE יסיר קודם את הפודים בעדיפות הנמוכה ביותר.

כשמפנים מקום ל-Pod של placeholder, הוא חוזר למצב Pending. אם משתמשים בפריסה לאספקת הקצאה עקבית, בקר הפריסה מנסה ליצור מחדש את ה-Pod באופן מיידי. אם ל-Pod של placeholder יש עדיפות של ‎-10, הוא יפעיל את שינוי הגודל האוטומטי של האשכול כדי ליצור צומת חדש (אם צריך) במקום הקיבולת השמורה שבה השתמשתם. המחזור הזה עוזר לוודא שתמיד יש באשכול את כמות הקיבולת הרזרבית שצוינה.

שיטות הקצאת קיבולת

בהתאם לתרחיש השימוש, אתם יכולים להקצות קיבולת נוספת באשכולות GKE באחת מהדרכים הבאות:

  • הקצאת קיבולת עקבית: אפשר להשתמש בפריסה כדי ליצור מספר מסוים של תרמילי Pods עם עדיפות נמוכה שפועלים כל הזמן באשכול. כש-GKE מפנה את ה-Pods האלה כדי להריץ את עומסי העבודה של הייצור, בקר הפריסה מוודא ש-GKE מספק יותר קיבולת כדי ליצור מחדש את ה-Pods בעדיפות הנמוכה שהופנו. השיטה הזו מספקת תקורה עקבית של קיבולת בכמה אירועי הגדלה והקטנה, עד למחיקת הפריסה.
  • הקצאת קיבולת לשימוש חד-פעמי: שימוש במשימה להפעלת מספר מסוים של פודי placeholder מקבילים בעדיפות נמוכה למשך תקופה מסוימת. אחרי שהזמן הזה חולף או אחרי ש-GKE מפנה את כל העותקים המשוכפלים של המשימה, הקיבולת השמורה מפסיקה להיות זמינה. השיטה הזו מספקת כמות ספציפית של קיבולת זמינה לתקופה מסוימת.

תמחור

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

ב-GKE Standard, אתם מחויבים על המכונות הווירטואליות הבסיסיות של Compute Engine ש-GKE מקצה, בלי קשר לשאלה אם ה-Pods משתמשים בקיבולת הזו. לפרטים נוספים, ראו תמחור רגיל

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

לפני שמתחילים, חשוב לוודא שביצעתם את הפעולות הבאות:

  • מפעילים את ממשק ה-API של Google Kubernetes Engine.
  • הפעלת Google Kubernetes Engine API
  • אם רוצים להשתמש ב-CLI של Google Cloud למשימה הזו, צריך להתקין ואז להפעיל את ה-CLI של gcloud. אם התקנתם בעבר את ה-CLI של gcloud, מריצים את הפקודה gcloud components update כדי לקבל את הגרסה העדכנית. יכול להיות שגרסאות קודמות של ה-CLI של gcloud לא יתמכו בהרצת הפקודות שמופיעות במסמך הזה.
  • מוודאים שיש לכם אשכול GKE Autopilot או אשכול GKE Standard עם הקצאת צמתים אוטומטית מופעלת.
  • כדאי לקרוא את השיקולים לגבי הקצאת קיבולת כדי לוודא שאתם בוחרים ערכים מתאימים בבקשות הקיבולת.

יצירת PriorityClass

כדי להשתמש באחת מהשיטות שמתוארות במאמר בנושא שיטות הקצאת קיבולת, צריך קודם ליצור את PriorityClass הבאים:

  • Default PriorityClass: PriorityClass גלובלי שמוגדר כברירת מחדל ומוקצה לכל Pod שלא הוגדר לו במפורש PriorityClass אחר במפרט ה-Pod. ל-Pods עם PriorityClass שמוגדר כברירת מחדל יש אפשרות להוציא משימוש Pods שמשתמשים ב-PriorityClass נמוך יותר.
  • Low PriorityClass: PriorityClass שאינו ברירת מחדל ומוגדר לעדיפות הנמוכה ביותר האפשרית ב-GKE. אפשר להוציא מ-Pods עם PriorityClass כזה כדי להריץ Pods עם PriorityClass גבוה יותר.
  1. שומרים את קובץ המניפסט הבא בשם priorityclasses.yaml:

    apiVersion: scheduling.k8s.io/v1
    kind: PriorityClass
    metadata:
      name: low-priority
    value: -10
    preemptionPolicy: Never
    globalDefault: false
    description: "Low priority workloads"
    ---
    apiVersion: scheduling.k8s.io/v1
    kind: PriorityClass
    metadata:
      name: default-priority
    value: 0
    preemptionPolicy: PreemptLowerPriority
    globalDefault: true
    description: "The global default priority."
    

    המניפסט הזה כולל את השדות הבאים:

    • preemptionPolicy: מציין אם אפשר להוציא משימוש Pods עם עדיפות נמוכה יותר ב-Pods שמשתמשים ב-PriorityClass. ‫low-priority PriorityClass משתמש ב-Never, ו-default PriorityClass משתמש ב-PreemptLowerPriority.
    • value: העדיפות של ה-Pods שמשתמשים ב-PriorityClass. באשכולות GKE, שינוי הגודל האוטומטי של האשכול משתמש בערך ברירת מחדל של סף עדיפות להוצאה משימוש של ‎-10. אם העדיפות היא ‎-10 או יותר, אפשר להפעיל את יצירת הצמתים החדשים ב-Pods אם אין קיבולת זמינה. אם העדיפות נמוכה מ-10-,‏ Pods לא מפעילים את שינוי הגודל האוטומטי של האשכול, ולכן לא מוקצים צמתים חדשים. אם אין קיבולת, ה-Pods נשארים במצב Pending.

      במאמר בחירת עדיפות מוסבר איך בוחרים את הערכים המתאימים לעדיפות.

    • globalDefault: מציין אם GKE מקצה את PriorityClass לפודים שלא הוגדר להם PriorityClass באופן מפורש במפרט הפוד. ‫low-priority PriorityClass משתמש ב-false, ו-default PriorityClass משתמש ב-true.

  2. החלת המניפסט:

    kubectl apply -f priorityclasses.yaml
    

הקצאת קיבולת מחשוב נוספת

בקטעים הבאים מוצגת דוגמה לאופן הקצאת קיבולת לאירוע יחיד או באופן עקבי לאורך זמן.

שימוש בפריסה להקצאת קיבולת עקבית

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

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: capacity-res-deploy
    spec:
      replicas: 10
      selector:
        matchLabels:
          app: reservation
      template:
        metadata:
          labels:
            app: reservation
        spec:
          priorityClassName: low-priority
          terminationGracePeriodSeconds: 0
          containers:
          - name: ubuntu
            image: ubuntu
            command: ["sleep"]
            args: ["infinity"]
            resources:
              requests:
                cpu: 500m
                memory: 500Mi
    

    המניפסט הזה כולל את השדות הבאים:

    • spec.replicas: משנים את הערך הזה בהתאם לדרישות.
    • spec.resources.requests: משנים את בקשות ה-CPU והזיכרון בהתאם לדרישות. כדי להחליט על ערכי בקשות מתאימים, אפשר להיעזר בהנחיות שבקטע בחירת גודל הקיבולת.
    • spec.containers.command ו-spec.containers.args: הגדרת ה-Pods כך שיישארו פעילים עד ש-GKE יוציא אותם.
  2. החלת המניפסט:

    kubectl apply -f capacity-res-deployment.yaml
    
  3. קבלת הסטטוס של ה-Pod:

    kubectl get pods -l app=reservation
    

    מחכים עד שכל העותקים יהיו בסטטוס Running.

שימוש במשימה להקצאת קיבולת לאירוע יחיד

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

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: capacity-res-job
    spec:
      parallelism: 4
      backoffLimit: 0
      template:
        spec:
          priorityClassName: low-priority
          terminationGracePeriodSeconds: 0
          containers:
          - name: ubuntu-container
            image: ubuntu
            command: ["sleep"]
            args: ["36000"]
            resources:
              requests:
                cpu: "16"
          restartPolicy: Never
    

    המניפסט הזה כולל את השדות הבאים:

    • spec.parallelism: משנים את מספר העבודות שרוצים להריץ במקביל כדי לשריין קיבולת.
    • spec.backoffLimit: 0: מניעה של יצירה מחדש של משימות שהוצאו על ידי בקר המשימות.
    • template.spec.resources.requests: משנים את בקשות ה-CPU והזיכרון בהתאם לדרישות. כדי להחליט על ערכים מתאימים, אפשר להיעזר בהנחיות שבקטע שיקולים.
    • template.spec.containers.command ו-template.spec.containers.args: מציינים את משך הזמן בשניות שבו העבודות צריכות להישאר פעילות, כלומר משך הזמן שבו אתם צריכים את הקיבולת הנוספת.
  2. החלת המניפסט:

    kubectl apply -f capacity-res-job.yaml
    
  3. קבלת סטטוס המשימה:

    kubectl get jobs
    

    מחכים עד שכל המשימות יהיו בסטטוס Running.

בדיקת הקצאת הקיבולת והסרת הקיבולת

כדי לוודא שהקצאת הקיבולת פועלת כמצופה:

  1. בטרמינל, עוקבים אחרי הסטטוס של עומסי העבודה של הקצאת הקיבולת:

    1. כדי להריץ פריסות, מריצים את הפקודה הבאה:

      kubectl get pods --label=app=reservation -w
      
    2. כדי להריץ את הפקודה Jobs:

      kubectl get Jobs -w
      
  2. פותחים חלון טרמינל חדש ומבצעים את הפעולות הבאות:

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

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: helloweb
        labels:
          app: hello
      spec:
        replicas: 5
        selector:
          matchLabels:
            app: hello
            tier: web
        template:
          metadata:
            labels:
              app: hello
              tier: web
          spec:
            containers:
            - name: hello-app
              image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0
              ports:
              - containerPort: 8080
              resources:
                requests:
                  cpu: 400m
                  memory: 400Mi
      
    2. החלת המניפסט:

      kubectl apply -f test-deployment.yaml
      
  3. בחלון הטרמינל המקורי, אפשר לראות ש-GKE מסיים כמה עומסי עבודה של הקצאת קיבולת כדי לתזמן את העותקים החדשים, כמו בדוגמה הבאה:

    NAME                                         READY   STATUS    RESTARTS   AGE
    capacity-res-deploy-6bd9b54ffc-5p6wc         1/1     Running   0          7m25s
    capacity-res-deploy-6bd9b54ffc-9tjbt         1/1     Running   0          7m26s
    capacity-res-deploy-6bd9b54ffc-kvqr8         1/1     Running   0          2m32s
    capacity-res-deploy-6bd9b54ffc-n7zn4         1/1     Running   0          2m33s
    capacity-res-deploy-6bd9b54ffc-pgw2n         1/1     Running   0          2m32s
    capacity-res-deploy-6bd9b54ffc-t5t57         1/1     Running   0          2m32s
    capacity-res-deploy-6bd9b54ffc-v4f5f         1/1     Running   0          7m24s
    helloweb-85df88c986-zmk4f                    0/1     Pending   0          0s
    helloweb-85df88c986-lllbd                    0/1     Pending   0          0s
    helloweb-85df88c986-bw7x4                    0/1     Pending   0          0s
    helloweb-85df88c986-gh8q8                    0/1     Pending   0          0s
    helloweb-85df88c986-74jrl                    0/1     Pending   0          0s
    capacity-res-deploy-6bd9b54ffc-v6dtk   1/1     Terminating   0          2m47s
    capacity-res-deploy-6bd9b54ffc-kvqr8   1/1     Terminating   0          2m47s
    capacity-res-deploy-6bd9b54ffc-pgw2n   1/1     Terminating   0          2m47s
    capacity-res-deploy-6bd9b54ffc-n7zn4   1/1     Terminating   0          2m48s
    capacity-res-deploy-6bd9b54ffc-2f8kx   1/1     Terminating   0          2m48s
    ...
    helloweb-85df88c986-lllbd              0/1     Pending       0          1s
    helloweb-85df88c986-gh8q8              0/1     Pending       0          1s
    helloweb-85df88c986-74jrl              0/1     Pending       0          1s
    helloweb-85df88c986-zmk4f              0/1     Pending       0          1s
    helloweb-85df88c986-bw7x4              0/1     Pending       0          1s
    helloweb-85df88c986-gh8q8              0/1     ContainerCreating   0          1s
    helloweb-85df88c986-zmk4f              0/1     ContainerCreating   0          1s
    helloweb-85df88c986-bw7x4              0/1     ContainerCreating   0          1s
    helloweb-85df88c986-lllbd              0/1     ContainerCreating   0          1s
    helloweb-85df88c986-74jrl              0/1     ContainerCreating   0          1s
    helloweb-85df88c986-zmk4f              1/1     Running             0          4s
    helloweb-85df88c986-lllbd              1/1     Running             0          4s
    helloweb-85df88c986-74jrl              1/1     Running             0          5s
    helloweb-85df88c986-gh8q8              1/1     Running             0          5s
    helloweb-85df88c986-bw7x4              1/1     Running             0          5s
    

    הפלט הזה מראה שהפריסה החדשה נמשכה חמש שניות, מהשלב Pending (בהמתנה) ועד לשלב Running (פועלת).

שיקולים בהקצאת קיבולת

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

הקצאת קיבולת עקבית

  • צריך להעריך כמה עותקים משוכפלים של Pod של placeholder נדרשים ומה הגודל של הבקשות בכל עותק משוכפל. ההעתקים המשוכפלים בעדיפות נמוכה צריכים לבקש לפחות את אותה קיבולת כמו עומס העבודה הגדול ביותר בסביבת הייצור, כדי שעומסי העבודה האלה יוכלו להיכנס לקיבולת שהוקצתה לעומס העבודה בעדיפות נמוכה.
  • אם אתם מפעילים מספר גדול של עומסי עבודה של ייצור בקנה מידה, כדאי להגדיר את בקשות המשאבים של ה-Pods של ה-placeholder לערכים שמספקים מספיק קיבולת להפעלת כמה עומסי עבודה של ייצור במקום רק אחד.

הקצאת קיבולת לשימוש חד-פעמי

  • מגדירים את משך הזמן שבו יופיעו המשרות של המשתמשים הפיקטיביים, בהתאם לזמן שבו נדרש לכם נפח אחסון נוסף. לדוגמה, אם רוצים להגדיר את הקיבולת הנוספת ליום ההשקה של משחק למשך 24 שעות, מגדירים את משך הזמן ל-86,400 שניות. כך תוכלו לוודא שהקיבולת שהוקצתה לא תספיק ליותר זמן ממה שאתם צריכים.
  • מגדירים חלון זמן לתחזוקה לאותה תקופה שבה אתם מזמינים את הקיבולת. כך מונעים את ההוצאה של משימות בעדיפות נמוכה במהלך שדרוג של צומת. מומלץ להגדיר חלון זמן לתחזוקה גם כשצפוי ביקוש גבוה לעומס העבודה.
  • אם אתם מפעילים מספר גדול של עומסי עבודה של ייצור בהיקף נרחב, כדאי להגדיר את בקשות המשאבים של משימות ה-placeholder לערכים שמספקים מספיק קיבולת להפעלת כמה עומסי עבודה של ייצור במקום רק אחד.

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

בחירת עדיפות

אפשר להגדיר כמה PriorityClass באשכול כדי להשתמש בהם עם עומסי עבודה שיש להם דרישות שונות. לדוגמה, אפשר ליצור PriorityClass עם עדיפות של ‎-10 להקצאת קיבולת לשימוש חד-פעמי, ו-PriorityClass עם עדיפות של ‎-9 להקצאת קיבולת עקבית. לאחר מכן תוכלו להקצות קיבולת עקבית באמצעות PriorityClass עם עדיפות של ‎-9, וכשאתם רוצים קיבולת גדולה יותר לאירוע מיוחד, תוכלו לפרוס משימות חדשות שמשתמשות ב-PriorityClass עם עדיפות של ‎-10. מערכת GKE מפנה קודם את עומסי העבודה עם העדיפות הכי נמוכה.

אפשר גם להשתמש ב-PriorityClass אחרים כדי להריץ עומסי עבודה לא ייצוריים בעדיפות נמוכה שמבצעים משימות בפועל, כמו עומסי עבודה באצווה שהם עמידים בכשלים, בעדיפות נמוכה יותר מעומסי העבודה הייצוריים אבל גבוהה יותר מ-Pods של placeholder. לדוגמה, ‎-5.

בחירת גודל הקיבולת

מגדירים את מספר הרפליקות ואת בקשות המשאבים של עומס העבודה של הפלייסהולדר כך שיהיו גדולים או שווים לקיבולת שעומסי העבודה בסביבת Production עשויים להזדקק לה כשמגדילים את קנה המידה.

הקיבולת הכוללת שהוקצתה מבוססת על מספר ה-Pods של placeholder שפרסתם ועל בקשות המשאבים של כל רפליקה. אם ההרחבה שלכם דורשת יותר קיבולת ממה שהוקצה ב-GKE לתאי ה-Pod של placeholder, חלק מעומסי העבודה שלכם בסביבת הייצור יישארו במצב Pending עד ש-GKE יוכל להקצות יותר קיבולת.

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