טעינת קטגוריות של Cloud Storage כנפחי אחסון זמניים של CSI

במדריך הזה מוסבר איך להשתמש בנפחי אחסון זמניים של CSI שמגובים על ידי קטגוריות Cloud Storage כדי לנהל באופן אוטומטי משאבי אחסון עבור Pods או Jobs של Kubernetes ב-Google Kubernetes Engine‏ (GKE). נפחי אחסון זמניים של CSI קשורים למחזור החיים של ה-Pod או ה-Job, ולא צריך לטפל ידנית באובייקטים של PersistentVolume ו-PersistentVolumeClaim.

המדריך הזה מיועד לאדמינים ולמפעילים של פלטפורמות שרוצים לפשט את ניהול האחסון של אפליקציות GKE.

לפני שקוראים את הדף הזה, חשוב לוודא שמכירים את הכרכים הזמניים של CSI, את ה-Pods וה-Jobs של Kubernetes ואת הקטגוריות של Cloud Storage.

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

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

חשוב לוודא שהשלמתם את הדרישות המוקדמות הבאות:

איך פועל אחסון זמני של CSI לקטגוריות של Cloud Storage

נפחי אחסון זמניים של CSI מפשטים את ניהול האחסון של האפליקציות ב-GKE. מגדירים נפחים זמניים של CSI ישירות במפרט של ה-Pod או של ה-Job. שימוש באמצעי אחסון זמניים של CSI מבטל את הצורך באובייקטים נפרדים של PersistentVolume ו-PersistentVolumeClaim.

שימוש בנפח זמני של CSI כולל את הפעולות הבאות:

  1. הגדרת אחסון: מציינים את האחסון בקובץ ה-YAML של ה-Pod או של ה-Job, כולל מנהל התקן ה-CSI שבו רוצים להשתמש וכל הפרמטרים הנדרשים. במקרה של Cloud Storage FUSE CSI driver, מציינים את שם הקטגוריה ופרטים רלוונטיים אחרים.

    אם רוצים, אפשר לשפר את הביצועים של מנהל ההתקן של CSI באמצעות התכונה file caching. שמירת קבצים במטמון יכולה לשפר את ביצועי האפליקציה של GKE על ידי שמירת קבצים ב-Cloud Storage שניגשים אליהם לעיתים קרובות במטמון בדיסק מהיר יותר.

    בנוסף, אפשר להשתמש בתכונה הורדה מקבילה כדי להאיץ קריאה של קבצים גדולים מ-Cloud Storage להורדות מרובות-הליכים. אתם יכולים להשתמש בתכונה הזו כדי לשפר את זמני הטעינה של המודל, במיוחד כשמדובר בקריאות בגודל של יותר מ-‎1 GB.

  2. הפעלת מנהל התקן: כשיוצרים את ה-Pod או את ה-Job, ‏ GKE מזהה את הבקשה לנפח זמני ומפעיל את מנהל התקן ה-CSI של Cloud Storage FUSE.

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

  4. ניהול מחזור חיים: נפח האחסון הזמני קיים למשך מחזור החיים של ה-Pod או ה-Job. כשמחיקת ה-Pod מסתיימת או כשפעולת ה-Job מסתיימת, מנהל ההתקן של CSI מטפל אוטומטית בניקוי ובביטול הטעינה של אמצעי האחסון.

צירוף נפח אחסון זמני של CSI

פועלים לפי ההוראות האלה, בהתאם לרצון לצרף את נפח האחסון הזמני של CSI ל-Pod או ל-Job.

Pod

