透過 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 --region COMPUTE_REGION
      

      請替換下列值:

      • CLUSTER_NAME:叢集名稱。

      叢集建立完成後,結果會類似如下:

        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 會將主機名稱寫入共用檔案,記錄自身狀態。

用於寫入器 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 --zone=COMPUTE_ZONE
    

    這會刪除組成 GKE 叢集的資源,包括讀取者和寫入者 Pod。

後續步驟