פריסה של עומס עבודה עם שמירת מצב באמצעות Filestore

במדריך הזה נסביר איך לפרוס עומס עבודה פשוט עם מצב (stateful) של קריאה/כתיבה באמצעות Persistent Volume (PV) ו-Persistent Volume Claim (PVC) ב-Google Kubernetes Engine ‏(GKE). במדריך הזה מוסבר איך לתכנן מדרגיות באמצעות Filestore, מערכת קבצים מנוהלת ברשת של Google Cloud.

רקע

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

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

באמצעות Filestore ב-GKE, אפשר לבצע את הפעולות הבאות:

  • לפרוס עומסי עבודה עם שמירת מצב שניתנים להרחבה.
  • להפעיל את האפשרות של כמה Pods להשתמש ב-ReadWriteMany בתור accessMode, כדי שכמה Pods יוכלו לקרוא ולכתוב בו-זמנית לאותו אחסון.
  • מגדירים את GKE כך שיצור נפחים (volumes) לכמה Pods בו-זמנית.
  • שמירת נתונים באחסון כשמסירים Pods.
  • הפעלת שיתוף נתונים בין Pods והרחבה קלה של הקיבולת.

מטרות

המדריך הזה מיועד למפעילים של אפליקציות ולמשתמשים אחרים שרוצים להגדיר עומס עבודה ניתן להרחבה עם שמירת מצב ב-GKE באמצעות PVC ו-NFS.

תרשים של עומס עבודה עם שמירת מצב ב-GKE

במדריך הזה מוסבר איך:

  1. יוצרים אשכול GKE.
  2. מגדירים את האחסון המנוהל של קבצים באמצעות Filestore באמצעות CSI.
  3. יוצרים Pod לקריאה ולכתיבה.
  4. חשיפה של ה-Pod של הקורא למאזן עומסים של שירות וגישה אליו.
  5. להגדיל את מספר הכותבים.
  6. גישה לנתונים מ-Pod הכתיבה.

עלויות

במדריך הזה השתמשנו ברכיבים הבאים של Google Cloud, והשימוש בהם כרוך בתשלום:

השתמשו במחשבון עלויות כדי ליצור הערכת עלות על סמך השימוש החזוי.

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


לחצו על תראו לי איך כדי לקרוא הסבר מפורט על המשימה ישירות במסוף Google Cloud :

תראו לי איך


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

הגדרת הפרויקט

  1. נכנסים לחשבון Google Cloud . אם אתם משתמשים חדשים ב- Google Cloud, צרו חשבון כדי שתוכלו להעריך את הביצועים של המוצרים שלנו בתרחישים מהעולם האמיתי. לקוחות חדשים מקבלים בחינם גם קרדיט בשווי 300$ להרצה, לבדיקה ולפריסה של עומסי העבודה.
  2. In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.

    Roles required to create a project

    To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. Enable the Compute Engine, GKE, and Filestore APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  5. In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.

    Roles required to create a project

    To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  6. Verify that billing is enabled for your Google Cloud project.

  7. Enable the Compute Engine, GKE, and Filestore APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

הגדרת ברירות מחדל ל-Google Cloud CLI

  1. במסוף Google Cloud , מפעילים מכונת Cloud Shell:
    פתיחת Cloud Shell

  2. מורידים את קוד המקור של האפליקציה לדוגמה:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    cd kubernetes-engine-samples/databases/stateful-workload-filestore
    
  3. מגדירים את משתני הסביבה שמוגדרים כברירת מחדל:

    gcloud config set project PROJECT_ID
    gcloud config set compute/region COMPUTE_REGION
    gcloud config set compute/zone COMPUTE_ZONE
    gcloud config set filestore/zone COMPUTE_ZONE
    gcloud config set filestore/region COMPUTE_REGION
    

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

