O Cost Sentry é um conjunto de scripts e configurações que lhe permitem encerrar recursos quando os orçamentos de faturação do Google Cloud são excedidos.
Este script é composto pelos seguintes componentes :
- Eventos – Fila – Pub/Sub
- Faturação – Controlos de custos – Orçamentos
- Eventos – Processamento de eventos – Cloud Functions
- Computação – VMs – Compute Engine
- Computação – Sem servidor – Cloud Run
Este script vai configurar um orçamento, uma fila de mensagens e uma função do Google Cloud para gerir tudo isto. Em seguida, inicia uma VM de exemplo e um serviço suportado por contentores que é gerido pelo sistema.
Começar
Clique no seguinte link para aceder a uma cópia do código fonte no Cloud Shell. Quando estiver lá, um único comando vai iniciar uma cópia funcional da aplicação no seu projeto.
Componentes do Cost Sentry
A arquitetura do Cost Sentry usa vários produtos. A lista seguinte apresenta os componentes, juntamente com mais informações sobre os componentes, incluindo links para vídeos relacionados, documentação do produto e visitas guiadas interativas.Scripts
O script de instalação usa um executável escrito em go
e ferramentas da CLI do Terraform para
usar um projeto vazio e instalar a aplicação no mesmo. A saída deve ser uma aplicação funcional e um URL para o endereço IP de equilíbrio de carga.
./main.tf
Ative os serviços
Os serviços Google Cloud estão desativados num projeto por predefinição. Para usar o Cost Sentry, ative os seguintes serviços:
- Orçamentos de faturação: acompanhe a faturação e faça a gestão dos alertas de faturação.
- Cloud Build: crie imagens de contentores e implemente-as no Cloud Run.
- Compute Engine: implemente máquinas virtuais e serviços de rede, como o balanceamento de carga.
- Cloud Functions: responda a eventos da plataforma de serviços.
- Cloud Run: aloja contentores num ambiente sem servidor e fornece URLs para aceder à aplicação.
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
}
Crie um canal do Pub/Sub
Cria um canal do Pub/Sub para ouvir eventos de orçamentos de faturação e responder com as Cloud Functions
resource "google_pubsub_topic" "costsentry" {
name = "${var.basename}-billing-channel"
project = var.project_number
}
Crie um serviço do Cloud Run para aplicar
Crie um serviço do Cloud Run de exemplo no qual executar a aplicação da faturação.
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]
}
Crie uma instância de VM
Crie uma instância de exemplo do Compute Engine na qual executar a aplicação.
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]
}
Crie um orçamento
Cria um orçamento para monitorizar os gastos nos seus projetos.
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
}
Crie uma conta de serviço e defina autorizações
Cria uma conta de serviço para as chamadas da função do Google Cloud.
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
}
Defina autorizações
O comando seguinte define as funções e as autorizações da IAM que permitem ao Cloud Build implementar os serviços necessários.
A série de comandos implementa o seguinte: Concede autorização à conta de serviço da função do Cloud para gerir o Cloud Run. Concede autorização à conta de serviço da função do Cloud para parar instâncias do Compute Engine. Concede autorização à conta de serviço do Cloud Build para agir em nome da conta de serviço do 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]
}
Implemente uma função do Cloud
O comando seguinte implementa uma função do Cloud que desativa recursos quando é acionado um alerta.
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
]
}
Conclusão
Depois de executada, deve ter uma solução de controlo de custos em execução no seu projeto. Além disso, deve ter todo o código para modificar ou expandir esta solução de forma a adequar-se ao seu ambiente.