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

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

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

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

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

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

חשוב לוודא שפעלת לפי דרישות הסף הבאות:

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

נפחי אחסון זמניים של CSI מפשטים את ניהול האחסון של האפליקציות ב-GKE. אתם מגדירים את הכרכים האפמריים של CSI ישירות במפרט של ה-Pod או של המשימה. שימוש באמצעי אחסון זמניים של 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 יכול לגשת אליהן. מידע נוסף זמין במאמר טעינה דינמית במסמכי התיעוד של 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 יהיה מספיק זמן לנקות את הנתונים אחרי שהאפליקציה תצא. למידע נוסף, קראו את המאמר שיטות מומלצות ל-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.

‫Pod (שמירת קבצים במטמון)

כדי לצרף את הנפח הזמני של 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: השם של חשבון השירות ב-Kubernetes שציינתם כשהגדרתם את הגישה לקטגוריות של Cloud Storage.
    • ‫BUCKET_NAME: השם של הקטגוריה ב-Cloud Storage שציינתם כשקבעתם את הגישה לקטגוריות ב-Cloud Storage. אפשר לציין קו תחתון (_) כדי לטעון את כל הקטגוריות שחשבון השירות של Kubernetes יכול לגשת אליהן. מידע נוסף זמין במאמר Dynamic mounting במאמרי העזרה של Cloud Storage FUSE.

      במניפסט לדוגמה, מאגר ה-init‏ data-loader יוצר 1,000 קבצים בגודל 64KiB ומעלה אותם לקטגוריה של 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. יוצרים קובץ מניפסט של Job ב-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.

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