יצירת אשכול GKE

  1. יוצרים אשכול GKE:

    gcloud container clusters create-auto CLUSTER_NAME --location CONTROL_PLANE_LOCATION
    

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

    • CLUSTER_NAME: שם האשכול.
    • CONTROL_PLANE_LOCATION: המיקום של Compute Engine במישור הבקרה של האשכול. מציינים אזור לאשכולות אזוריים או אזור זמין לאשכולות אזוריים.

    אחרי שיוצרים את האשכול, התוצאה אמורה להיראות כך:

      gcloud container clusters describe CLUSTER_NAME
      NAME: CLUSTER_NAME
      LOCATION: northamerica-northeast2
      MASTER_VERSION: 1.21.11-gke.1100
      MASTER_IP: 34.130.255.70
      MACHINE_TYPE: e2-medium
      NODE_VERSION: 1.21.11-gke.1100
      NUM_NODES: 3
      STATUS: RUNNING
    

    כאשר הערך של STATUS הוא RUNNING.

הגדרת אחסון קבצים מנוהל באמצעות Filestore באמצעות CSI

‫GKE מספק דרך לפרוס ולנהל אוטומטית את מנהל ההתקן של ה-CSI של Kubernetes Filestore באשכולות. שימוש ב-Filestore CSI מאפשר ליצור או למחוק באופן דינמי מופעים של Filestore ולהשתמש בהם בעומסי עבודה של Kubernetes עם StorageClass או Deployment.

אתם יכולים ליצור מופע חדש של Filestore על ידי יצירת PVC שמקצה באופן דינמי מופע של Filestore ואת ה-PV, או לגשת למופעים של Filestore שהוקצו מראש בעומסי עבודה של Kubernetes.

מופע חדש

יצירת מחלקת אחסון

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: filestore-sc
provisioner: filestore.csi.storage.gke.io
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
parameters:
  tier: standard
  network: default
  • הערך של volumeBindingMode מוגדר ל-WaitForFirstConsumer, מה שגורם לעיכוב בהקצאת נפח האחסון עד ש-Pod ישתמש בו. ההגדרה הזו מאפשרת למישור הבקרה לדעת את המיקום של עוצמת הקול (ב-Kubernetes זה נקרא טופולוגיה), ומאפשרת לדוגמה הזו לפעול באשכולות חדשים ללא צמתים, שבהם עדיין אין טופולוגיה.
  • הערך של tier מוגדר ל-standard כדי לקצר את זמן היצירה של מופע Filestore. אם אתם צריכים אחסון NFS עם זמינות גבוהה יותר, תמונות מצב לגיבוי נתונים, שכפול נתונים בכמה אזורים ותכונות אחרות ברמת הארגון, כדאי להגדיר את tier ל-enterprise. הערה: מדיניות השחזור של PV שנוצר באופן דינמי היא Delete כברירת מחדל, אם לא מוגדר reclaimPolicy ב-StorageClass.
  1. יוצרים את משאב StorageClass:

    kubectl create -f filestore-storageclass.yaml
    
  2. מוודאים שנוצר Storage Class:

    kubectl get sc
    

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

    NAME                     PROVISIONER                    RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
    filestore-sc             filestore.csi.storage.gke.io   Delete          Immediate              true                   94m
    

מופע שהוקצה מראש

יצירת מחלקת אחסון

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: filestore-sc
provisioner: filestore.csi.storage.gke.io
volumeBindingMode: Immediate
allowVolumeExpansion: true

כשהערך של volumeBindingMode מוגדר כ-Immediate, אפשר להתחיל מיד את הקצאת נפח האחסון.

  1. יוצרים את משאב StorageClass:

      kubectl create -f preprov-storageclass.yaml
    
  2. מוודאים שנוצר Storage Class:

      kubectl get sc
    

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

      NAME                     PROVISIONER                    RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
      filestore-sc             filestore.csi.storage.gke.io   Delete          Immediate              true                   94m
    

יצירת נפח אחסון מתמיד (Persistent Volume) למופע Filestore

apiVersion: v1
kind: PersistentVolume
metadata:
  name: fileserver
  annotations:
    pv.kubernetes.io/provisioned-by: filestore.csi.storage.gke.io
