Automazione delle ottimizzazioni dei costi con Cloud Functions, Cloud Scheduler e Cloud Monitoring


Questo documento mostra come utilizzare Cloud Functions per identificare e ripulire le risorse cloud sprecate, pianificare le funzioni da eseguire con Cloud Scheduler e utilizzare i criteri di avviso di Cloud Monitoring per eseguirle in base all'utilizzo osservato. Questo documento è rivolto a sviluppatori, SRE, Cloud Architect e amministratori di infrastrutture cloud che cercano un approccio sistematico e automatizzato per identificare e ridurre gli sprechi di spesa per il cloud.

Questo documento presuppone la conoscenza di quanto segue:

Obiettivi

  • Elimina gli indirizzi IP inutilizzati: su Google Cloud, gli indirizzi IP statici sono una risorsa gratuita quando sono collegati a un bilanciatore del carico o a un'istanza di macchina virtuale (VM). Quando un indirizzo IP statico viene prenotato, ma non utilizzato, accumula un addebito orario. Nelle app che dipendono in larga misura da indirizzi IP statici e provisioning dinamico su larga scala, questi sprechi possono diventare significativi nel tempo.
  • Elimina i dischi permanenti orfani o non utilizzati: i dischi permanenti non sono utilizzati o se sono orfani se vengono creati senza essere mai collegati a una VM o se una macchina ha più dischi e uno o più dischi sono scollegati.
  • Esegui la migrazione a classi di archiviazione meno costose: Google Cloud offre diverse classi di archiviazione di oggetti. Usa il corso più adatto alle tue esigenze.

Architettura

Il seguente diagramma descrive la prima parte del deployment, in cui pianifichi una Cloud Function per identificare e ripulire gli indirizzi IP inutilizzati.

Architettura di una Cloud Function che identifica ed esegue la pulizia degli indirizzi IP inutilizzati.

Il primo esempio riguarda quanto segue:

  • Creazione di una VM Compute Engine con un indirizzo IP esterno statico e un indirizzo IP esterno statico inutilizzato separato.
  • Deployment di una Cloud Function per identificare gli indirizzi inutilizzati.
  • Creazione di un job Cloud Scheduler per pianificare l'esecuzione della funzione mediante un trigger HTTP.

Nel diagramma seguente, pianifichi una Cloud Function per identificare e ripulire i dischi permanenti non collegati e orfani.

Architettura di una Cloud Function che identifica ed esegue la pulizia dei dischi permanenti inutilizzati.

Il secondo esempio riguarda quanto segue:

  • Creazione di una VM Compute Engine con due dischi permanenti e un disco permanente separato separato. Uno dei dischi è orfano poiché viene scollegato dalla VM.
  • Deployment di una Cloud Function per identificare dischi permanenti non collegati e orfani.
  • Creazione di un job Cloud Scheduler per pianificare l'esecuzione della Cloud Function mediante un trigger HTTP.

Nel diagramma seguente, attiverai una Cloud Function per eseguire la migrazione di un bucket di archiviazione a una classe di archiviazione meno costosa da un criterio di avviso di Monitoring.

Architettura di una Cloud Function che esegue la migrazione di un bucket di archiviazione.

Il terzo esempio riguarda quanto segue:

  • Creazione di due bucket di archiviazione, aggiunta di un file al bucket di pubblicazione e generazione di traffico.
  • Creazione di una dashboard di Monitoring per visualizzare l'utilizzo del bucket.
  • Deployment di una Cloud Function per eseguire la migrazione del bucket inattivo a una classe di archiviazione meno costosa.
  • Attivare la funzione utilizzando un payload destinato a simulare una notifica ricevuta da un criterio di avviso di Monitoring.

Costi

In questo documento vengono utilizzati i seguenti componenti fatturabili di Google Cloud:

Per generare una stima dei costi in base all'utilizzo previsto, utilizza il Calcolatore prezzi. I nuovi utenti di Google Cloud possono essere idonei a una prova senza costi aggiuntivi.

Una volta completate le attività descritte in questo documento, puoi evitare la fatturazione continua eliminando le risorse che hai creato. Per ulteriori informazioni, consulta la pagina Pulizia.

