שחזור מתמונת מצב של Pod

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

במאמר הזה מוסבר איך להפעיל ולהגדיר תמונות מצב של GKE Pod לעומסי העבודה.

מידע נוסף על אופן הפעולה של תמונות מצב של Pod זמין במאמר מידע על תמונות מצב של Pod.

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

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

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

הפעלת תמונות מצב של Pod

כדי להפעיל את התכונה 'תמונת מצב של Pod', צריך ליצור או לעדכן אשכול עם התכונה הזו. באשכולות Standard, צריך גם ליצור או לעדכן מאגר צמתים כדי להריץ ב-GKE Sandbox. ‫GKE Sandbox נתמך כברירת מחדל באשכולות Autopilot.

כדי להפעיל צילומי מצב של Pod באשכול, צריך לבצע את אחד מההליכים הבאים, בהתאם למצב הפעולה של GKE שבו רוצים להשתמש:

טייס אוטומטי

  • כדי להפעיל צילומי מצב של Pod באשכול חדש, מריצים את הפקודה הבאה:

      gcloud container clusters create-auto CLUSTER_NAME \
          --enable-pod-snapshots \
          --location=CONTROL_PLANE_LOCATION \
          --cluster-version=CLUSTER_VERSION
    

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

    • CLUSTER_NAME: השם של האשכול.
    • CONTROL_PLANE_LOCATION: המיקום של מישור הבקרה של האשכול.
    • CLUSTER_VERSION: הגרסה של האשכול החדש, שצריכה להיות 1.35.3-gke.1234000 ואילך.
  • כדי להפעיל צילומי מצב של Pod באשכול קיים, מבצעים את השלבים הבאים:

    1. משדרגים את האשכול לגרסה 1.35.3-gke.1234000 ואילך:

        gcloud container clusters upgrade CLUSTER_NAME \
            --cluster-version=CLUSTER_VERSION \
            --location=CONTROL_PLANE_LOCATION
      

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

      • CLUSTER_NAME: השם של האשכול.
      • CONTROL_PLANE_LOCATION: המיקום של מישור הבקרה של האשכול.
      • CLUSTER_VERSION: הגרסה של האשכול החדש, שצריכה להיות 1.35.3-gke.1234000 ואילך.
    2. מפעילים תמונות מצב של Pod באשכול:

        gcloud container clusters update CLUSTER_NAME \
            --enable-pod-snapshots \
            --location=CONTROL_PLANE_LOCATION
      

תמונות מצב של Pod לא תומכות בסוגי מכונות E2. ב-Autopilot,‏ GKE עשוי להגדיר כברירת מחדל צומתי E2. כדי לוודא שעומסי העבודה שלכם פועלים על חומרה תואמת, מומלץ להשתמש בComputeClass מותאם אישית כדי לתת עדיפות לסדרות מכונות תואמות.

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

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

      apiVersion: cloud.google.com/v1
      kind: ComputeClass
      metadata:
        name: non-e2-class
      spec:
        priorities:
        - machineFamily: n2
        - machineFamily: c3
        activeMigration:
          optimizeRulePriority: false
        whenUnsatisfiable: DoNotScaleUp
    
  2. החלת המניפסט:

      kubectl apply -f non-e2-class.yaml
    
  3. במפרט של ה-Pod, מפנים אל ComputeClass באמצעות cloud.google.com/compute-class node selector:

      spec:
        nodeSelector:
          cloud.google.com/compute-class: non-e2-class
        ...
    

