הקצאת נפחי אחסון של דיסקים לאחסון מתמיד אזורי ו-Hyperdisk Balanced High Availability

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

כדי ליצור פתרונות מקצה לקצה לאפליקציות עם זמינות גבוהה באמצעות דיסקים קשיחים אזוריים, אפשר לעיין במאמר שיפור הזמינות של אפליקציות עם שמירת מצב באמצעות Stateful HA Operator. התכונה הזו לא תומכת בנפחי אחסון של Hyperdisk Balanced High Availability.

Hyperdisk Balanced High Availability

בדוגמה הזו אפשר לראות איך אפשר להקצות נפחים של Hyperdisk Balanced High Availability באופן דינמי לפי הצורך, או להקצות אותם מראש באופן ידני על ידי אדמין האשכול.

הקצאת הרשאות דינמית

  1. שומרים את המניפסט הבא בקובץ בשם balanced-ha-storage.yaml.

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: balanced-ha-storage
    provisioner: pd.csi.storage.gke.io
    volumeBindingMode: WaitForFirstConsumer
    # Allow volume expansion.
    allowVolumeExpansion: true
    parameters:
      type: hyperdisk-balanced-high-availability
      # Provisioned throughput in MiB/s.
      provisioned-throughput-on-create: "250Mi"
      # Provisioned IOPS (input/output operations per second).
      provisioned-iops-on-create: "7000"
    allowedTopologies:
    - matchLabelExpressions:
      - key: topology.gke.io/zone
        values:
        - ZONE1
        - ZONE2
    

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

    • ‫ZONE1, ZONE2: האזורים בתוך האזור שבו יתבצע השכפול של אמצעי האחסון שהוקצה באופן דינמי.
  2. יוצרים את StorageClass:

    kubectl create -f hdb-ha-example-class.yaml
    
  3. שומרים את מניפסט PersistentVolumeClaim הבא בקובץ בשם pvc-example.yaml:

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: podpvc
    spec:
      accessModes:
      - ACCESS_MODE
      storageClassName: balanced-ha-storage
      resources:
        requests:
          storage: 20Gi
    

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

    • ‫ACCESS_MODE: Hyperdisk Balanced High Availability תומך ב-ReadWriteOnce, ב-ReadWriteMany וב-ReadWriteOncePod. במאמר מצבי גישה ל-Persistent Volume מוסבר על ההבדלים בין מצבי הגישה ועל תרחישי השימוש בכל אחד מהם.
    • אם בוחרים להשתמש ב-ReadWriteMany, צריך להוסיף את volumeMode: Block גם ל-PersistentVolumeClaim. ההגדרה הזו מונעת שיבוש נתונים שיכול לקרות אם כמה תרמילים כותבים לאחסון בו-זמנית. ההגדרה volumeMode: Block חושפת את הדיסק כהתקן בלוקים גולמי שעוקף את ניהול מערכת הקבצים על ידי Kubernetes. לדוגמה:
      kind: PersistentVolumeClaim
      apiVersion: v1
      metadata:
        name: podpvc
      spec:
        accessModes:
        - ReadWriteMany
        volumeMode: Block
        storageClassName: balanced-ha-storage
        resources:
          requests:
            storage: 20Gi
      ```
    
  4. מחילים את PersistentVolumeClaim שמפנה אל StorageClass שיצרתם קודם:

    kubectl apply -f pvc-example.yaml
    

הקצאת הרשאות ידנית

  1. פועלים לפי ההוראות במאמר בנושא Compute Engine כדי ליצור נפח אחסון של Hyperdisk Balanced High Availability באופן ידני.

  2. שומרים את המניפסט של PersistentVolume בקובץ בשם pv-example.yaml. קובץ המניפסט מפנה לנפח האחסון Hyperdisk Balanced High Availability שיצרתם:

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv-demo
    spec:
      capacity:
        storage: 500Gi
      accessModes:
        - ACCESS_MODE
      # ClaimRef links this PersistentVolume to a PersistentVolumeClaim.
      claimRef:
        namespace: default
        name: podpvc
      csi:
        driver: pd.csi.storage.gke.io
        # The unique identifier of the Compute Engine disk resource that backs this volume.
        volumeHandle: projects/PROJECT_ID/regions/REGION/disks/gce-disk-1
      # Node affinity to ensure the Pod is scheduled in a zone where the volume is replicated.
      nodeAffinity:
        required:
          nodeSelectorTerms:
            - matchExpressions:
              - key: topology.gke.io/zone
                operator: In
                values:
                - ZONE1
                - ZONE2
    

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

    • ‫PROJECT_ID: מזהה הפרויקט של אמצעי האחסון שיצרתם.
    • ‫REGION: האזור של הדיסק שיצרתם. למידע על הזמינות האזורית העדכנית, אפשר לעיין במאמרי העזרה של Compute Engine.
    • ‫ZONE1, ZONE2: האזורים בתוך האזור שבו הכרך שיצרתם משוכפל.
    • ‫ACCESS_MODE: Hyperdisk Balanced High Availability תומך ב-ReadWriteOnce, ב-ReadWriteMany וב-ReadWriteOncePod. במאמר מצבי גישה ל-Persistent Volume מוסבר על ההבדלים בין מצבי הגישה ועל תרחישי השימוש בכל אחד מהם.
  3. יוצרים את Persistent Volume שמפנה לנפח Hyperdisk Balanced High Availability שיצרתם קודם:

    kubectl apply -f pv-example.yaml
    
  4. שומרים את מניפסט PersistentVolumeClaim הבא בקובץ בשם pvc-example.yaml:

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: podpvc
    spec:
      accessModes:
      - ACCESS_MODE
      storageClassName: balanced-ha-storage
      resources:
        requests:
          storage: 20Gi
    

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

    • ‫ACCESS_MODE: Hyperdisk Balanced High Availability תומך ב-ReadWriteOnce, ב-ReadWriteMany וב-ReadWriteOncePod. מצב הגישה צריך להיות זהה לזה שצוין ב-PersistentVolume מהשלב הקודם. במאמר מצבי גישה ל-Persistent Volume מוסבר על ההבדלים בין מצבי הגישה ועל תרחישי השימוש בכל אחד מהם.
  5. מחילים את PersistentVolumeClaim שמפנה אל PersistentVolume שיצרתם קודם:

    kubectl apply -f pvc-example.yaml
    

שימוש בנפח אחסון עם גישת קריאה וכתיבה מרובות במצב בלוק

כדי להשתמש באמצעי אחסון במצב בלוק, צריך לציין volumeBlock במקום volumeMounts ב-Pod שמשתמש בו. דוגמה ל-Pod שמשתמש ב-PersistenVolumeClaim שהוצג קודם:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server-deployment
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        # Use volumeDevices instead of volumeMounts to consume the volume as a raw block device.
        volumeDevices:
        # The "mountPath" field specifies the path where the block device is accessible in the container.
        - mountPath: /dev/my-device
          name: mypvc
      volumes:
      - name: mypvc
        persistentVolumeClaim:
          claimName: podpvc
          readOnly: false

דיסקים לאחסון מתמיד אזורי

בדומה לדיסקים לאחסון מתמיד של תחום, אפשר להקצות דינמית דיסקים לאחסון מתמיד אזורי לפי הצורך, או להקצות אותם מראש באופן ידני על ידי האדמין של האשכול. עם זאת, מומלץ להקצות אותם באופן דינמי. כדי להשתמש בדיסקים לאחסון מתמיד אזורי מסוג pd-standard, צריך להגדיר את המאפיין spec.resources.requests.storage של PersistentVolumeClaim לערך מינימלי של ‎200 GiB. אם אתם צריכים נפח קטן יותר, כדאי להשתמש במקום זאת ב-pd-balanced או ב-pd-ssd.

הקצאת הרשאות דינמית

כדי להפעיל הקצאה דינמית של דיסקים לאחסון מתמיד (persistent disks) אזוריים, צריך ליצור StorageClass עם הפרמטר replication-type ולציין אילוצים של אזור ב-allowedTopologies.

לדוגמה, המניפסט הבא מתאר מכונת StorageClass בשם regionalpd-storageclass שמשתמשת בדיסקים קשיחים רגילים ומשכפלת נתונים לאזורים europe-west1-b ו-europe-west1-c:

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: regionalpd-storageclass
provisioner: pd.csi.storage.gke.io
parameters:
  type: pd-balanced
  # Specifies that the disk should be a regional persistent disk.
  replication-type: regional-pd
volumeBindingMode: WaitForFirstConsumer
# Constrains which zones the regional persistent disk can be provisioned in.
allowedTopologies:
- matchLabelExpressions:
  - key: topology.gke.io/zone
    values:
    - europe-west1-b
    - europe-west1-c

אם משתמשים באשכול אזורי, אפשר לא לציין את allowedTopologies. אם תעשו את זה, כשתיצרו Pod שמשתמש ב-PersistentVolumeClaim שמשתמש ב-StorageClass, יוקצה דיסק לאחסון מתמיד אזורי עם שני אזורים. תחום אחד זהה לתחום שבו מתוזמן ה-Pod. התחום השני נבחר באופן אקראי מבין התחומים שזמינים לאשכול.

כשמשתמשים באשכול אזורי, צריך להגדיר את allowedTopologies.

אחרי שיוצרים את StorageClass, יוצרים אובייקט PersistentVolumeClaim, ומשתמשים בשדה storageClassName כדי להפנות אל StorageClass. לדוגמה, המניפסט הבא יוצר PersistentVolumeClaim בשם regional-pvc ומפנה אל regionalpd-storageclass:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: regional-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 500Gi
  storageClassName: regionalpd-storageclass

מכיוון שה-StorageClass מוגדר עם volumeBindingMode: WaitForFirstConsumer, לא מוקצה PersistentVolume עד שנוצר Pod באמצעות PersistentVolumeClaim.

המאניפסט הבא הוא דוגמה ל-Pod שמשתמש ב-PersistentVolumeClaim שנוצר קודם:

kind: Pod
apiVersion: v1
metadata:
  name: task-pv-pod
spec:
  volumes:
    - name: task-pv-storage
      # This Pod uses the PVC that's associated with the
      # "regionalpd-storageclass" StorageClass.
      persistentVolumeClaim:
        claimName: regional-pvc
  containers:
    - name: task-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      # The volume is mounted into the container at the "/usr/share/nginx/html" path.
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: task-pv-storage

הקצאת הרשאות ידנית

קודם יוצרים דיסק מתמשך אזורי באמצעות הפקודה gcloud compute disks create. בדוגמה הבאה נוצר דיסק בשם gce-disk-1 שמשוכפל לאזורים europe-west1-b ו-europe-west1-c:

gcloud compute disks create gce-disk-1 \
   --size 500Gi \
   --region europe-west1 \
   --replica-zones europe-west1-b,europe-west1-c

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

דוגמה לStorageClassמניפסט שמשתמש בדיסקים סטנדרטיים קבועים ומשכפל נתונים לאזורים europe-west1-b ו-europe-west1-c:

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: regionalpd-storageclass
provisioner: pd.csi.storage.gke.io
parameters:
  type: pd-balanced
  # Specifies that the disk should be a regional persistent disk.
  replication-type: regional-pd
volumeBindingMode: WaitForFirstConsumer
# Constrains which zones the regional persistent disk can be provisioned in.
allowedTopologies:
- matchLabelExpressions:
  - key: topology.gke.io/zone
    values:
    - europe-west1-b
    - europe-west1-c

דוגמה למניפסט שיוצר PersistentVolume בשם pv-demo ומפנה אל regionalpd-storageclass:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-demo
spec:
  # The StorageClass that specifies regional replication.
  storageClassName: "regionalpd-storageclass"
  capacity:
     storage: 500Gi
  accessModes:
     - ReadWriteOnce
  claimRef:
    namespace: default
    name: pv-claim-demo
  csi:
    driver: pd.csi.storage.gke.io
    # The unique identifier for the pre-existing regional disk.
    volumeHandle: projects/PROJECT_ID/regions/europe-west1/disks/gce-disk-1
  # Ensures that Pods are scheduled in zones where the disk is replicated.
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
          - key: topology.gke.io/zone
            operator: In
            values:
               - europe-west1-b
               - europe-west1-c

הערות לגבי הדוגמה PersistentVolume:

  • השדה volumeHandle מכיל פרטים מהקריאה gcloud compute disks create, כולל PROJECT_ID.
  • צריך לציין את השדה claimRef.namespace גם אם הערך שלו הוא default.

מתן שמות לדיסקים לאחסון מתמיד

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

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