Esegui il deployment di un carico di lavoro stateful con Filestore


Questo tutorial mostra come eseguire il deployment di un semplice carico di lavoro stateful reader/writer utilizzando un volume permanente (PV) e una rivendicazione di volumi permanenti (PVC) su Google Kubernetes Engine (GKE). Segui questo tutorial per imparare a progettare per la scalabilità utilizzando Filestore, il file system di rete gestito di Google Cloud.

Contesto

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

In qualità di operatore applicativo, potresti voler mantenere carichi di lavoro stateful. Alcuni esempi di carichi di lavoro di questo tipo sono le applicazioni che elaborano gli articoli di WordPress, le app di messaggistica e le app che elaborano le operazioni di machine learning.

Utilizzando Filestore su GKE, puoi eseguire le seguenti operazioni:

  • Esegui il deployment di carichi di lavoro stateful scalabili.
  • Consentire 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.
  • Mantieni lo spazio di archiviazione quando i pod vengono rimossi.
  • Consenti ai pod di condividere dati e scalare facilmente.

Obiettivi

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

Diagramma GKE del carico di lavoro stateful

Questo tutorial illustra i seguenti passaggi:

  1. Creare un cluster GKE.
  2. Configura l'archiviazione gestita dei file 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. Amplia il ruolo dell'autore.
  6. Accedere 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 di continuare la fatturazione eliminando le risorse che hai creato. Per ulteriori informazioni, consulta Pulizia.


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

Guidami


Prima di iniziare

Configura il progetto

  1. Accedi al tuo account Google Cloud. Se non conosci Google Cloud, crea un account per valutare le prestazioni dei nostri prodotti in scenari reali. I nuovi clienti ricevono anche 300 $di crediti gratuiti per l'esecuzione, il test e il deployment dei carichi di lavoro.
  2. Nella pagina del selettore di progetti della console Google Cloud, fai clic su Crea progetto per iniziare a creare un nuovo progetto Google Cloud.

    Vai al selettore progetti

  3. Assicurati che la fatturazione sia attivata per il tuo progetto Google Cloud.

  4. Abilita le API Compute Engine, GKE, and Filestore.

    Abilita le API

  5. Nella pagina del selettore di progetti della console Google Cloud, fai clic su Crea progetto per iniziare a creare un nuovo progetto Google Cloud.

    Vai al selettore progetti

  6. Assicurati che la fatturazione sia attivata per il tuo progetto Google Cloud.

  7. Abilita le API Compute Engine, GKE, and Filestore.

    Abilita le API

Configura i valori predefiniti per Google Cloud CLI

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

  2. Scarica il codice sorgente per 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 denominato stateful-cluster:

    gcloud container clusters create-auto stateful-cluster --region COMPUTE_REGION
    

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

      gcloud container clusters describe stateful-cluster
      NAME: stateful-cluster
      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 per stateful-cluster.

Configura l'archiviazione gestita dei file con Filestore utilizzando CSI

GKE offre un modo per eseguire automaticamente il deployment e la gestione del driver CSI Filestore Filestore nei tuoi cluster. L'uso di Filestore CSI consente di creare o eliminare in modo dinamico le 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 esegua il provisioning dinamico di un'istanza Filestore e dell'oggetto PV o accedere alle istanze Filestore di cui è stato eseguito il pre-provisioning 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, quindi il provisioning del volume può iniziare immediatamente.
  • tier è impostato su standard per velocizzare la creazione dell'istanza Filestore. Se hai bisogno di un livello di spazio di archiviazione NFS disponibile più elevato, di snapshot per il backup dei dati, la replica dei dati su più zone e altre funzionalità di livello aziendale, imposta invece tier su enterprise. Nota: il criterio di recupero per l'oggetto PV creato dinamicamente è impostato su Delete se il reclaimPolicy in StorageClass non è impostato.
  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 pre-provisioning

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 il criterio volumeBindingMode è impostato su Immediate, il provisioning del volume può iniziare 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 volume permanente 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/<FILESTORE_ZONE>/<INSTANCE_NAME>/<FILESTORE_SHARE_NAME>"
    volumeAttributes:
      ip: <IP_ADDRESS> # Modify this to Pre-provisioned Filestore instance IP
      volume: <FILESTORE_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 di 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 sopra 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 l'oggetto PV

      kubectl apply -f preprov-pv.yaml
    
  5. Verifica che STATUS dell'oggetto PV sia impostato 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 manifest pvc.yaml fa riferimento al driver CSI Filestore StorageClass denominato filestore-sc.