spec:
  storageClassName: filestore-sc
  capacity:
    storage: 1Ti
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Delete
  volumeMode: Filesystem
  csi:
    driver: filestore.csi.storage.gke.io
    # Modify this to use the zone, filestore instance and share name.
    volumeHandle: "modeInstance/<LOCATION>/<INSTANCE_NAME>/<FILE_SHARE_NAME>"
    volumeAttributes:
      ip: <IP_ADDRESS> # Modify this to Pre-provisioned Filestore instance IP
      volume: <FILE_SHARE_NAME> # Modify this to Pre-provisioned Filestore instance share name
  1. מוודאים שמופע Filestore הקיים מוכן:

      gcloud filestore instances list
    

    הפלט אמור להיראות כך, כאשר הערך STATE הוא READY:

      INSTANCE_NAME: stateful-filestore
      LOCATION: us-central1-a
      TIER: ENTERPRISE
      CAPACITY_GB: 1024
      FILE_SHARE_NAME: statefulpath
      IP_ADDRESS: 10.109.38.98
      STATE: READY
      CREATE_TIME: 2022-04-05T18:58:28
    

    שימו לב לערכים INSTANCE_NAME, LOCATION, FILE_SHARE_NAME ו-IP_ADDRESS של מופע Filestore.

  2. מאכלסים את משתני המסוף של מכונת Filestore:

      INSTANCE_NAME=INSTANCE_NAME
      LOCATION=LOCATION
      FILE_SHARE_NAME=FILE_SHARE_NAME
      IP_ADDRESS=IP_ADDRESS
    
  3. מחליפים את משתני הפלייסהולדר במשתני המסוף שקיבלתם למעלה בקובץ preprov-pv.yaml:

      sed "s/<INSTANCE_NAME>/$INSTANCE_NAME/" preprov-pv.yaml > changed.yaml && mv changed.yaml preprov-pv.yaml
      sed "s/<LOCATION>/$LOCATION/" preprov-pv.yaml > changed.yaml && mv changed.yaml preprov-pv.yaml
      sed "s/<FILE_SHARE_NAME>/$FILE_SHARE_NAME/" preprov-pv.yaml > changed.yaml && mv changed.yaml preprov-pv.yaml
      sed "s/<IP_ADDRESS>/$IP_ADDRESS/" preprov-pv.yaml > changed.yaml && mv changed.yaml preprov-pv.yaml
    
  4. יצירת PV

      kubectl apply -f preprov-pv.yaml
    
  5. מוודאים ש-STATUS של ה-PV מוגדר ל-Bound:

      kubectl get pv
    

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

      NAME        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                STORAGECLASS    REASON   AGE
      fileserver  1Ti        RWX            Delete           Bound    default/fileserver   filestore-sc             46m
    

שימוש ב-PersistentVolumeClaim כדי לגשת לנפח האחסון

במניפסט pvc.yaml הבא יש הפניה ל-CSI driver של Filestore‏ StorageClass שנקרא filestore-sc.

כדי שכמה פודים יוכלו לקרוא ולכתוב את הווליום, הערך של accessMode מוגדר ל-ReadWriteMany.

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: fileserver
spec:
  accessModes:
  - ReadWriteMany
  storageClassName: filestore-sc
  resources:
    requests:
      storage: 1Ti
  1. פורסים את ה-PVC:

    kubectl create -f pvc.yaml
    
  2. מוודאים שה-PVC נוצר:

    kubectl get pvc
    

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

    NAME         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS        AGE
    fileserver   Bound    pvc-aadc7546-78dd-4f12-a909-7f02aaedf0c3   1Ti        RWX            filestore-sc        92m
    

יצירת Pod עם הרשאות קריאה וכתיבה

בקטע הזה יוצרים Pod לקריאה ו-Pod לכתיבה. במדריך הזה משתמשים ב-Kubernetes Deployments כדי ליצור את ה-Pods. פריסה היא אובייקט Kubernetes API שמאפשר להפעיל כמה רפליקות של Pods שמפוזרות בין הצמתים באשכול.

יצירת פודקאסט הקריאה