כדי לצרף את עוצמת הקול הזמנית של CSI ב-Pod, פועלים לפי השלבים הבאים:

  1. יוצרים מניפסט YAML של Pod עם המפרט הבא:

    apiVersion: v1
    kind: Pod
    metadata:
      name: gcs-fuse-csi-example-ephemeral 
      namespace: NAMESPACE
      annotations:
        gke-gcsfuse/volumes: "true" 
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - image: busybox
        name: busybox
        command: ["sleep"]
        args: ["infinity"] 
        volumeMounts:
        - name: gcs-fuse-csi-ephemeral
          mountPath: /data
          readOnly: true
      serviceAccountName: KSA_NAME
      volumes:
      - name: gcs-fuse-csi-ephemeral
        csi:
          driver: gcsfuse.csi.storage.gke.io
          readOnly: true
          volumeAttributes:
            bucketName: BUCKET_NAME
            mountOptions: "implicit-dirs" 
    

    מחליפים את הערכים הבאים:

    • NAMESPACE: מרחב השמות של Kubernetes שבו רוצים לפרוס את ה-Pod.
    • KSA_NAME: השם של חשבון השירות ב-Kubernetes שציינתם כשהגדרתם גישה לקטגוריות של Cloud Storage.
    • BUCKET_NAME: שם הקטגוריה ב-Cloud Storage שציינתם כשקבעתם את הגישה לקטגוריות ב-Cloud Storage. אפשר לציין קו תחתון (_) כדי לטעון את כל הקטגוריות שחשבון השירות של Kubernetes יכול לגשת אליהן. מידע נוסף זמין במאמר Dynamic mounting במאמרי העזרה של Cloud Storage FUSE.

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

    • metadata.annotations: ההערה gke-gcsfuse/volumes: "true" נדרשת. במאמר הגדרת קונטיינר sidecar מוסבר איך להוסיף הערות אופציונליות.
    • spec.volumes[n].csi.driver: משתמשים ב-gcsfuse.csi.storage.gke.io כשם של מנהל התקן CSI.

    אפשר גם לשנות את המשתנים האלה:

    • spec.terminationGracePeriodSeconds: כברירת מחדל, הערך הזה מוגדר ל-30. אם אתם צריכים לכתוב קבצים גדולים לקטגוריה של Cloud Storage, כדאי להגדיל את הערך הזה כדי לוודא של-Cloud Storage FUSE יהיה מספיק זמן לרוקן מידע (Flush) אחרי שהאפליקציה תצא. מידע נוסף זמין במאמר שיטות מומלצות ל-Kubernetes: סיום פעולה בצורה תקינה.
    • spec.volumes[n].csi.volumeAttributes.mountOptions: העברת אפשרויות טעינה אל Cloud Storage FUSE. מציינים את הדגלים במחרוזת אחת שמופרדת באמצעות פסיקים, ללא רווחים.
    • spec.volumes[n].csi.volumeAttributes: העברת מאפייני נפח נוספים אל Cloud Storage FUSE.
    • spec.volumes[n].csi.readOnly: מציינים true אם כל הנפחים המותקנים הם לקריאה בלבד.
    • spec.containers[n].volumeMounts[m].readOnly: מציינים true אם רק נקודת טעינה ספציפית של נפח היא לקריאה בלבד.
  2. מריצים את הפקודה הבאה כדי להחיל את המניפסט על האשכול:

    kubectl apply -f FILE_PATH
    

    מחליפים את FILE_PATH בנתיב לקובץ ה-YAML.

