Sentry dei costi

Architettura

Costo Sentry è un insieme di script e configurazioni che consentono di arrestare le risorse quando vengono superati i budget di fatturazione di Google Cloud.

Questo script è costituito dai seguenti componenti :

  • Eventi - Coda - Pub/Sub
  • Fatturazione - Controlli dei costi - Budget
  • Eventi - Gestione eventi - Cloud Functions
  • Computing - VM - Compute Engine
  • Computing - Serverless - Cloud Run

Questo script imposterà un budget, una coda di messaggi e una Cloud Function per gestire tutto questo. Quindi avvia una VM di esempio e un servizio supportato da container gestito dal sistema.


Inizia

Fai clic sul link seguente a una copia del codice sorgente in Cloud Shell. Da 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 Sentry costi

L'architettura di Cost Sentry utilizza diversi prodotti. Di seguito sono elencati i componenti, insieme a ulteriori informazioni sui componenti, tra cui link a video correlati, documentazione del prodotto e procedure dettagliate interattive.
Video Documenti Procedure dettagliate
Google Cloud Pub/Sub Google Cloud Pub/Sub è un bus di messaggistica per l'integrazione di applicazioni su servizi diversi su diversi 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 impostate.
Cloud Functions Cloud Functions è una piattaforma di servizi che consente di ascoltare i caricamenti di file di Cloud Storage ed eseguire il codice per crearne le miniature.
Compute Engine Compute Engine è la tecnologia virtuale di Google Cloud. Consente di avviare molte configurazioni diverse di VM per adattarsi alle tue esigenze di computing.
Cloud Run Cloud Run ti consente di eseguire applicazioni in un container, ma in modo serverless, senza dover configurare il numero di istanze, processori o memoria. Carica un contenitore, recupera un URL.

Script

Lo script di installazione utilizza un eseguibile scritto in go e negli strumenti dell'interfaccia a riga di comando di Terraform per acquisire un progetto vuoto e installare l'applicazione al suo interno. L'output deve essere un'applicazione funzionante e un URL per l'indirizzo IP di 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 in Cloud Run.
  • Compute Engine: implementa macchine virtuali e servizi di networking, come il bilanciamento del carico.
  • Cloud Functions: risposta agli eventi della piattaforma di servizio.
  • 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 canale Pub/Sub

Crea un canale Pub/Sub per rimanere in ascolto degli eventi relativi al 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 per l'applicazione forzata

Crea un servizio Cloud Run di esempio su cui eseguire l'applicazione forzata 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 forzata.

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 relativa ai 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 alla 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 Functions l'autorizzazione per gestire Cloud Run. Concede all'account di servizio della funzione Cloud l'autorizzazione per arrestare le istanze di 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 seguente comando esegue il deployment di una Cloud Function 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

Una volta eseguita, dovresti avere una soluzione di controllo dei costi in esecuzione nel tuo progetto. Inoltre, dovresti disporre di tutto il codice per modificare o estendere questa soluzione in modo che si adatti al tuo ambiente.