Cost Sentry

+

Architettura

Cost Sentry è un insieme di script e configurazioni che ti consente di spegnere le risorse quando i budget di fatturazione di Google Cloud vengono superati.

Questo script è costituito dai seguenti componenti :

  • Eventi - Coda - Pub/Sub
  • Fatturazione - Controllo dei costi - Budget
  • Eventi - Gestione eventi - Funzioni Cloud
  • Compute - VM - Compute Engine
  • Compute - Serverless - Cloud Run

Questo script configurerà un budget, una coda di messaggistica e una funzione Cloud per gestire tutto. Viene quindi avviata una VM di esempio e un servizio basato su container gestito dal sistema.


Inizia

Fai clic sul seguente link per una copia del codice sorgente in Cloud Shell. Una volta lì, un singolo comando avvierà una copia funzionante dell'applicazione nel tuo progetto.

Apri in Cloud Shell

Visualizza il codice sorgente su GitHub


Componenti di Cost Sentry

L'architettura di Cost Sentry utilizza diversi prodotti. Di seguito sono elencati i componenti, insieme a ulteriori informazioni su di essi, inclusi link a video correlati, documentazione del prodotto e walkthrough interattivi.
Video Documenti Procedure dettagliate
Google Cloud Pub/Sub Google Cloud Pub/Sub è un bus di messaggistica per l'integrazione di applicazioni su diversi servizi e componenti cloud in un sistema integrato.
Budget di fatturazione I budget di fatturazione ti consentono di ricevere notifiche e intervenire quando la fatturazione supera le soglie che hai impostato.
Cloud Functions Cloud Functions è una piattaforma Functions as a Service che ti consente di monitorare i caricamenti di file di Cloud Storage ed eseguire codice per crearne le miniature.
Compute Engine Compute Engine è la tecnologia virtuale di Google Cloud. Con questo strumento puoi avviare molte configurazioni diverse di VM per adattarle alle tue esigenze di calcolo.
Cloud Run Cloud Run ti consente di eseguire applicazioni in un contenitore, ma in modo serverless, senza dover configurare il numero di istanze, processori o memoria. Carica un contenitore, ricevi un URL.

Script

Lo script di installazione utilizza un file eseguibile scritto in go e gli strumenti Terraform CLI per prendere un progetto vuoto e installarvi l'applicazione. L'output deve essere un'applicazione funzionante e un URL per l'indirizzo IP del bilanciamento del carico.

./main.tf

Attiva i servizi

I servizi Google Cloud sono disabilitati in un progetto per impostazione predefinita. Per utilizzare Cost Sentry, attiva i seguenti servizi:

  • Budget di fatturazione: monitora la fatturazione e gestisci gli avvisi di fatturazione.
  • Cloud Build: crea immagini container ed esegui il deployment su Cloud Run.
  • Compute Engine: implementa macchine virtuali e servizi di rete, come il bilanciamento del carico.
  • Cloud Functions: rispondi agli eventi della piattaforma di servizi.
  • Cloud Run: ospita i container in un ambiente serverless e fornisce gli URL per accedere all'applicazione.
variable "gcp_service_list" {
        description = "The list of apis necessary for the project"
        type        = list(string)
        default = [
            "cloudresourcemanager.googleapis.com",
            "cloudbilling.googleapis.com",
            "billingbudgets.googleapis.com",
            "cloudbuild.googleapis.com",
            "compute.googleapis.com",
            "cloudfunctions.googleapis.com",
            "storage.googleapis.com",
            "run.googleapis.com"
        ]
}

resource "google_project_service" "all" {
    for_each           = toset(var.gcp_service_list)
    project            = var.project_number
    service            = each.key
    disable_on_destroy = false
}

Crea un canale Pub/Sub

Crea un canale Pub/Sub per ascoltare gli eventi del budget di fatturazione e rispondere con Cloud Functions

resource "google_pubsub_topic" "costsentry" {
    name = "${var.basename}-billing-channel"
    project    = var.project_number
}

Crea il servizio Cloud Run da applicare

Crea un servizio Cloud Run di esempio su cui eseguire l'applicazione della fatturazione.

resource "google_cloud_run_service" "app" {
    name     = "${var.basename}-run-service"
    location = var.region
    project  = var.project_id

    metadata {
        labels = {"${var.label}"=true}
    }

    template {
        spec {
            containers {
                image = "us-docker.pkg.dev/cloudrun/container/hello"
            }
        }

        metadata {
            annotations = {
                "autoscaling.knative.dev/maxScale" = "1000"
                "run.googleapis.com/client-name"   = "terraform"
            }
        }
    }
    autogenerate_revision_name = true
    depends_on = [google_project_service.all]
}