רגילה

  • כדי להפעיל צילומי מצב של Pod באשכול חדש, מריצים את הפקודה הבאה:

      gcloud container clusters create CLUSTER_NAME \
          --enable-pod-snapshots \
          --cluster-version=CLUSTER_VERSION \
          --workload-pool=PROJECT_ID.s3ns.svc.id.goog \
          --workload-metadata=GKE_METADATA \
          --location=CONTROL_PLANE_LOCATION
    

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

    • CLUSTER_NAME: השם של האשכול.
    • CLUSTER_VERSION: הגרסה של האשכול החדש, שצריכה להיות 1.35.3-gke.1234000 ואילך.
    • PROJECT_ID: מזהה הפרויקט.
    • CONTROL_PLANE_LOCATION: המיקום של מישור הבקרה של האשכול.
  • כדי להפעיל צילומי מצב של Pod באשכול קיים, מבצעים את השלבים הבאים:

    1. משדרגים את האשכול לגרסה 1.35.3-gke.1234000 ואילך:

        gcloud container clusters upgrade CLUSTER_NAME \
            --node-pool=NODEPOOL_NAME \
            --cluster-version=CLUSTER_VERSION \
            --location=CONTROL_PLANE_LOCATION
      

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

      • CLUSTER_NAME: השם של האשכול.
      • NODEPOOL_VERSION: השם של מאגר הצמתים.
      • CLUSTER_VERSION: הגרסה לעדכון האשכול החדש, שחייבת להיות 1.35.3-gke.1234000 ואילך.
      • CONTROL_PLANE_LOCATION: המיקום של מישור הבקרה של האשכול.
    2. מפעילים תמונות מצב של Pod באשכול:

      gcloud beta container clusters update CLUSTER_NAME \
         --enable-pod-snapshots \
         --location=CONTROL_PLANE_LOCATION
      

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

      • PROJECT_ID במזהה הפרויקט.
      • CONTROL_PLANE_LOCATION: המיקום של מישור הבקרה של האשכול.

כדי להריץ Pods ב-GKE Sandbox באשכול Standard, צריך ליצור או לעדכן מאגר צמתים עם gVisor מופעל. כדי לעדכן מאגר צמתים, משתמשים בדגל --sandbox type=gvisor. כדי ליצור מאגר צמתים עם gVisor מופעל, מריצים את הפקודה הבאה:

gcloud container node-pools create NODE_POOL_NAME \
  --cluster=CLUSTER_NAME \
  --node-version=NODE_VERSION \
  --machine-type=MACHINE_TYPE \
  --location=CONTROL_PLANE_LOCATION \
  --image-type=cos_containerd \
  --sandbox type=gvisor

מחליפים את המשתנים הבאים:

  • NODE_POOL_NAME: השם של מאגר הצמתים החדש.
  • NODE_VERSION: הגרסה שבה ייעשה שימוש במאגר הצמתים.
  • MACHINE_TYPE: סוג המכונה שבה רוצים להשתמש לצמתים.
  • CONTROL_PLANE_LOCATION: המיקום של מישור הבקרה של האשכול.

מידע נוסף על השימוש ב-gVisor זמין במאמר בידוד עומסי עבודה באמצעות GKE Sandbox.

תמונות מצב של חנויות

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

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

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

יצירת קטגוריה של Cloud Storage

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

  1. יצירת קטגוריה של Cloud Storage. הפקודה הבאה יוצרת קטגוריה עם ההגדרות הנדרשות:

    gcloud storage buckets create "gs://BUCKET_NAME" \
       --uniform-bucket-level-access \
       --enable-hierarchical-namespace \
       --soft-delete-duration=0d \
       --location="LOCATION"
    

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

    • BUCKET_NAME: השם של הקטגוריה.
    • LOCATION: המיקום של הקטגוריה.

    רשימת האפשרויות המלאה ליצירת קטגוריות מופיעה במאמר אפשרויות של buckets create.

מתן הרשאה לעומסי עבודה לגשת לקטגוריה של Cloud Storage

כברירת מחדל, ל-GKE אין הרשאות גישה ל-Cloud Storage. כדי לקרוא ולכתוב קבצים של תמונות מצב, צריך להעניק הרשאות IAM לחשבון שירות (KSA) של Kubernetes שמשמש את פודים של עומסי העבודה. במקום להעניק הרשאות ספציפיות, אפשר להעניק אסימונים לטווח קצר.

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

    gcloud container clusters get-credentials "CLUSTER_NAME"
    
  2. לכל Pod, מבצעים את השלבים הבאים:

    1. יוצרים KSA לכל פוד:

      kubectl create serviceaccount "KSA_NAME" \
          --namespace "NAMESPACE"
      

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

      • KSA_NAME: השם של ה-KSA.
      • NAMESPACE: מרחב השמות של ה-Pods.
    2. נותנים ל-KSA הרשאה לגשת לקטגוריה:

      gcloud storage buckets add-iam-policy-binding "gs://BUCKET_NAME" \
          --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.s3ns.svc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME" \
          --role="roles/storage.bucketViewer"
      
      gcloud storage buckets add-iam-policy-binding "gs://BUCKET_NAME" \
          --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.s3ns.svc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME" \
          --role="roles/storage.objectUser"
      

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

      • PROJECT_NUMBER: מספר הפרויקט.
      • PROJECT_ID: מזהה הפרויקט.

