Esegui il deployment di un workload stateful con Filestore


Questo tutorial mostra come eseguire il deployment di un semplice workload stateful in lettura/scrittura utilizzando un Persistent Volume (PV) e una Persistent Volume Claim (PVC) su Google Kubernetes Engine (GKE). Segui questo tutorial per scoprire come progettare per la scalabilità utilizzando Filestore, il file system di rete gestito di Google Cloud.

Sfondo

Per loro natura, i pod sono temporanei. Ciò significa che GKE distrugge lo stato e il valore archiviati in un pod quando viene eliminato, rimosso o riprogrammato.

In qualità di operatore di applicazioni, potresti voler gestire i workload stateful. Alcuni esempi di questi workload includono applicazioni che elaborano articoli di WordPress, app di messaggistica e app che elaborano operazioni di machine learning.

Utilizzando Filestore su GKE, puoi eseguire le seguenti operazioni:

  • Esegui il deployment di carichi di lavoro stateful scalabili.
  • Consenti a più pod di avere ReadWriteMany come accessMode, in modo che più pod possano leggere e scrivere contemporaneamente nello stesso spazio di archiviazione.
  • Configura GKE per montare i volumi in più pod contemporaneamente.
  • Conserva lo spazio di archiviazione quando i pod vengono rimossi.
  • Consenti ai pod di condividere i dati e di scalare facilmente.

Obiettivi

Questo tutorial è destinato agli operatori di applicazioni e ad altri utenti che vogliono configurare un workload stateful scalabile su GKE utilizzando PVC e NFS.

Diagramma del workload stateful GKE

Questo tutorial illustra i seguenti passaggi:

  1. Creare un cluster GKE.
  2. Configura l'archiviazione di file gestiti con Filestore utilizzando CSI.
  3. Crea un pod del lettore e del writer.
  4. Esponi il pod del lettore a un bilanciatore del carico del servizio e accedi.
  5. Fai lo scale up del writer.
  6. Accedi ai dati dal pod del writer.

Costi

Questo tutorial utilizza i seguenti componenti fatturabili di Google Cloud:

Utilizza il Calcolatore prezzi per generare una stima dei costi in base all'utilizzo previsto.

Al termine di questo tutorial, puoi evitare l'addebito di ulteriori costi eliminando le risorse create. Per ulteriori informazioni, vedi Pulizia.


Per seguire le indicazioni dettagliate per questa attività direttamente nella Google Cloud console, fai clic su Procedura guidata:

Procedura guidata


Prima di iniziare