Crea istanza VM

Crea un'istanza Compute Engine di esempio su cui eseguire l'applicazione.

resource "google_compute_instance" "example" {
    name         = "${var.basename}-example"
    machine_type = "n1-standard-1"
    zone         = var.zone
    project      = var.project_id
    tags                    = ["http-server"]
    labels = {"${var.label}"=true}

    boot_disk {
        auto_delete = true
        device_name = "${var.basename}-example"
        initialize_params {
            image = "family/debian-10"
            size  = 200
            type  = "pd-standard"
        }
    }   

    network_interface {
        network = "default"
        access_config {
        // Ephemeral public IP
        }
    }

    depends_on = [google_project_service.all]
}

Crea un budget

Crea un budget per monitorare la spesa nei tuoi progetti.

provisioner "local-exec" {
    command = <<-EOT
    gcloud beta billing budgets create --display-name ${var.basename}-budget \
    --billing-account ${var.billing_account} --budget-amount ${var.budgetamount} \
    --all-updates-rule-pubsub-topic=projects/${var.project_id}/topics/${var.basename}-billing-channel
    EOT
}

Crea un account di servizio e imposta le autorizzazioni

Crea un account di servizio per le chiamate di Cloud Function.

resource "google_service_account" "functions_accounts" {
    account_id   = local.safunctionuser
    description  = "Service Account for the costsentry to run as"
    display_name = local.safunction
    project      = var.project_number
}

Imposta autorizzazioni

Il seguente comando imposta i ruoli e le autorizzazioni IAM che consentono a Cloud Build di eseguire il deployment dei servizi richiesti.

La serie di comandi implementa quanto segue: Concede all'account di servizio Cloud Function l'autorizzazione per gestire Cloud Run. Concede all'account di servizio Cloud Function l'autorizzazione per arrestare le istanze Compute Engine. Concede all'account di servizio Cloud Build l'autorizzazione ad agire per conto dell'account di servizio Compute.

variable "build_roles_list" {
        description = "The list of roles that fucntions needs for"
        type        = list(string)
        default = [
            "roles/run.admin",
            "roles/compute.instanceAdmin",
            "roles/iam.serviceAccountUser"
        ]
}

resource "google_project_iam_member" "allbuild" {
    for_each   = toset(var.build_roles_list)
    project    = var.project_number
    role       = each.key
    member     = "serviceAccount:${google_service_account.functions_accounts.email}"
    depends_on = [google_project_service.all,google_service_account.functions_accounts]
}

Esegui il deployment di una funzione Cloud Functions

Il comando seguente esegue il deployment di una funzione Cloud che disattiva le risorse quando viene attivato un avviso.

resource "google_storage_bucket" "function_bucket" {
    name     = "${var.project_id}-function-deployer"
    project  = var.project_number
    location = var.location
}

resource "null_resource" "cloudbuild_function" {
    provisioner "local-exec" {
        command = <<-EOT
        cp code/function/function.go .
        cp code/function/go.mod .
        zip index.zip function.go
        zip index.zip go.mod
        rm go.mod
        rm function.go
        EOT
    }

    depends_on = [
        google_project_service.all
    ]
}

resource "google_storage_bucket_object" "archive" {
    name   = "index.zip"
    bucket = google_storage_bucket.function_bucket.name
    source = "index.zip"
    depends_on = [
        google_project_service.all,
        google_storage_bucket.function_bucket,
        null_resource.cloudbuild_function
    ]
}

resource "google_cloudfunctions_function" "function" {
    name    = var.basename
    project = var.project_id
    region  = var.region
    runtime = "go116"
    service_account_email = google_service_account.functions_accounts.email
    available_memory_mb   = 128
    source_archive_bucket = google_storage_bucket.function_bucket.name
    source_archive_object = google_storage_bucket_object.archive.name
    entry_point           = "LimitUsage"
    event_trigger {
        event_type = "google.pubsub.topic.publish"
        resource   = google_pubsub_topic.costsentry.name
    }

    environment_variables = {
        GOOGLE_CLOUD_PROJECT = var.project_id
        LABEL= var.label
    }

    depends_on = [
        google_storage_bucket.function_bucket,
        google_storage_bucket_object.archive,
        google_project_service.all
    ]
}

Conclusione

Al termine dell'esecuzione, nel progetto dovrebbe essere in esecuzione una soluzione di controllo dei costi. Inoltre, dovresti disporre di tutto il codice per modificare o estendere questa soluzione in base al tuo ambiente.