Per avere più pod in lettura e scrittura sul 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 la PVC sia stata creata:

    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 di lettore e di scrittore

Crea il pod di lettore

Il pod di lettura leggerà il file che viene scritto dai pod degli autori. I pod del lettore vedranno a che ora e quale replica del pod dello scrittore ha scritto il 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 di lettore leggerà dal percorso /usr/share/nginx/html che è condiviso tra tutti i pod.

  1. Esegui il deployment del pod di lettura:

    kubectl apply -f reader-fs.yaml
    
  2. Verifica che le repliche dei lettori siano in esecuzione eseguendo 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 di scrittura scrive periodicamente su un file condiviso a cui possono accedere altri pod di scrittura e lettori. Il pod di scrittura registra la sua presenza scrivendo il nome host nel file condiviso.

L'immagine utilizzata per il pod dello scrittore è un'immagine personalizzata di Alpine Linux, che viene utilizzata per utilità e applicazioni di produzione. Include uno script indexInfo.html che otterrà i metadati dell'autore più recente e tiene il conteggio 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 dello scrittore scrive ogni 30 secondi sul percorso /html/index.html. Modifica il valore numerico sleep in modo che abbia una frequenza di scrittura diversa.

  1. Esegui il deployment del pod writer:

    kubectl apply -f writer-fs.yaml
    
  2. Verifica che i pod del writer siano in esecuzione eseguendo 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
    

Esponi e accedi al carico di lavoro dei lettori a un bilanciatore del carico dei servizi

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. Controlla 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 visualizzazione.

  4. Utilizza un browser web per accedere alla risorsa EXTERNAL-IP assegnata al bilanciatore del carico. La pagina viene aggiornata ogni 30 secondi. Maggiore è il numero di pod di scrittura e minore la frequenza, maggiore sarà il numero di voci che mostrerà.

Per ulteriori dettagli sul servizio bilanciatore del carico, vedi loadbalancer.yaml.

Fai lo scale up del writer

Poiché l'oggetto PV accessMode è stato impostato su ReadWriteMany, GKE può fare lo scale up del numero di pod in modo che più pod writer possano scrivere su questo volume condiviso (o più lettori possano leggere per leggerli).

  1. Fai lo scale up di writer fino 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 al EXTERNAL-IP assegnato al bilanciatore del carico.

A questo punto, hai configurato e scalato il cluster per supportare cinque pod di writer stateful. Quando più pod writer scrivono sullo stesso file contemporaneamente. Inoltre, è possibile fare facilmente lo scale up dei pod di lettura.

(Facoltativo) Accedere ai dati dal pod del writer

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

  1. Recupera il nome del pod dello scrittore:

    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 di scrittura (ad 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 vedere 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. Nella console Google Cloud, vai alla pagina Gestisci risorse.

    Vai a Gestisci risorse

  2. Nell'elenco dei progetti, seleziona il progetto che vuoi eliminare, quindi fai clic su Elimina.
  3. Nella finestra di dialogo, digita l'ID del progetto e fai clic su Chiudi per eliminare il progetto.

Elimina le singole risorse

  1. Elimina il servizio del bilanciatore del carico:

    kubectl delete service reader-lb
    

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

  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 stati 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 stateful-cluster --zone=COMPUTE_ZONE
    

    Questa operazione elimina le risorse che compongono il cluster GKE, inclusi i pod di lettore e autore.

Passaggi successivi