Configura il progetto

  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. Impostare i valori predefiniti per Google Cloud CLI

    1. Nella console Google Cloud , avvia un'istanza Cloud Shell:
      Apri Cloud Shell

    2. Scarica il codice sorgente di questa app di esempio:

      git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
      cd kubernetes-engine-samples/databases/stateful-workload-filestore
      
    3. Imposta le variabili di ambiente predefinite:

      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
      

      Sostituisci i seguenti valori:

    Crea un cluster GKE

    1. Crea un cluster GKE:

      gcloud container clusters create-auto CLUSTER_NAME --location CONTROL_PLANE_LOCATION
      

      Sostituisci il seguente valore:

      • CLUSTER_NAME: il nome del cluster.
      • CONTROL_PLANE_LOCATION: la posizione di Compute Engine del control plane del tuo cluster. Fornisci una regione per i cluster regionali o una zona per i cluster zonali.

      Una volta creato il cluster, il risultato è simile al seguente:

        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
      

      Dove STATUS è RUNNING.

    Configura l'archiviazione di file gestiti con Filestore utilizzando CSI

    GKE offre un modo per eseguire automaticamente il deployment e la gestione del driver CSI Kubernetes Filestore nei cluster. L'utilizzo di Filestore CSI consente di creare o eliminare dinamicamente istanze Filestore e utilizzarle nei carichi di lavoro Kubernetes con un StorageClass o un Deployment.

    Puoi creare una nuova istanza Filestore creando una PVC che esegue il provisioning dinamico di un'istanza Filestore e del PV oppure accedere a istanze Filestore di cui è stato eseguito il provisioning preliminare nei carichi di lavoro Kubernetes.

    Nuova istanza

    Crea la classe di archiviazione

    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 è impostato su Immediate, il che consente di iniziare immediatamente il provisioning del volume.
    • tier è impostato su standard per ridurre i tempi di creazione dell'istanza Filestore. Se hai bisogno di uno spazio di archiviazione NFS con maggiore disponibilità, snapshot per il backup dei dati, replica dei dati in più zone e altre funzionalità di livello aziendale, imposta tier su enterprise. Nota: se reclaimPolicy in StorageClass non è impostato, il criterio di recupero per i PV creati dinamicamente viene impostato su Delete per impostazione predefinita.
    1. Crea la risorsa StorageClass:

      kubectl create -f filestore-storageclass.yaml
      
    2. Verifica che la classe di archiviazione sia stata creata:

      kubectl get sc
      

      L'output è simile al seguente:

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

    Istanza di cui è stato eseguito il provisioning preliminare

    Crea la classe di archiviazione

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

    Se volumeBindingMode è impostato su Immediate, consente di iniziare il provisioning del volume immediatamente.

    1. Crea la risorsa StorageClass:

        kubectl create -f preprov-storageclass.yaml
      
    2. Verifica che la classe di archiviazione sia stata creata:

        kubectl get sc
      

      L'output è simile al seguente:

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

    Crea un Persistent Volume per l'istanza 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. Verifica che l'istanza Filestore preesistente sia pronta:

        gcloud filestore instances list
      

      L'output è simile al seguente, dove il valore 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
      

      Prendi nota di INSTANCE_NAME, LOCATION, FILE_SHARE_NAME e IP_ADDRESS dell'istanza Filestore.

    2. Compila le variabili della console dell'istanza Filestore:

        INSTANCE_NAME=INSTANCE_NAME
        LOCATION=LOCATION
        FILE_SHARE_NAME=FILE_SHARE_NAME
        IP_ADDRESS=IP_ADDRESS
      
    3. Sostituisci le variabili segnaposto con le variabili della console ottenute in precedenza nel file 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. Crea il PV

        kubectl apply -f preprov-pv.yaml
      
    5. Verifica che la variabile PV STATUS sia impostata su Bound:

        kubectl get pv
      

      L'output è simile al seguente:

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

    Usa un oggetto PersistentVolumeClaim per accedere al volume

    Il seguente file manifest pvc.yaml fa riferimento al StorageClass del driver CSI Filestore denominato filestore-sc.

    Per avere più pod del lettore e del writer nel volume, accessMode è impostato su ReadWriteMany.

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: fileserver
    spec:
      accessModes:
      - ReadWriteMany
      storageClassName: filestore-sc
      resources:
        requests:
          storage: 1Ti
    1. Esegui il deployment della PVC:

      kubectl create -f pvc.yaml
      
    2. Verifica che il PVC sia stato creato:

      kubectl get pvc
      

      L'output è simile al seguente:

      NAME         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS        AGE
      fileserver   Bound    pvc-aadc7546-78dd-4f12-a909-7f02aaedf0c3   1Ti        RWX            filestore-sc        92m
      
    3. Verifica che l'istanza Filestore appena creata sia pronta:

      gcloud filestore instances list
      

      L'output è simile al seguente:

      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
      

    Crea un pod del lettore e del writer

    In questa sezione, creerai un pod del lettore e un pod del writer. Questo tutorial utilizza i deployment Kubernetes per creare i pod. Un deployment è un oggetto API Kubernetes che consente di eseguire più repliche di pod distribuite tra i nodi di un cluster.

    Crea il pod del lettore

    Il pod del lettore leggerà il file scritto dai pod del writer. I pod del lettore vedranno l'ora e la replica del pod del writer che ha scritto nel file.

    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

    Il pod del lettore leggerà dal percorso /usr/share/nginx/html, condiviso tra tutti i pod.

    1. Esegui il deployment del pod del lettore:

      kubectl apply -f reader-fs.yaml
      
    2. Verifica che le repliche del lettore siano in esecuzione con una query sull'elenco dei pod:

      kubectl get pods
      

      L'output è simile al seguente:

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

    Crea il pod del writer

    Il pod del writer scrive periodicamente in un file condiviso a cui possono accedere altri pod del writer e del lettore. Il pod writer registra la sua presenza scrivendo il nome host nel file condiviso.

    L'immagine utilizzata per il pod writer è un'immagine personalizzata di Alpine Linux, che viene utilizzata per le utilità e le applicazioni di produzione. Include uno script indexInfo.html che recupera i metadati dell'ultimo autore e tiene traccia di tutti gli autori unici e delle scritture totali.

    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

    Per questo tutorial, il pod writer scrive ogni 30 secondi nel percorso /html/index.html. Modifica il valore del numero sleep in modo che abbia una frequenza di scrittura diversa.

    1. Esegui il deployment del pod del writer:

      kubectl apply -f writer-fs.yaml
      
    2. Verifica che i pod di scrittura siano in esecuzione con una query sull'elenco dei pod:

      kubectl get pods
      

      L'output è simile al seguente:

      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
      

    Esporre il workload del lettore a un bilanciatore del carico del servizio e accedervi

    Per esporre un carico di lavoro all'esterno del cluster, crea un servizio di tipo LoadBalancer. Questo tipo di servizio crea un bilanciatore del carico esterno con un indirizzo IP raggiungibile tramite internet.

    1. Crea un servizio di tipo LoadBalancer denominato reader-lb:

      kubectl create -f loadbalancer.yaml
      
    2. Guarda il deployment per vedere che GKE assegna un EXTERNAL-IP per il servizio reader-lb:

      kubectl get svc --watch
      

      Quando Service è pronto, la colonna EXTERNAL-IP mostra l'indirizzo IP pubblico del bilanciatore del carico:

        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. Premi Ctrl+C per terminare il processo di monitoraggio.

    4. Utilizza un browser web per accedere a EXTERNAL-IP assegnato al bilanciatore del carico. La pagina viene aggiornata ogni 30 secondi. Più sono i writer Pod e più breve è la frequenza, più voci verranno visualizzate.

    Per visualizzare ulteriori dettagli sul servizio di bilanciamento del carico, consulta loadbalancer.yaml.

    Fai lo scale up del writer

    Poiché il PV accessMode è stato impostato su ReadWriteMany, GKE può aumentare il numero di pod in modo che più pod del writer possano scrivere in questo volume condiviso (o più lettori possano leggerli).

    1. Aumenta lo scale up di writer a cinque repliche:

      kubectl scale deployment writer --replicas=5
      

      L'output è simile al seguente:

      deployment.extensions/writer scaled
      
    2. Verifica il numero di repliche in esecuzione:

      kubectl get pods
      

      L'output è simile al seguente:

      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. Utilizza un browser web per tornare a EXTERNAL-IP assegnato al bilanciatore del carico.

    A questo punto, hai configurato e scalato il cluster per supportare cinque pod writer stateful. Quando più pod di scrittura scrivono contemporaneamente nello stesso file. Anche i pod reader possono essere facilmente scalati.

    (Facoltativo) Accedi ai dati dal pod Writer

    Questa sezione mostra come utilizzare un'interfaccia a riga di comando per accedere a un pod di lettura o scrittura. Puoi vedere il componente condiviso in cui lo scrittore sta scrivendo e da cui il lettore sta leggendo.

    1. Ottieni il nome del pod del writer:

      kubectl get pods
      

      L'output è simile al seguente:

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

      Prendi nota del nome host di un pod del writer (esempio: writer-5465d65b46-7hxv4).

    2. Esegui questo comando per accedere al pod writer:

      kubectl exec -it WRITER_HOSTNAME -- /bin/sh
      
    3. Visualizza il componente condiviso nel file indexData.html:

      cd /html
      cat indexData.html
      
    4. Cancella il file indexData.html:

      echo '' > indexData.html
      

      Aggiorna il browser web che ospita l'indirizzo EXTERNAL-IP per visualizzare la modifica.

    5. Esci dall'ambiente:

      exit
      

    Esegui la pulizia

    Per evitare che al tuo Account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, elimina il progetto che contiene le risorse oppure mantieni il progetto ed elimina le singole risorse.

    Elimina il progetto

    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.

    Elimina le singole risorse

    1. Elimina il servizio del bilanciatore del carico:

      kubectl delete service reader-lb
      

      Attendi che il bilanciatore del carico di cui è stato eseguito il provisioning per il servizio di lettura venga eliminato.

    2. Verifica che l'elenco restituisca Listed 0 items:

      gcloud compute forwarding-rules list
      
    3. Elimina i deployment

      kubectl delete deployment writer
      kubectl delete deployment reader
      
    4. Verifica che i pod siano eliminati e restituisca No resources found in default namespace.

      kubectl get pods
      
    5. Elimina la PVC. Verranno eliminati anche il PV e l'istanza Filestore per via del criterio di conservazione impostato su delete

      kubectl delete pvc fileserver
      
    6. Elimina il cluster GKE:

      gcloud container clusters delete CLUSTER_NAME --location=CONTROL_PLANE_LOCATION
      

      Vengono eliminate le risorse che compongono il cluster GKE, inclusi i pod di lettore e writer.

    Passaggi successivi