Prima di iniziare

  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, seleziona o crea un 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, Cloud Functions, and Cloud Storage.

    Abilita le API

  5. Nella pagina del selettore di progetti della console Google Cloud, seleziona o crea un 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, Cloud Functions, and Cloud Storage.

    Abilita le API

  8. Nella console Google Cloud, attiva Cloud Shell.

    Attiva Cloud Shell

    Nella parte inferiore della console Google Cloud viene avviata una sessione di Cloud Shell che mostra un prompt della riga di comando. Cloud Shell è un ambiente shell con Google Cloud CLI già installato e con valori già impostati per il progetto attuale. L'inizializzazione della sessione può richiedere alcuni secondi.

  9. Esegui tutti i comandi in questo documento da Cloud Shell.

Configurazione dell'ambiente

In questa sezione configurerai l'infrastruttura e le identità necessarie per questa architettura.

  1. In Cloud Shell, clona il repository e passa alla directory gcf-automated-resource-cleanup:

    git clone https://github.com/GoogleCloudPlatform/gcf-automated-resource-cleanup.git && cd gcf-automated-resource-cleanup/
    
  2. Imposta le variabili di ambiente e imposta la cartella del repository come la tua cartella $WORKDIR, dove esegui tutti i comandi:

    export PROJECT_ID=$(gcloud config list \
        --format 'value(core.project)' 2>/dev/null)
        WORKDIR=$(pwd)
    
  3. Installa Apache Bench, uno strumento open source di generazione del carico:

    sudo apt-get install apache2-utils
    

Pulizia degli indirizzi IP inutilizzati

In questa sezione, devi completare i seguenti passaggi:

  • Crea due indirizzi IP statici.
  • Creare una VM che utilizza un indirizzo IP statico.
  • Esamina il codice di Cloud Functions.
  • Eseguire il deployment della Cloud Function.
  • Testa la Cloud Function utilizzando i job Cloud Scheduler.

Crea indirizzi IP

  1. In Cloud Shell, passa alla directory unused-ip:

    cd $WORKDIR/unused-ip
    
  2. Esporta i nomi degli indirizzi IP come variabili:

    export USED_IP=used-ip-address
    export UNUSED_IP=unused-ip-address
    
  3. Crea due indirizzi IP statici:

    gcloud compute addresses create $USED_IP \
        --project=$PROJECT_ID --region=us-central1
    gcloud compute addresses create $UNUSED_IP \
        --project=$PROJECT_ID --region=us-central1
    

    Questo esempio utilizza la regione us-central1, ma puoi scegliere una regione diversa e farvi riferimento in modo coerente nel resto del documento.

  4. Conferma che sono stati creati due indirizzi:

    gcloud compute addresses list --filter="region:(us-central1)"
    

    Nell'output, lo stato RESERVED significa che gli indirizzi IP non sono in uso:

    NAME               ADDRESS/RANGE  TYPE      REGION       SUBNET  STATUS
    unused-ip-address  35.232.144.85  EXTERNAL  us-central1          RESERVED
    used-ip-address    104.197.56.87  EXTERNAL  us-central1          RESERVED
    
  5. Imposta l'indirizzo IP utilizzato come variabile di ambiente:

    export USED_IP_ADDRESS=$(gcloud compute addresses describe $USED_IP \
        --region=us-central1 --format=json | jq -r '.address')
    

Crea una VM

  1. In Cloud Shell, crea un'istanza:

    gcloud compute instances create static-ip-instance \
        --zone=us-central1-a \
        --machine-type=n1-standard-1 \
        --subnet=default \
        --address=$USED_IP_ADDRESS
    
  2. Conferma che uno degli indirizzi IP sia ora in uso:

    gcloud compute addresses list --filter="region:(us-central1)"
    

    L'output è simile al seguente:

    NAME               ADDRESS/RANGE  TYPE      REGION       SUBNET  STATUS
    unused-ip-address  35.232.144.85  EXTERNAL  us-central1          RESERVED
    used-ip-address    104.197.56.87  EXTERNAL  us-central1          IN_USE
    

