透過 Filestore 部署有狀態的工作負載


本教學課程說明如何使用 永久磁碟區 (PV)永久磁碟區要求 (PVC),在 Google Kubernetes Engine (GKE) 上部署簡單的讀取端/寫入端有狀態工作負載。請參閱本教學課程,瞭解如何使用 Google Cloud 的受管理網路檔案系統 Filestore,設計可擴充的系統。

背景

Pod 本質上是暫時性的,也就是說,GKE 會在 Pod 遭到刪除、逐出或重新排程時,清除 Pod 中儲存的狀態和值。

應用程式運算子可能需要維護有狀態的工作負載。這類工作負載的範例包括處理 WordPress 文章的應用程式、訊息應用程式,以及處理機器學習作業的應用程式。

在 GKE 上使用 Filestore 時,您可以執行下列作業:

  • 部署可擴充的有狀態工作負載。
  • 讓多個 Pod 將 ReadWriteMany 設為 accessMode,以便多個 Pod 同時讀取及寫入同一個儲存空間。
  • 設定 GKE,同時將磁碟區掛接到多個 Pod。
  • 在移除 Pod 時保留儲存空間。
  • 讓 Pods 共用資料,輕鬆擴充規模。

目標

本教學課程適用於應用程式運算子和其他使用者,他們想使用 PVC 和 NFS 在 GKE 上設定可擴充的有狀態工作負載。

有狀態工作負載 GKE 圖表

本教學課程包含下列步驟:

  1. 建立 GKE 叢集。
  2. 使用 CSI 透過 Filestore 設定代管檔案儲存空間。
  3. 建立讀取者和寫入者 Pod。
  4. 將讀取者 Pod 公開至 Service 負載平衡器以存取。
  5. 擴大寫入者數量。
  6. 從寫入者 Pod 存取資料。

費用

本教學課程使用下列 Google Cloud的計費元件:

使用 Pricing Calculator 可根據您的預測使用量來產生費用預估。

完成本教學課程後,您可以刪除建立的資源以避免繼續計費。詳情請參閱「清除」。


如要直接在 Google Cloud 控制台按照逐步指南操作,請按一下「Guide me」(逐步引導)

逐步引導


事前準備

設定專案

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

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

    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.

    Go to project selector

  6. Make sure that billing is enabled for your Google Cloud project.

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

    Enable the APIs

  8. 設定 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

    使用 CSI 透過 Filestore 設定代管檔案儲存空間

    GKE 可在叢集中自動部署及管理 Kubernetes Filestore CSI 驅動程式。使用 Filestore CSI,您就能動態建立或刪除 Filestore 執行個體,並透過 StorageClassDeployment 在 Kubernetes 工作負載中使用這些執行個體。

    您可以建立 PVC,動態佈建 Filestore 執行個體和 PV,藉此建立新的 Filestore 執行個體,也可以在 Kubernetes 工作負載中存取預先佈建的 Filestore 執行個體。

    新增執行個體

    建立 StorageClass

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: filestore-sc
    provisioner: filestore.csi.storage.gke.io
    volumeBindingMode: Immediate
    allowVolumeExpansion: true
    parameters:
      tier: standard
      network: default
    • volumeBindingMode 設為 Immediate,系統會立即開始佈建磁碟區。
    • tier 設為 standard,加快 Filestore 執行個體建立時間。 如需高可用性的 NFS 儲存空間、資料備份的快照、跨多個可用區的資料複製功能,以及其他企業級功能,請改為將 tier 設為 enterprise。 注意:如果未設定 StorageClass 中的 reclaimPolicy,系統會將動態建立的 PV 預設為 Delete
    1. 建立 StorageClass 資源:

      kubectl create -f filestore-storageclass.yaml
      
    2. 確認已建立儲存空間級別:

      kubectl get sc
      

      輸出結果會與下列內容相似:

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

    預先佈建的執行個體

    建立 StorageClass

    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. 確認已建立儲存空間級別:

        kubectl get sc
      

      輸出結果會與下列內容相似:

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

    為 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
      

      請記下 Filestore 執行個體的 INSTANCE_NAMELOCATIONFILE_SHARE_NAMEIP_ADDRESS

    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. 確認 PV 的 STATUS 已設為 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 資訊清單會參照 Filestore CSI 驅動程式的 StorageClass,名稱為 filestore-sc

    如要讓多個 Pod 讀取及寫入磁碟區,請將 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
      
    3. 確認新建立的 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
      

    建立讀取者和寫入者 Pod

    在本節中,您將建立讀取者 Pod 和寫入者 Pod。本教學課程使用 Kubernetes 部署建立 Pod。Deployment 是 Kubernetes API 物件,可讓您執行多個 Pod 副本,並將這些副本分配到叢集中的節點。

    建立讀取者 Pod

    讀取者 Pod 會讀取寫入者 Pod 正在寫入的檔案。 讀取者 Pod 會看到寫入者 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 會從所有 Pod 共用的路徑 /usr/share/nginx/html 讀取資料。

    1. 部署讀取者 Pod:

      kubectl apply -f reader-fs.yaml
      
    2. 查詢 Pod 清單,確認讀取器副本是否正在執行:

      kubectl get pods
      

      輸出結果會與下列內容相似:

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

    建立寫入者 Pod

    寫入者 Pod 會定期寫入其他寫入者和讀取者 Pod 可存取的共用檔案。寫入器 Pod 會將主機名稱寫入共用檔案,記錄自身狀態。

    用於 Writer 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. 查詢 Pod 清單,確認寫入器 Pod 是否正在運作:

      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
      

    將讀取者工作負載公開至 Service 負載平衡器以存取

    如要從叢集外部公開發布工作負載,請建立類型為 LoadBalancer 的 Service。這種類型的 Service 會建立外部負載平衡器,並指派可透過網際網路存取的 IP 位址。

    1. 建立名為 reader-lbLoadBalancer 類型服務:

      kubectl create -f loadbalancer.yaml
      
    2. 監控部署作業,確認 GKE 為 reader-lb 服務指派 EXTERNAL-IP

      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 可以擴充 Pod 數量,讓更多寫入者 Pod 寫入這個共用磁碟區 (或讓更多讀取者讀取)。

    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

    此時,您已設定及擴充叢集,支援五個具狀態的寫入者 Pod。多個寫入器 Pod 同時寫入同一個檔案。讀取者 Pod 也可以輕鬆擴充。

    選用:從 Writer 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. In the Google Cloud console, go to the Manage resources page.

      Go to Manage resources

    2. In the project list, select the project that you want to delete, and then click Delete.
    3. In the dialog, type the project ID, and then click Shut down to delete the project.

    刪除個別資源

    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. 確認 Pod 已刪除並傳回 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 叢集的資源,包括讀取者和寫入者 Pod。

    後續步驟