הפעלת ריבוי דיירים באמצעות אסימונים לטווח קצר

במקום להעניק הרשאות לכל חשבון KSA בנפרד, אפשר להפעיל ריבוי דיירים באמצעות אסימונים לטווח קצר עם היקף מוגבל. הגישה הזו עוזרת להימנע מעיכובים בהפצה שקשורים לקשירת הרשאות ידנית ב-IAM. במקום להעניק הרשאות לכל KSA, מעניקים פעם אחת את התפקיד roles/storage.admin בקטגוריית האחסון של התמונת מצב לחשבון השירות של צומת GKE. לאחר מכן, חשבון השירות של הצומת יוצר אסימונים לטווח קצר לפי דרישה עבור נתיבים ספציפיים.

כדי להפעיל טוקנים עם תמונות מצב של Pod, צריך להשתמש ב-GKE בגרסה 1.35.3-gke.1234000 ואילך.

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

  1. כדי לתת לחשבון השירות של הצומת הרשאה לגשת לקטגוריה, מריצים את הפקודה הבאה:

    gcloud storage buckets add-iam-policy-binding "gs://BUCKET_NAME" \
        --member="serviceAccount:service-PROJECT_NUMBER@gcp-sa-gkenode.s3ns-system.iam.gserviceaccount.com" \
        --role="roles/storage.admin"
    
  2. כשמגדירים אחסון לתמונות מצב, מגדירים את הערך של השדה tokenSource ל-federatedP4SA.

הענקת הרשאת בקרה לגישה לקטגוריה של Cloud Storage

כדי לאפשר ל-Pod Snapshot Controller למחוק תמונות מצב בתוך קטגוריה של Cloud Storage, צריך להעניק לסוכן השירות של GKE הרשאה של משתמש אובייקט אחסון.

  1. הקצאת התפקיד roles/storage.objectUser:

    gcloud projects add-iam-policy-binding "PROJECT_ID" \
      --member="serviceAccount:service-PROJECT_NUMBER@container-engine-robot.s3ns-system.iam.gserviceaccount.com" \
      --role="roles/storage.objectUser" \
      --condition="expression=resource.name.startsWith(\"projects/_/buckets/BUCKET_NAME\"),title=restrict_to_bucket,description=Restricts access to one bucket only"
    

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

    • PROJECT_NUMBER: מספר הפרויקט.
    • PROJECT_ID: מזהה הפרויקט.
    • BUCKET_NAME: השם של הקטגוריה.

(אופציונלי) יצירת תיקיות מנוהלות לקטגוריה של Cloud Storage

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

  1. יוצרים תפקיד IAM בהתאמה אישית שמכיל רק את ההרשאות הנדרשות לצילומי מצב של Pod:

    gcloud iam roles create podSnapshotGcsReadWriter \
        --project="PROJECT_ID" \
        --permissions="storage.objects.get,storage.objects.create,storage.objects.delete,storage.folders.create"
    
  2. נותנים את התפקיד roles/storage.bucketViewer לכל החשבונות של שירותי ה-KSA במרחב השמות של היעד. התפקיד הזה מאפשר ל-KSA לקרוא את המטא-נתונים של הקטגוריה, אבל לא נותן הרשאות קריאה או כתיבה לאובייקטים בקטגוריה.

    gcloud storage buckets add-iam-policy-binding "gs://BUCKET_NAME" \
        --member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.s3ns.svc.id.goog/namespace/NAMESPACE" \
        --role="roles/storage.bucketViewer"
    

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

    • PROJECT_NUMBER: מספר הפרויקט.
    • PROJECT_ID: מזהה הפרויקט.
  3. לכל KSA שצריך לאחסן תמונות מצב של Pod, מבצעים את השלבים הבאים:

    1. יוצרים תיקייה מנוהלת עבור ערב הסעודית:

      gcloud storage managed-folders create "gs://BUCKET_NAME/FOLDER_PATH/"
      

      מחליפים את FOLDER_PATH בנתיב לתיקייה המנוהלת, לדוגמה my-app-snapshots.

    2. הקצאת התפקיד המותאם אישית podSnapshotGcsReadWriter לחשבון השירות המנוהל בתיקייה המנוהלת:

      gcloud storage managed-folders add-iam-policy-binding "gs://BUCKET_NAME/FOLDER_PATH/" \
          --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.s3ns.svc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME" \
          --role="projects/PROJECT_ID/roles/podSnapshotGcsReadWriter"
      

      מחליפים את KSA_NAME בשם של KSA.