קפסולה (שמירה במטמון של קבצים)

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

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

  2. יוצרים מניפסט YAML של Pod עם המפרט הבא:

    apiVersion: v1
    kind: Pod
    metadata:
      name: gcs-fuse-csi-file-cache-example 
      namespace: NAMESPACE
      annotations:
        gke-gcsfuse/volumes: "true"
        gke-gcsfuse/ephemeral-storage-limit: "50Gi" 
    spec:
      nodeSelector:
        cloud.google.com/gke-ephemeral-storage-local-ssd: "true"
      restartPolicy: Never
      initContainers:
      - name: data-loader
        image: gcr.io/google.com/cloudsdktool/google-cloud-cli:slim
        resources:
          limits:
            cpu: 500m
            memory: 1Gi
          requests:
            cpu: 500m
            memory: 1Gi
        command:
          - "/bin/sh"
          - "-c"
          - |
            mkdir -p /test_files
            for i in $(seq 1 1000); do dd if=/dev/zero of=/test_files/file_$i.txt bs=1024 count=64; done
            gcloud storage cp /test_files gs://BUCKET_NAME --recursive
      containers:
      - name: data-validator
        image: busybox
        resources:
          limits:
            cpu: 500m
            memory: 512Mi
          requests:
            cpu: 500m
            memory: 512Mi
        command:
          - "/bin/sh"
          - "-c"
          - |
            echo "first read with cache miss"
            time cat /data/test_files/file_* > /dev/null
    
            echo "second read from local cache"
            time cat /data/test_files/file_* > /dev/null 
        volumeMounts:
        - name: gcs-fuse-csi-ephemeral
          mountPath: /data
      serviceAccountName: KSA_NAME
      volumes:
      - name: gcs-fuse-csi-ephemeral
        csi:
          driver: gcsfuse.csi.storage.gke.io
          volumeAttributes:
            bucketName: BUCKET_NAME
            mountOptions: "implicit-dirs,file-cache:max-size-mb:-1"
    

    מחליפים את הערכים הבאים:

    • NAMESPACE: מרחב השמות של Kubernetes שבו רוצים לפרוס את ה-Pod.
    • KSA_NAME: השם של KubernetesServiceAccount שציינתם כשקבעתם את הגישה לקטגוריות של Cloud Storage.
    • BUCKET_NAME: שם הקטגוריה ב-Cloud Storage שציינתם כשקבעתם את הגישה לקטגוריות ב-Cloud Storage. אפשר לציין קו תחתון (_) כדי לטעון את כל הקטגוריות שחשבון השירות של Kubernetes יכול לגשת אליהן. מידע נוסף זמין במאמר Dynamic mounting במאמרי העזרה של Cloud Storage FUSE.

      במניפסט לדוגמה, קובץ ה-init container data-loader יוצר 1,000 קבצים בגודל 64 KiB, ומעלה את הקבצים לקטגוריה של Cloud Storage. הקונטיינר הראשי data-validator קורא את כל הקבצים מה-bucket פעמיים, ומתעד את משך הזמן.

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

    kubectl apply -f FILE_PATH
    

    מחליפים את FILE_PATH בנתיב לקובץ ה-YAML.

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

    kubectl logs -n NAMESPACE gcs-fuse-csi-file-cache-example -c data-validator
    

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

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

    first read with cache miss
    real    0m 54.68s
    ...
    second read from local cache
    real    0m 0.38s
    ...
    

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

Pod (הורדה מקבילה)

כדי לצרף את נפח ה-CSI הזמני עם הורדה מקבילה ב-Pod, פועלים לפי השלבים הבאים:

  1. יוצרים מניפסט YAML של Pod עם המפרט הבא:

    apiVersion: v1
    kind: Pod
    metadata:
      name: gcs-fuse-csi-example-ephemeral 
      namespace: NAMESPACE
      annotations:
        gke-gcsfuse/volumes: "true"
        gke-gcsfuse/ephemeral-storage-limit: "50Gi" 
    spec:
      containers:
      ...
      volumes:
      - name: gcs-fuse-csi-ephemeral 
        csi:
          driver: gcsfuse.csi.storage.gke.io
          volumeAttributes:
            bucketName: BUCKET_NAME
            mountOptions: "implicit-dirs,file-cache:enable-parallel-downloads:true,file-cache:max-size-mb:-1"
            fileCacheCapacity: "-1"
    

    מחליפים את הערכים הבאים:

    • NAMESPACE: מרחב השמות של Kubernetes שבו רוצים לפרוס את ה-Pod.
    • BUCKET_NAME: שם הקטגוריה ב-Cloud Storage שציינתם כשקבעתם את הגישה לקטגוריות ב-Cloud Storage. אפשר לציין קו תחתון (_) כדי לטעון את כל הקטגוריות שחשבון השירות של Kubernetes יכול לגשת אליהן. מידע נוסף זמין במאמר Dynamic mounting במאמרי העזרה של Cloud Storage FUSE.
  2. מריצים את הפקודה הבאה כדי להחיל את המניפסט על האשכול:

    kubectl apply -f FILE_PATH
    

    מחליפים את FILE_PATH בנתיב לקובץ ה-YAML.

