透過 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」(逐步引導)

「Guide me」(逐步引導)


事前準備

設定專案

  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

  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 執行個體。

新增執行個體

建立儲存空間類別

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。 注意:如果未設定 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
    

預先佈建的執行個體

建立儲存空間類別

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
    

建立讀取者和寫入者 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. 確認新建立的 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. 查詢 Pod 清單,確認讀取器副本是否正在執行:

    kubectl get pods
    

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

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

建立寫入者 Pod

寫入者 Pod 會定期寫入其他寫入者和讀取者 Pod 可存取的共用檔案。寫入器 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. 查詢 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 Service 指派 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。

後續步驟