הגדרת אחסון לתמונות מצב

כדי לציין איפה לאחסן קבצים של snapshot, יוצרים משאב PodSnapshotStorageConfig.

  1. בדוגמה הבאה מוגדר GKE לאחסון קובצי snapshot של Pod בנתיב FOLDER_PATH/ בתוך קטגוריה של Cloud Storage‏ BUCKET_NAME. שומרים את קובץ המניפסט הבא בשם example-pod-snapshot-storage-config:

    apiVersion: podsnapshot.gke.io/v1
    kind: PodSnapshotStorageConfig
    metadata:
      name: example-pod-snapshot-storage-config
    spec:
      snapshotStorageConfig:
        gcs:
          bucket: "BUCKET_NAME"
          path: "FOLDER_PATH"
          tokenSource: "TOKEN_SOURCE"
    

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

    • BUCKET_NAME: שם הקטגוריה של Cloud Storage.
    • FOLDER_PATH: הנתיב לתיקייה המנוהלת ב-Cloud Storage.
    • TOKEN_SOURCE: ספק הזהויות לגישה. משתמשים ב-podKSA (ברירת מחדל) או ב-federatedP4SA לריבוי דיירים.
  2. החלת המניפסט:

    kubectl apply -f example-pod-snapshot-storage-config.yaml
    

יצירת מדיניות של תמונות מצב

כדי להפעיל תמונות מצב של Pod, יוצרים משאב PodSnapshotPolicy עם סלקטור שתואם לתוויות של ה-Pod.

  1. בדוגמה הבאה נוצרת מדיניות שחלה על Pods עם התווית app: my-app ומשתמשת בהגדרת האחסון example-pod-snapshot-storage-config. שומרים את קובץ המניפסט הבא בשם example-pod-snapshot-policy.yaml:

    apiVersion: podsnapshot.gke.io/v1
    kind: PodSnapshotPolicy
    metadata:
      name: example-pod-snapshot-policy
      namespace: NAMESPACE
    spec:
      storageConfigName: example-pod-snapshot-storage-config
      selector:
        matchLabels:
          app: my-app
      triggerConfig:
        type: TRIGGER_TYPE
        postCheckpoint: resume
    

    מחליפים את TRIGGER_TYPE בסוג הטריגר. הערכים הנתמכים הם workload להפעלות מבוססות-עומס עבודה או manual לצילומי מצב לפי דרישה.

    רשימה מלאה של כל השדות שאפשר להגדיר מופיעה במסמכי התיעוד של PodSnapshotPolicy CustomResourceDefinition (CRD).

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

    kubectl apply -f example-pod-snapshot-policy.yaml --namespace NAMESPACE
    

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

אפשר להגדיר מדיניות נוספת ב-PodSnapshotPolicy, למשל:

  • ניקוי אוטומטי: כדי לנקות באופן אוטומטי משאבים ישנים של תמונות מצב של Pod, מגדירים מדיניות שמירה באמצעות השדה spec.retentionConfig. אפשר לציין משך זמן באמצעות השדה lastAccessTimeout (לדוגמה, 7d), שאחריו התמונה תמחק.

  • ארגון תמונות המצב: אתם יכולים לקבץ תמונות מצב באופן הגיוני כדי להבדיל בין תמונות מצב שצולמו בסביבות דומות, אבל בהקשרים שונים. לדוגמה, בתרחיש של ריבוי דיירים שבו יכול להיות שפוד הבסיס זהה לכל המשתמשים, אפשר לבודד את התמונות לפי משתמש או קבוצה. כדי לבודד תמונות מצב, מציינים תוויות קיבוץ במדיניות באמצעות השדה snapshotGroupingRules.

בדוגמה הבאה מוצגות ההגדרות של שמירת הנתונים ושל הקיבוץ ב-PodSnapshotPolicy. אפשר להגדיר את ההגדרות האלה בנפרד:

# ... other fields omitted
spec:
  retentionConfig:
    lastAccessTimeout: 7d
  snapshotGroupingRules:
    groupByLabelValue:
      labels: ["tenant", "environment"]
      groupRetentionPolicy:
        maxSnapshotCountPerGroup: 5

רשימה מלאה של כל השדות שאפשר להגדיר מופיעה במסמכי ה-CRD של PodSnapshotPolicy.