משימה

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

  1. יוצרים קובץ מניפסט של משרה ב-YAML עם המפרט הבא:

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: gcs-fuse-csi-job-example 
      namespace: NAMESPACE 
    spec:
      template:
        metadata: 
          annotations:
            gke-gcsfuse/volumes: "true"
        spec:
          serviceAccountName: KSA_NAME 
          containers:
          - name: writer
            image: busybox
            command:
              - "/bin/sh"
              - "-c"
              - touch /data/test && echo $(date) >> /data/test && sleep 10
            volumeMounts:
            - name: gcs-fuse-csi-ephemeral
              mountPath: /data
          - name: reader
            image: busybox
            command:
              - "/bin/sh"
              - "-c"
              - sleep 10 && cat /data/test 
            volumeMounts:
            - name: gcs-fuse-csi-ephemeral
              mountPath: /data
              readOnly: true
          volumes:
          - name: gcs-fuse-csi-ephemeral
            csi:
              driver: gcsfuse.csi.storage.gke.io
              volumeAttributes:
                bucketName: BUCKET_NAME
          restartPolicy: Never 
      backoffLimit: 1
    

    מחליפים את הערכים הבאים:

    • NAMESPACE: מרחב השמות של Kubernetes שבו פורס ה-Pod.
    • KSA_NAME: השם של KubernetesServiceAccount שציינתם כשקבעתם את הגישה לקטגוריות של Cloud Storage.
    • BUCKET_NAME: שם הקטגוריה ב-Cloud Storage שציינתם כשקבעתם את הגישה לקטגוריות ב-Cloud Storage. אפשר לציין קו תחתון (_) כדי לטעון את כל הקטגוריות שלחשבון שירות Kubernetes יש גישה אליהן. מידע נוסף זמין במאמר Dynamic mounting במאמרי העזרה של Cloud Storage FUSE.

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

    • metadata.annotations: נדרשת ההערה gke-gcsfuse/volumes: "true". במאמר הגדרת קונטיינר sidecar מוסבר איך מוסיפים הערות אופציונליות.
    • spec.volumes[n].csi.driver: שימוש ב-gcsfuse.csi.storage.gke.io כשם של מנהל ההתקן של CSI.

    אפשר גם לשנות את המשתנים האלה:

    • spec.volumes[n].csi.volumeAttributes.mountOptions: העברת אפשרויות טעינה אל Cloud Storage FUSE. מציינים את הדגלים במחרוזת אחת שמופרדת באמצעות פסיקים, ללא רווחים.
    • spec.volumes[n].csi.volumeAttributes: העברת מאפייני נפח נוספים אל Cloud Storage FUSE.
    • spec.volumes[n].csi.readOnly: מציינים true אם כל הנפחים המחוברים הם לקריאה בלבד.
    • spec.containers[n].volumeMounts[m].readOnly: מציינים true אם רק נקודת טעינה ספציפית של נפח היא לקריאה בלבד.
  2. מריצים את הפקודה הבאה כדי להחיל את המניפסט על האשכול:

    kubectl apply -f FILE_PATH
    

    מחליפים את FILE_PATH בנתיב לקובץ ה-YAML.

טעינת אותה קטגוריה של Cloud Storage עם אמצעי אחסון זמניים שונים של CSI

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

apiVersion: batch/v1
kind: Job
metadata:
  name: gcs-fuse-csi-job-example
  namespace: NAMESPACE
spec:
  template:
    metadata:
      annotations:
        gke-gcsfuse/volumes: "true"
    spec:
      serviceAccountName: KSA_NAME
      containers:
      - name: writer
        image: busybox
        command:
          - "/bin/sh"
          - "-c"
          - touch /data/test && echo $(date) >> /data/test && sleep 10
        volumeMounts: 
        - name: gcs-fuse-csi-ephemeral
          mountPath: /data
        volumeMounts:
        - name: gcs-fuse-csi-ephemeral-with-mo
          mountPath: /data2
      volumes:
      - name: gcs-fuse-csi-ephemeral
        csi:
          driver: gcsfuse.csi.storage.gke.io
          volumeAttributes:
            bucketName: BUCKET_NAME
      - name: gcs-fuse-csi-ephemeral-with-mo
        csi:
          driver: gcsfuse.csi.storage.gke.io
          volumeAttributes:
            bucketName: BUCKET_NAME
            mountOptions: "implicit-dirs"
      restartPolicy: Never
  backoffLimit: 1

פתרון בעיות

מידע נוסף על פתרון בעיות בדרייבר Cloud Storage FUSE CSI אפשר למצוא במדריך לפתרון בעיות במאמרי העזרה של פרויקט GitHub.

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