Esamina il codice della Cloud Function

  • In Cloud Shell, genera la sezione principale del codice:

    cat $WORKDIR/unused-ip/function.js | grep "const compute" -A 31
    

    L'output è il seguente:

    const compute = new Compute();
    compute.getAddresses(function(err, addresses){ // gets all addresses across regions
         if(err){
             console.log("there was an error: " + err);
         }
         if (addresses == null) {
             console.log("no addresses found");
             return;
         }
         console.log("there are " + addresses.length + " addresses");
    
         // iterate through addresses
         for (let item of addresses){
    
              // get metadata for each address
              item.getMetadata(function(err, metadata, apiResponse) {
    
                  // if the address is not used AND if it's at least ageToDelete days old:
                  if ((metadata.status=='RESERVED') & (calculateAge(metadata.creationTimestamp) >= ageToDelete)){
                      // delete address
                      item.delete(function(err, operation, apiResponse2){
                          if (err) {
                              console.log("could not delete address: " + err);
                          }
                      })
                  }
              })
          }
           // return number of addresses evaluated
          res.send("there are " + addresses.length + " total addresses");
      });
    }
    

    Nell'esempio di codice precedente, presta attenzione a quanto segue:

    • compute.getAddresses(function(err, addresses){ // gets all addresses across regions
      

      Utilizza il metodo getAddresses per recuperare gli indirizzi IP in tutte le regioni nel progetto.

    • // get metadata for each address
      item.getMetadata(function(err, metadata, apiResponse) {
         // if the address is not used:
             if (metadata.status=='RESERVED'){
      

      Recupera i metadati per ogni indirizzo IP e controlla il relativo campo STATUS.

    • if ((metadata.status=='RESERVED') &
      (calculateAge(metadata.creationTimestamp) >= ageToDelete)){
      

      Controlla se l'indirizzo IP è in uso, calcola la sua età utilizzando una funzione helper e confronta la sua età con una costante (impostata su 0 ai fini dell'esempio).

    • // delete address
      item.delete(function(err, operation, apiResponse2){
      

      Elimina l'indirizzo IP.

Esegui il deployment della Cloud Function

  1. In Cloud Shell, esegui il deployment della Cloud Function:

    gcloud functions deploy unused_ip_function --trigger-http --runtime=nodejs8
    
  2. Imposta l'URL del trigger come variabile di ambiente:

    export FUNCTION_URL=$(gcloud functions describe unused_ip_function \
        --format=json | jq -r '.httpsTrigger.url')
    

Pianifica e testa la Cloud Function

  1. In Cloud Shell, crea un'attività Cloud Scheduler per eseguire la Cloud Function ogni giorno alle 02:00:

    gcloud scheduler jobs create http unused-ip-job \
        --schedule="* 2 * * *" \
        --uri=$FUNCTION_URL
    
  2. Testa il job attivandolo manualmente:

    gcloud scheduler jobs run unused-ip-job
    
  3. Verifica che l'indirizzo IP inutilizzato sia stato eliminato:

    gcloud compute addresses list --filter="region:(us-central1)"
    

    L'output è simile al seguente:

    NAME             ADDRESS/RANGE  TYPE      REGION       SUBNET  STATUS
    used-ip-address  104.197.56.87  EXTERNAL  us-central1          IN_USE
    

Pulizia dei dischi permanenti inutilizzati e orfani

In questa sezione, devi completare i seguenti passaggi:

  • Creare due dischi permanenti.
  • Creare una VM che utilizza uno dei dischi.
  • Scollega il disco dalla VM.
  • Esamina il codice della Cloud Function.
  • Eseguire il deployment della Cloud Function.
  • Testa la Cloud Function utilizzando i job Cloud Scheduler.

Creazione di dischi permanenti

  1. In Cloud Shell, passa alla directory unattached-pd:

    cd $WORKDIR/unattached-pd
    
  2. Esporta i nomi dei dischi come variabili di ambiente:

    export ORPHANED_DISK=orphaned-disk
    export UNUSED_DISK=unused-disk
    
  3. Crea i due dischi:

    gcloud beta compute disks create $ORPHANED_DISK \
       --project=$PROJECT_ID \
       --type=pd-standard \
       --size=500GB \
       --zone=us-central1-a
    gcloud beta compute disks create $UNUSED_DISK \
        --project=$PROJECT_ID \
        --type=pd-standard \
        --size=500GB \
        --zone=us-central1-a
    
  4. Conferma che i due dischi siano stati creati:

    gcloud compute disks list
    

    L'output è il seguente:

    NAME                LOCATION       LOCATION_SCOPE SIZE_GB TYPE         STATUS
    orphaned-disk       us-central1-a  zone           500     pd-standard  READY
    static-ip-instance  us-central1-a  zone           10      pd-standard  READY
    unused-disk         us-central1-a  zone           500     pd-standard  READY
    

crea una VM ed esamina i dischi

  1. In Cloud Shell, crea l'istanza:

    gcloud compute instances create disk-instance \
        --zone=us-central1-a \
        --machine-type=n1-standard-1 \
        --disk=name=$ORPHANED_DISK,device-name=$ORPHANED_DISK,mode=rw,boot=no
    
  2. Controlla il disco collegato alla VM:

    gcloud compute disks describe $ORPHANED_DISK \
        --zone=us-central1-a \
        --format=json | jq
    

    L'output è simile al seguente:

    {
      "creationTimestamp": "2019-06-12T12:21:25.546-07:00",
      "id": "7617542552306904666",
      "kind": "compute#disk",
      "labelFingerprint": "42WmSpB8rSM=",
      "lastAttachTimestamp": "2019-06-12T12:24:53.989-07:00",
      "name": "orphaned-disk",
      "physicalBlockSizeBytes": "4096",
      "selfLink": "https://www.googleapis.com/compute/v1/projects/automating-cost-optimization/zones/us-central1-a/disks/orphaned-disk",
      "sizeGb": "500",
      "status": "READY",
      "type": "https://www.googleapis.com/compute/v1/projects/automating-cost-optimization/zones/us-central1-a/diskTypes/pd-standard",
      "users": [
        "https://www.googleapis.com/compute/v1/projects/automating-cost-optimization/zones/us-central1-a/instances/disk-instance"
      ],
      "zone": "https://www.googleapis.com/compute/v1/projects/automating-cost-optimization/zones/us-central1-a"
    }
    

    Nell'esempio di codice precedente, presta attenzione a quanto segue:

    • users identifica la VM a cui è collegato il disco.
    • lastAttachTimestamp identifica quando il disco è stato collegato per l'ultima volta a una VM.
  3. Controlla il disco che non è stato collegato a una VM:

    gcloud compute disks describe $UNUSED_DISK \
        --zone=us-central1-a \
        --format=json | jq
    

    L'output è simile al seguente:

    {
      "creationTimestamp": "2019-06-12T12:21:30.905-07:00",
      "id": "1313096191791918677",
      "kind": "compute#disk",
      "labelFingerprint": "42WmSpB8rSM=",
      "name": "unused-disk",
      "physicalBlockSizeBytes": "4096",
      "selfLink": "https://www.googleapis.com/compute/v1/projects/automating-cost-optimization/zones/us-central1-a/disks/unused-disk",
      "sizeGb": "500",
      "status": "READY",
      "type": "https://www.googleapis.com/compute/v1/projects/automating-cost-optimization/zones/us-central1-a/diskTypes/pd-standard",
      "zone": "https://www.googleapis.com/compute/v1/projects/automating-cost-optimization/zones/us-central1-a"
    }
    

    Nell'esempio di codice precedente, è importante quanto segue:

    • Il disco non contiene users perché non è attualmente utilizzato da una VM.
    • Il disco non contiene lastAttachedTimestamp perché non è mai stato utilizzato.
  4. Scollega il disco permanente orfano dalla VM:

    gcloud compute instances detach-disk disk-instance \
        --device-name=$ORPHANED_DISK \
        --zone=us-central1-a
    
  5. Ispeziona il disco orfano:

    gcloud compute disks describe $ORPHANED_DISK \
        --zone=us-central1-a \
        --format=json | jq
    

    L'output è simile al seguente:

    {
      "creationTimestamp": "2019-06-12T12:21:25.546-07:00",
      "id": "7617542552306904666",
      "kind": "compute#disk",
      "labelFingerprint": "42WmSpB8rSM=",
      "lastAttachTimestamp": "2019-06-12T12:24:53.989-07:00",
      "lastDetachTimestamp": "2019-06-12T12:34:56.040-07:00",
      "name": "orphaned-disk",
      "physicalBlockSizeBytes": "4096",
      "selfLink": "https://www.googleapis.com/compute/v1/projects/automating-cost-optimization/zones/us-central1-a/disks/orphaned-disk",
      "sizeGb": "500",
      "status": "READY",
      "type": "https://www.googleapis.com/compute/v1/projects/automating-cost-optimization/zones/us-central1-a/diskTypes/pd-standard",
      "zone": "https://www.googleapis.com/compute/v1/projects/automating-cost-optimization/zones/us-central1-a"
    }
    

    Nell'esempio di codice precedente, è importante quanto segue:

    • Il disco non riporta users, il che indica che non è attualmente in uso.
    • Ora è presente una voce lastDetachTimestamp, che indica quando il disco è stato ultimo scollegato da una VM e, pertanto, quando è stato l'ultimo utilizzo.
    • Il campo lastAttachTimestamp è ancora presente.

Esamina il codice della Cloud Function

  1. In Cloud Shell, genera la sezione di codice che recupera tutti i dischi permanenti nel progetto:

    cat $WORKDIR/unattached-pd/main.py | grep "(request)" -A 12
    

    L'output è il seguente:

    def delete_unattached_pds(request):
        # get list of disks and iterate through it:
        disksRequest = compute.disks().aggregatedList(project=project)
        while disksRequest is not None:
            diskResponse = disksRequest.execute()
            for name, disks_scoped_list in diskResponse['items'].items():
                if disks_scoped_list.get('warning') is None:
                    # got disks
                    for disk in disks_scoped_list['disks']: # iterate through disks
                        diskName = disk['name']
                        diskZone = str((disk['zone'])).rsplit('/',1)[1]
                        print (diskName)
                        print (diskZone)
    

    La funzione utilizza il metodo aggregatedList per recuperare tutti i dischi permanenti nel progetto Google Cloud in cui è in esecuzione ed esegue l'iterazione attraverso ciascuno dei dischi.

  2. Genera la sezione del codice che controlla il campo lastAttachTimestamp ed elimina il disco se non esiste:

    cat $WORKDIR/unattached-pd/main.py | grep "handle never" -A 11
    

    L'output è il seguente:

    # handle never attached disk - delete it
    # lastAttachedTimestamp is not present
    if disk.get("lastAttachTimestamp") is None:
           print ("disk " + diskName + " was never attached - deleting")
           deleteRequest = compute.disks().delete(project=project,
                  zone=diskZone,
                  disk=diskName)
           deleteResponse = deleteRequest.execute()
           waitForZoneOperation(deleteResponse, project, diskZone)
           print ("disk " + diskName + " was deleted")
           Continue
    

    Questa sezione elimina il disco se lastAttachTimestamp non è presente, il che significa che il disco non è mai stato in uso.

  3. Genera la sezione del codice che calcola l'età del disco se è orfano, crea uno snapshot del disco e poi lo elimina:

    cat $WORKDIR/unattached-pd/main.py | grep "handle detached" -A 32
    

    L'output è il seguente:

    # handle detached disk - snapshot and delete
    # lastAttachTimestamp is present AND users is not present AND it meets the age criterium
    if disk.get("users") is None \
        and disk.get("lastDetachTimestamp") is not None \
        and diskAge(disk['lastDetachTimestamp'])>=deleteAge:
    
        print ("disk " + diskName + " has no users and has been detached")
        print ("disk meets age criteria for deletion")
    
        # take a snapshot
        snapShotName = diskName + str(int(time.time()))
        print ("taking snapshot: " + snapShotName)
        snapshotBody = {
            "name": snapShotName
        }
        snapshotRequest = compute.disks().createSnapshot(project=project,
             zone=diskZone,
             disk=diskName,
             body=snapshotBody)
        snapshotResponse = snapshotRequest.execute()
        waitForZoneOperation(snapshotResponse, project, diskZone)
        print ("snapshot completed")
    
        # delete the disk
        print ("deleting disk " + diskName)
        deleteRequest = compute.disks().delete(project=project,
            zone=diskZone,
            disk=diskName)
        deleteResponse = deleteRequest.execute()
        waitForZoneOperation(deleteResponse, project, diskZone)
        print ("disk " + diskName + " was deleted")
        continue
    

    Questa sezione di codice viene utilizzata quando il disco contiene users ed è presente lastDetachTimestamp, il che significa che il disco non è attualmente in uso, ma è stato utilizzato in un secondo momento. In questo caso, la Cloud Function crea uno snapshot del disco per conservare i dati, quindi lo elimina.

Esegui il deployment della Cloud Function

  1. In Cloud Shell, esegui il deployment della Cloud Function:

    gcloud functions deploy delete_unattached_pds \
        --trigger-http --runtime=python37
    
  2. Imposta l'URL di trigger della Cloud Function come variabile di ambiente:

    export FUNCTION_URL=$(gcloud functions describe delete_unattached_pds \
        --format=json | jq -r '.httpsTrigger.url')
    

Pianifica e testa la Cloud Function

  1. In Cloud Shell, crea un'attività Cloud Scheduler per eseguire la Cloud Function ogni giorno alle 02:00:

    gcloud scheduler jobs create http unattached-pd-job \
        --schedule="* 2 * * *" \
        --uri=$FUNCTION_URL
    
  2. Testa il job:

    gcloud scheduler jobs run unattached-pd-job
    
  3. Verifica che sia stato creato uno snapshot del disco orfano:

    gcloud compute snapshots list
    

    L'output è simile al seguente:

    NAME                     DISK_SIZE_GB  SRC_DISK                           STATUS
    orphaned-disk1560455894  500           us-central1-a/disks/orphaned-disk  READY
    
  4. Verifica che il disco inutilizzato e quello orfano siano stati eliminati:

    gcloud compute disks list
    

    L'output è il seguente:

    NAME                LOCATION       LOCATION_SCOPE SIZE_GB  TYPE         STATUS
    disk-instance       us-central1-a  zone           10       pd-standard  READY
    static-ip-instance  us-central1-a  zone           10       pd-standard  READY
    

Migrazione dei bucket di archiviazione a classi di archiviazione meno costose

Google Cloud fornisce regole del ciclo di vita degli oggetti di archiviazione che puoi utilizzare per spostare automaticamente gli oggetti in classi di archiviazione diverse in base a un insieme di attributi, come la data di creazione o lo stato attivo. Tuttavia, queste regole non sanno se è stato eseguito l'accesso agli oggetti. A volte potresti voler spostare gli oggetti più recenti in Nearline Storage se non sono stati consultati per un determinato periodo di tempo.

In questa sezione, devi completare i seguenti passaggi:

  • Creare due bucket Cloud Storage.
  • Aggiungi un oggetto a uno dei bucket.
  • Configura Monitoring per osservare l'accesso agli oggetti del bucket.
  • Esamina il codice della Cloud Function che esegue la migrazione degli oggetti da un bucket Regional Storage a un bucket Nearline Storage.
  • Eseguire il deployment della Cloud Function.
  • Testa la Cloud Function utilizzando un avviso di Monitoring.

Creare bucket Cloud Storage e aggiungere un file

  1. In Cloud Shell, passa alla directory migrate-storage:

    cd $WORKDIR/migrate-storage
    
  2. Crea il bucket Cloud Storage serving-bucket che verrà utilizzato in seguito per modificare le classi di archiviazione:

    export PROJECT_ID=$(gcloud config list \
        --format 'value(core.project)' 2>/dev/null)
    gsutil mb -c regional -l us-central1 gs://${PROJECT_ID}-serving-bucket
    
  3. Rendi pubblico il bucket:

    gsutil acl ch -u allUsers:R gs://${PROJECT_ID}-serving-bucket
    
  4. Aggiungi un file di testo al bucket:

    gsutil cp $WORKDIR/migrate-storage/testfile.txt  \
        gs://${PROJECT_ID}-serving-bucket
    
  5. Rendi il file pubblico:

    gsutil acl ch -u allUsers:R gs://${PROJECT_ID}-serving-bucket/testfile.txt
    
  6. Verifica di poter accedere al file:

    curl http://storage.googleapis.com/${PROJECT_ID}-serving-bucket/testfile.txt
    

    L'output è il seguente:

    this is a test
    
  7. Crea un secondo bucket denominato idle-bucket che non gestisce dati:

    gsutil mb -c regional -l us-central1 gs://${PROJECT_ID}-idle-bucket
    

configura un'area di lavoro di Cloud Monitoring

In questa sezione configurerai Cloud Monitoring per osservare l'utilizzo dei bucket e capire quando non vengono utilizzati gli oggetti bucket. Quando il bucket di pubblicazione non viene utilizzato, una Cloud Function esegue la migrazione del bucket dalla classe Regional Storage alla classe Nearline Storage.

  1. Nella console Google Cloud, vai a Monitoring.

    Vai a Cloud Monitoring

  2. Fai clic su Nuova area di lavoro e poi su Aggiungi.

    Attendi il completamento della configurazione iniziale.

crea una dashboard di Cloud Monitoring

  1. In Monitoring, vai a Dashboard, quindi fai clic su Crea dashboard.

  2. Fai clic su Aggiungi grafico.

  3. Nel campo Nome, inserisci Bucket Access.

  4. Per trovare la metrica dei contenuti delle richieste per il bucket Cloud Storage, nel campo Trova risorsa e metrica inserisci request, quindi seleziona la metrica Conteggio richieste per la risorsa gcs_bucket.

  5. Per raggruppare le metriche in base al nome del bucket, nell'elenco a discesa Raggruppa per, fai clic su bucket_name.

  6. Per filtrare in base al nome del metodo, nel campo Filter (Filtro), inserisci ReadObject, quindi fai clic su Applica.

  7. Fai clic su Salva.

  8. Nel campo del nome, inserisci Bucket Usage.

  9. Per confermare che la dashboard è accessibile, tieni premuto il puntatore del mouse su Dashboard e verifica che venga visualizzato Utilizzo bucket.

    Hai configurato Monitoring per osservare l'accesso agli oggetti nei bucket. Il grafico non mostra dati perché non c'è traffico verso i bucket Cloud Storage.

Genera carico sul bucket di pubblicazione

Ora che il monitoraggio è configurato, utilizza Apache Bench per inviare il traffico al bucket di pubblicazione.

  1. In Cloud Shell, invia richieste all'oggetto nel bucket di gestione:

    ab -n 10000 \
        http://storage.googleapis.com/$PROJECT_ID-serving-bucket/testfile.txt
    
  2. Nella console Google Cloud, vai a Monitoring.

    Vai a Cloud Monitoring

  3. Per selezionare la dashboard Utilizzo bucket, tieni il puntatore del mouse su Dashboard e seleziona Utilizzo bucket. Conferma che ci sia traffico solo verso il bucket di pubblicazione. La serie temporale request_count metric viene visualizzata solo per il bucket di pubblicazione, perché il bucket inattivo non ha alcun traffico verso il bucket.

Rivedi ed esegui il deployment della Cloud Function

  1. In Cloud Shell, genera il codice che utilizza la Cloud Function per eseguire la migrazione di un bucket di archiviazione nella classe Nearline Storage:

    cat $WORKDIR/migrate-storage/main.py | grep "migrate_storage(" -A 15
    

    L'output è il seguente:

    def migrate_storage(request):
        # process incoming request to get the bucket to be migrated:
        request_json = request.get_json(force=True)
        # bucket names are globally unique
        bucket_name = request_json['incident']['resource_name']
    
        # create storage client
        storage_client = storage.Client()
    
        # get bucket
        bucket = storage_client.get_bucket(bucket_name)
    
        # update storage class
        bucket.storage_class = "NEARLINE"
        bucket.patch()
    

    La funzione Cloud Functions utilizza il nome del bucket passato nella richiesta per modificare la classe di archiviazione in Nearline Storage.

  2. Esegui il deployment della Cloud Function:

    gcloud functions deploy migrate_storage --trigger-http --runtime=python37
    
  3. Imposta l'URL del trigger come variabile di ambiente da utilizzare nella sezione successiva:

    export FUNCTION_URL=$(gcloud functions describe migrate_storage \
        --format=json | jq -r '.httpsTrigger.url')
    

Testare e convalidare l'automazione degli avvisi

  1. Imposta il nome del bucket inattivo:

    export IDLE_BUCKET_NAME=$PROJECT_ID-idle-bucket
    
  2. Invia una notifica di test alla Cloud Function di cui hai eseguito il deployment utilizzando il file incident.json:

    envsubst < $WORKDIR/migrate-storage/incident.json | curl -X POST \
        -H "Content-Type: application/json" $FUNCTION_URL -d @-
    

    L'output è il seguente:

    OK
    

    L'output non viene terminato con una nuova riga e quindi è immediatamente seguito dal prompt dei comandi.

  3. Verifica che sia stata eseguita la migrazione del bucket inattivo su Nearline Storage:

    gsutil defstorageclass get gs://$PROJECT_ID-idle-bucket
    

    L'output è il seguente:

    gs://automating-cost-optimization-idle-bucket: NEARLINE
    

Considerazioni relative a un ambiente di produzione

Quando automatizzi le ottimizzazioni dei costi nel tuo ambiente Google Cloud, prendi in considerazione quanto segue:

  • Considerazioni generali: ti consigliamo di aumentare la sicurezza per le funzioni Cloud Functions che possono modificare o eliminare le risorse Google Cloud.
  • Identificazione degli sprechi: questo documento descrive alcuni esempi di spese inutili. Esistono molti altri esempi che generalmente rientrano in una delle tre categorie seguenti:
    • Risorse con overprovisioning: le risorse di cui è stato eseguito il provisioning in modo che siano superiori al necessario per un determinato carico di lavoro, ad esempio le VM con più potenza e memoria della CPU del necessario.
    • Risorse inattive: risorse completamente inutilizzate.
    • Risorse inattive part-time: risorse utilizzate solo durante l'orario di lavoro.
  • Pulizia automatica: in questo documento era necessario un processo in più passaggi con più operazioni asincrone per creare uno snapshot ed eliminare il disco. Altre risorse Google Cloud, come gli indirizzi IP inutilizzati, possono utilizzare le operazioni sincrone.
  • Deployment su larga scala: in questo documento, l'ID progetto Google Cloud è definito nel codice della funzione Cloud Function. Per eseguire il deployment di una soluzione di questo tipo su larga scala, puoi utilizzare l'API fatturazione Cloud o Cloud Resource Manager per ottenere l'elenco dei progetti con un account di fatturazione o un'organizzazione. Poi, passa gli ID progetto Google Cloud come variabili a una funzione. In una configurazione di questo tipo, devi aggiungere l'account di servizio della Cloud Function ai progetti in cui può eseguire la pulizia o eliminare risorse. Ti consigliamo di utilizzare un framework di deployment automatizzato, come Cloud Deployment Manager o Terraform.
  • Automazione degli avvisi: questo documento mostra come utilizzare un payload fittizio di un avviso di Monitoring per attivare la migrazione della classe di archiviazione. I criteri di avviso di monitoraggio possono essere valutati per un massimo di 23 ore e 59 minuti. In un ambiente di produzione, questa limitazione potrebbe non essere abbastanza lunga da considerare un bucket inattivo prima di eseguire la migrazione della sua classe di archiviazione. Valuta la possibilità di abilitare gli audit log di accesso ai dati nel bucket Cloud Storage e di creare una pipeline che utilizzi questi audit log per valutare se un bucket è stato utilizzato per la gestione negli ultimi 30 giorni. Per ulteriori informazioni, consulta Comprendere gli audit log e valuta la possibilità di creare un sink aggregato per inviare i log a Pub/Sub e una pipeline Dataflow per elaborarli.

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.

Passaggi successivi