אופטימיזציה של גודל תמונת המצב

כשמפעילים צילום של תמונת מצב של Pod, ‏ gVisor מצלם את כל המצב של כל הקונטיינרים, כולל:

  • מצב האפליקציה, כמו זיכרון ורשומות
  • שינויים במערכת קבצים הבסיסית וב-tmpfs (כולל נפחי emptyDir)
  • מצב הליבה, כמו מתארים של קבצים פתוחים, שרשורים ושקעים

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

אופטימיזציה של גודל התמונה חשובה במיוחד לעומסי עבודה כמו מודלים גדולים של שפה (LLM). שרתי LLM מורידים לעיתים קרובות משקלים של מודלים לאחסון מקומי (rootfs או tmpfs) לפני שהם נטענים ל-GPU. כשמצלמים תמונת מצב, נשמרים גם מצב ה-GPU וגם קובצי המשקלים של המודל. בתרחיש הזה, אם המודל הוא 100 GB, התמונה שנוצרת היא בערך 200 GB (100 GB של קובצי מודל, ועוד 100 GB שמייצגים את מצב ה-GPU). אחרי שמשקלי המודל נטענים ל-GPU, לרוב לא צריך את הקבצים במערכת הקבצים כדי שהאפליקציה תפעל. אם תמחקו את קובצי המודל האלה לפני שתפעילו את הצילום, תוכלו להקטין את גודל התמונה בחצי ולשחזר את האפליקציה עם חביון נמוך משמעותית.

הפעלת תמונת מצב

אפשר להפעיל תמונת מצב מתוך עומס עבודה כשהאפליקציה מוכנה, או להפעיל באופן ידני תמונת מצב לפי דרישה עבור Pod ספציפי.

הפעלת צילום תמונת מצב מעומס עבודה

כדי להפעיל צילום תמונת מצב מתוך קוד האפליקציה, צריך להגדיר את האפליקציה כך שתשלח אות כשהיא מוכנה לצילום תמונת מצב. כדי לסמן שהגיבוי מוכן, כותבים 1 לקובץ /proc/gvisor/checkpoint, לדוגמה echo 1 > /proc/gvisor/checkpoint. פעולת הכתיבה מתחילה את תהליך יצירת התמונה באופן אסינכרוני וחוזרת באופן מיידי. קריאה מאותו מתאר קובץ תחסום את תהליך הקריאה עד שהתמונה והשחזור יושלמו ועומס העבודה יהיה מוכן להמשך.

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

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

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-app
      namespace: NAMESPACE
      labels:
        app: my-app
    spec:
      serviceAccountName: KSA_NAME
      runtimeClassName: gvisor
      containers:
      - name: my-container
        image: python:3.10-slim
        command: ["python3", "-c"]
        args:
          - |
            import time
            def trigger_snapshot():
              try:
                with open("/proc/gvisor/checkpoint", "r+") as f:
                  f.write("1")
                  res = f.read().rstrip()
                  print(f"GKE Pod Snapshot: {res}")
              except FileNotFoundError:
                print("GKE Pod Snapshot file does not exist -- Pod Snapshots is disabled")
                return
              except OSError as e:
                return e
            i = 0
            while True:
              print(f"Count: {i}", flush=True)
              if (i == 20): #simulate the application being ready to snapshot at 20th count
                trigger_snapshot()
              i += 1
              time.sleep(1)
        resources:
          limits:
            cpu: "500m"
            memory: "512Mi"
          requests:
            cpu: "250m"
            memory: "256Mi"
    
  2. מפעילים את האפליקציה:

    kubectl apply -f my-app.yaml
    

הפעלת צילום תמונת מצב באופן ידני

כדי להפעיל ידנית צילום מצב לפי דרישה של Pod ספציפי, צריך ליצור משאב PodSnapshotManualTrigger.

  1. בדוגמה הבאה מופעלת תמונת מצב עבור Pod בשם my-pod. שומרים את קובץ המניפסט הבא בשם example-manual-trigger.yaml:

    apiVersion: podsnapshot.gke.io/v1
    kind: PodSnapshotManualTrigger
    metadata:
      name: example-manual-trigger
      namespace: NAMESPACE
    spec:
      targetPod: my-pod
    
  2. החלת המניפסט:

    kubectl apply -f example-manual-trigger.yaml --namespace NAMESPACE
    

כדי לוודא שהפעלת ה-snapshot הצליחה, בודקים את השדה status של המשאב PodSnapshotManualTrigger:

kubectl get podsnapshotmanualtriggers.podsnapshot.gke.io example-manual-trigger -n NAMESPACE -o yaml

השדה status מציין אם הפעלת הצילום של התמונה המייצגת הצליחה או נכשלה.

אימות תמונות מצב

כדי לוודא שנוצר snapshot, בודקים את היסטוריית האירועים של אירועי GKEPodSnapshotting:

kubectl get events -o \
custom-columns=NAME:involvedObject.name,CREATIONTIME:.metadata.creationTimestamp,REASON:.reason,MESSAGE:.message \
--namespace NAMESPACE \
--field-selector involvedObject.name=POD_NAME,reason=GKEPodSnapshotting

מחליפים את POD_NAME בשם ה-Pod, לדוגמה my-app או my-pod.

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

NAME                                    CREATIONTIME           REASON               MESSAGE
default/5b449f9c7c-bd7pc                2025-11-05T16:25:11Z   GKEPodSnapshotting   Successfully checkpointed the pod to PodSnapshot

ניהול תמונות מצב

כשיוצרים תמונת מצב של Pod, נוצר משאב PodSnapshot CRD כדי לאחסן את מצב ה-Pod באותו זמן. השדה status במשאב הזה מציין אם פעולת ה-snapshot הצליחה ואם ה-snapshot זמין לשחזורים.

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

kubectl get podsnapshots.podsnapshot.gke.io --namespace NAMESPACE

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

NAME                                   STATUS                  POLICY           AGE
de334898-1e7a-4cdb-9f2e-7cc2181c29e4   AllSnapshotsAvailable   example-policy   47h

שחזור עומס עבודה מתמונת מצב

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

בשלבים הבאים מוסבר איך לשחזר Pod מתמונת מצב תואמת על ידי מחיקה ופריסה מחדש של ה-Pod:

  1. מוחקים את ה-Pod:

    kubectl delete -f POD_NAME.yaml
    

    מחליפים את POD_NAME בשם של ה-Pod, לדוגמה my-app.

  2. החלה מחדש של רצף המודעות:

    kubectl apply -f POD_NAME.yaml
    
  3. כדי לוודא שהשחזור של תמונת המצב בוצע:

    kubectl logs my-app --namespace NAMESPACE
    

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

שחזור מתמונת מצב ספציפית

כברירת מחדל, GKE משחזר עומסי עבודה מהמשאב PodSnapshot העדכני ביותר שתואם ל-Pod. כשמבצעים צילום מצב, GKE יוצר באופן אוטומטי שם ייחודי (UUID) למשאב PodSnapshot, שאפשר לראות אותו על ידי הפעלת הפקודה kubectl get podsnapshots.gke.io --namespace NAMESPACE.

כדי לשחזר עומס עבודה ממקור PodSnapshot ישן או ספציפי, מוסיפים את ההערה podsnapshot.gke.io/ps-name למפרט של עומס העבודה של ה-Pod, ומציינים את השם של מקור ה-PodSnapshot שבו רוצים להשתמש לשחזור עומס העבודה:

apiVersion: v1
kind: Pod
metadata:
  name: my-app
  namespace: NAMESPACE
  labels:
    app: my-app
  annotations:
    podsnapshot.gke.io/ps-name: "POD_SNAPSHOT_NAME"
spec:
  serviceAccountName: KSA_NAME
  runtimeClassName: gvisor
  containers:
  ...

מחליפים את POD_SNAPSHOT_NAME בשם של תמונת המצב שרוצים לשחזר ממנה. כדי לקבל את שמות התמונות מריצים את הפקודה kubectl get podsnapshots.gke.io --namespace NAMESPACE.

כדי ש-GKE ישתמש בתמונת המצב שצוינה לשחזור, תנאי הסטטוס של משאב PodSnapshot צריך להיות Ready ולהופיע באותו מרחב שמות כמו ה-Pod. אם ה-PodSnapshot לא Ready או לא קיים באותו מרחב שמות כמו ה-Pod, עומס העבודה מבצע הפעלה במצב התחלתי (cold start) במקום לשחזר מגיבוי.

השבתת תמונות המצב

הסרה של PodSnapshotPolicy CRD מונעת יצירה של תמונת מצב של Pods ושחזור שלהם. מחיקת המשאבים לא משפיעה על ה-Pods הפועלים. עם זאת, אם תמחקו את המדיניות בזמן שקובץ ה-Pod נשמר או משוחזר, יכול להיות שהקובץ יעבור למצב של כשל.