ה-Pod של הקורא יקרא את הקובץ שנכתב על ידי ה-Pods של הכותבים. ה-Pods של הקוראים יראו באיזו שעה ובאיזה עותק משוכפל של ה-Pod של הכותב נכתב הקובץ.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: reader
spec:
  replicas: 1
  selector:
    matchLabels:
      app: reader
  template:
    metadata:
      labels:
        app: reader
    spec:
      containers:
      - name: nginx
        image: nginx:stable-alpine
        ports:
        - containerPort: 80
        volumeMounts:
        - name: fileserver
          mountPath: /usr/share/nginx/html # the shared directory 
          readOnly: true
      volumes:
      - name: fileserver
        persistentVolumeClaim:
          claimName: fileserver

ה-Pod של הקורא יקרא מהנתיב /usr/share/nginx/html שמשותף לכל ה-Pods.

  1. פורסים את ה-Pod של הקורא:

    kubectl apply -f reader-fs.yaml
    
  2. בודקים שהמופע החדש של Filestore מוכן:

    gcloud filestore instances list
    

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

    INSTANCE_NAME: pvc-5bc55493-9e58-4ca5-8cd2-0739e0a7b68c
    LOCATION: northamerica-northeast2-a
    TIER: STANDARD
    CAPACITY_GB: 1024
    FILE_SHARE_NAME: vol1
    IP_ADDRESS: 10.29.174.90
    STATE: READY
    CREATE_TIME: 2022-06-24T18:29:19
    
  3. כדי לוודא שהרפליקות לקריאה פועלות, מריצים שאילתה על רשימת ה-Pods:

    kubectl get pods
    

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

    NAME                      READY   STATUS    RESTARTS   AGE
    reader-66b8fff8fd-jb9p4   1/1     Running   0          3m30s
    

יצירת תרמיל סופר

ה-Pod של הכותב יכתוב מעת לעת לקובץ משותף ש-Pods אחרים של כותבים וקוראים יכולים לגשת אליו. ה-Pod של הכותב מתעד את הנוכחות שלו על ידי כתיבת שם המארח שלו בקובץ המשותף.

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

apiVersion: apps/v1
kind: Deployment
metadata:
  name: writer
spec:
  replicas: 2 # start with 2 replicas
  selector:
    matchLabels:
      app: writer
  template:
    metadata:
      labels:
        app: writer
    spec:
      containers:
      - name: content
        image: us-docker.pkg.dev/google-samples/containers/gke/stateful-workload:latest
        volumeMounts:
        - name: fileserver
          mountPath: /html # the shared directory
        command: ["/bin/sh", "-c"]
        args:
        - cp /htmlTemp/indexInfo.html /html/index.html;
          while true; do
          echo "<b> Date :</b> <text>$(date)</text> <b> Writer :</b> <text2> ${HOSTNAME} </text2> <br>  " >> /html/indexData.html;
          sleep 30;  
          done
      volumes:
      - name: fileserver
        persistentVolumeClaim:
          claimName: fileserver

במדריך הזה, ה-Pod של הכותב כותב כל 30 שניות לנתיב /html/index.html. משנים את הערך של המספר sleep כדי להגדיר תדירות כתיבה שונה.

  1. פורסים את ה-Pod של הכותב:

    kubectl apply -f writer-fs.yaml
    
  2. כדי לוודא ש-Pods של כתיבה פועלים, שולחים שאילתה לרשימת ה-Pods:

    kubectl get pods
    

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

    NAME                      READY   STATUS    RESTARTS   AGE
    reader-66b8fff8fd-jb9p4   1/1     Running   0          3m30s
    writer-855565fbc6-8gh2k   1/1     Running   0          2m31s
    writer-855565fbc6-lls4r   1/1     Running   0          2m31s
    

חשיפה של עומס העבודה של הקורא למאזן עומסים של שירות וגישה אליו

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

  1. יוצרים שירות מסוג LoadBalancer בשם reader-lb:

    kubectl create -f loadbalancer.yaml
    
  2. צופים בפריסה כדי לוודא ש-GKE מקצה EXTERNAL-IP לשירות reader-lb:

    kubectl get svc --watch
    

    כשה-Service מוכן, בעמודה EXTERNAL-IP מוצגת כתובת ה-IP הציבורית של מאזן העומסים:

      NAME         TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)        AGE
      kubernetes   ClusterIP      10.8.128.1    <none>          443/TCP        2d21h
      reader-lb    LoadBalancer   10.8.131.79   34.71.232.122   80:32672/TCP   2d20h
    
  3. מקישים על Ctrl+C כדי להפסיק את תהליך הצפייה.

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

