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