כדי להשבית את יצירת התמונות והשחזור של Pods חדשים הכפופים למדיניות, מוחקים את PodSnapshotPolicy על ידי הפעלת הפקודה הבאה:

kubectl delete podsnapshotpolicies.podsnapshot.gke.io SNAPSHOT_POLICY --namespace=NAMESPACE

מחליפים את SNAPSHOT_POLICY בשם של PodSnapshotPolicy שרוצים למחוק, לדוגמה example-pod-snapshot-policy.

אפשר גם למחוק משאב PodSnapshot ספציפי כדי שה-Pods לא ישוחזרו יותר מהתמונה הספציפית הזו. מחיקה של המשאב PodSnapshot מסירה גם את הקבצים שמאוחסנים ב-Cloud Storage.

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

kubectl delete podsnapshots.podsnapshot.gke.io POD_SNAPSHOT_NAME --namespace=NAMESPACE

מחליפים את POD_SNAPSHOT_NAME בשם של התמונה של הדיסק שרוצים למחוק, למשל example-podsnapshot.

פתרון בעיות

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

סיכוני מוטציה אחרי נקודת ביקורת עם PVC

סיכון משמעותי מתרחש במהלך תהליך העבודה של 'נקודת ביקורת והמשך' אם ה-Pod שלכם משתמש ב-Persistent Volume Claim (PVC). אם מגדירים עומס עבודה להמשך פעולה מיד אחרי נקודת ביקורת (באמצעות השדה postCheckpoint: resume), האפליקציה נשארת פעילה ויכולה לשנות את ה-PVC אחרי נקודת הביקורת.

  • בעיה בכיבוי מבוקר: אחרי מחזור של יצירת נקודת ביקורת והמשך, כשמוחקים Pod, ‏ Kubernetes מתחיל רצף של כיבוי מבוקר על ידי שליחת אות SIGTERM לתהליך הראשי בקונטיינר. בהרבה אפליקציות מיושמת לוגיקה של כיבוי חלק, שבמהלכו הן עשויות להפעיל שגרות ניקוי, למחוק או לעדכן קבצים זמניים ב-PVC.
  • שחזור נכשל: אם השינויים האלה מתרחשים ב-PVC אחרי שנוצר צילום המצב של ה-Pod, תהליך השחזור יצפה למצב ה-PVC כפי שהיה ברגע המדויק של נקודת הבדיקה, מה שיוביל לשגיאות שחזור פוטנציאליות או לחוסר עקביות בנתונים.
  • המלצה לצמצום הסיכון: אם השימוש ב-PVC נחוץ לעומס העבודה, אל תפעילו מחדש את עומס העבודה אחרי נקודת ביקורת. משתמשים בהגדרה postCheckpoint: stop ב-PodSnapshotPolicy. ההגדרה הזו עוזרת לוודא שלתהליך לא תהיה אפשרות לבצע כתיבות משניות או שינויים במצב אחרי ששלב יצירת נקודת הבדיקה מסתיים.

טעינה של ConfigMap והסתרת ספריות

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

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

בדוגמה הבאה, שינויים בספרייה /etc/my-app/ לא נכללים בתמונת המצב כי כל הספרייה היא נקודת הרכבה חיצונית:

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config
data:
  config.json: |
    {
      "mode": "local"
    }
---
apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  runtimeClassName: gvisor
  containers:
    - name: my-app-container
      image: my-app-image
      volumeMounts:
        - mountPath: /etc/my-app
          name: config-volume
  volumes:
    - name: config-volume
      configMap:
        name: my-config

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

בדוגמה הבאה מוצגת ההגדרה של volumeMounts באמצעות subPath:

      volumeMounts:
        - mountPath: /etc/my-app/config.json
          name: config-volume
          subPath: config.json

נפחים משתמעים אנונימיים

קובצי אימג' מסוימים של קונטיינרים מגדירים נפחים במטא-נתונים שלהם (באמצעות ההוראה VOLUME בקובץ Dockerfile). גם אם מפרט ה-Pod לא מגדיר נפח אחסון, Kubernetes יוצר באופן אוטומטי נפח אחסון אנונימי לכל נתיב שמוגדר כנפח אחסון בתמונת הבסיס. לדוגמה, התמונה alpine/git מגדירה את /git כנפח משתמע.

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

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