פרטים נוספים על שירות איזון העומסים זמינים במאמר loadbalancer.yaml.

הגדלת היקף הכתיבה

מכיוון שה-PV accessMode הוגדר ל-ReadWriteMany, ‏ GKE יכול להגדיל את מספר ה-Pods כדי שיותר Pods של כתיבה יוכלו לכתוב לנפח המשותף הזה (או שיותר קוראים יוכלו לקרוא אותם).

  1. הגדלת מספר הרפליקות של writer לחמש:

    kubectl scale deployment writer --replicas=5
    

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

    deployment.extensions/writer scaled
    
  2. בודקים את מספר הרפליקות הפועלות:

    kubectl get pods
    

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

    NAME                      READY   STATUS    RESTARTS   AGE
    reader-66b8fff8fd-jb9p4   1/1     Running   0          11m
    writer-855565fbc6-8dfkj   1/1     Running   0          4m
    writer-855565fbc6-8gh2k   1/1     Running   0          10m
    writer-855565fbc6-gv5rs   1/1     Running   0          4m
    writer-855565fbc6-lls4r   1/1     Running   0          10m
    writer-855565fbc6-tqwxc   1/1     Running   0          4m
    
  3. משתמשים בדפדפן אינטרנט כדי לנווט שוב אל EXTERNAL-IP שהוקצה למאזן העומסים.

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

אופציונלי: גישה לנתונים מ-Pod הכתיבה

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

  1. משיגים את שם ה-Pod של הכותב:

    kubectl get pods
    

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

    NAME                      READY   STATUS    RESTARTS   AGE
    writer-5465d65b46-7hxv4   1/1     Running   0          20d
    

    שימו לב לשם המארח של Pod של כותב (לדוגמה: writer-5465d65b46-7hxv4).

  2. מריצים את הפקודה הבאה כדי לגשת ל-Pod של הכותב:

    kubectl exec -it WRITER_HOSTNAME -- /bin/sh
    
  3. הנה הרכיב המשותף בקובץ indexData.html:

    cd /html
    cat indexData.html
    
  4. מנקים את הקובץ indexData.html:

    echo '' > indexData.html
    

    כדי לראות את השינוי, צריך לרענן את דפדפן האינטרנט שבו מתארחת הכתובת EXTERNAL-IP.

  5. כדי לצאת מהסביבה:

    exit
    

הסרת המשאבים

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

מחיקת הפרויקט

  1. במסוף Google Cloud , נכנסים לדף Manage resources.

    כניסה לדף Manage resources

  2. ברשימת הפרויקטים, בוחרים את הפרויקט שרוצים למחוק ולוחצים על Delete.
  3. כדי למחוק את הפרויקט, כותבים את מזהה הפרויקט בתיבת הדו-שיח ולוחצים על Shut down.

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

  1. מוחקים את שירות מאזן העומסים:

    kubectl delete service reader-lb
    

    ממתינים עד שמקצים את מאזן העומסים לשירות הקורא

  2. מוודאים שהרשימה מחזירה Listed 0 items:

    gcloud compute forwarding-rules list
    
  3. מחיקת הפריסות

    kubectl delete deployment writer
    kubectl delete deployment reader
    
  4. מוודאים שה-Pods נמחקו ומוחזרת התוצאה No resources found in default namespace.

    kubectl get pods
    
  5. מוחקים את ה-PVC. הפעולה הזו תמחק גם את ה-PV ואת מופע Filestore, כי מדיניות שמירת הנתונים מוגדרת ל-delete

    kubectl delete pvc fileserver
    
  6. מחיקת אשכול GKE:

    gcloud container clusters delete CLUSTER_NAME --location=CONTROL_PLANE_LOCATION
    

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

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