Análise de custo é um conjunto de scripts e configurações que permitem encerrar recursos quando os orçamentos do Google Cloud Billing são excedidos.
Esse script é composto pelos seguintes componentes :
- Eventos: fila - Pub/Sub
- Faturamento - Controles de custo - 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 Cloud para gerenciar tudo isso. Em seguida, ele ativa uma VM de amostra e um serviço com suporte de contêiner gerenciado pelo sistema.
Comece já
Clique no link a seguir para copiar o código-fonte no Cloud Shell. Depois, um único comando ativará uma cópia de trabalho do aplicativo no seu projeto.
Ver código-fonte no GitHub (em inglês)
Componentes da Sentry de custo
A arquitetura Cost Sentry usa vários produtos. Veja a seguir os componentes e mais informações sobre eles, incluindo links para vídeos relacionados, documentação do produto e tutoriais interativos.Scripts
O script de instalação usa um executável escrito em go
e ferramentas da CLI do Terraform para
pegar um projeto vazio e instalar o aplicativo nele. A saída será um aplicativo em funcionamento e um URL para o endereço IP de balanceamento de carga.
./main.tf
Ativar serviços
Os serviços do Google Cloud são desativados em um projeto por padrão. Para usar o Cost Sentry, ative os seguintes serviços:
- Orçamentos de faturamento: acompanhe o faturamento e gerencie alertas.
- Cloud Build: crie imagens de contêiner e implante no Cloud Run.
- Compute Engine: implemente máquinas virtuais e serviços de rede, como balanceamento de carga.
- Cloud Functions: responda a eventos da plataforma de serviços.
- Cloud Run: hospeda contêineres em um ambiente sem servidor e disponibiliza URLs para acessar o aplicativo.
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
}
Criar canal do Pub/Sub
Cria um canal do Pub/Sub para detectar eventos de orçamento de faturamento e responder com o Cloud Functions
resource "google_pubsub_topic" "costsentry" {
name = "${var.basename}-billing-channel"
project = var.project_number
}
Crie o serviço do Cloud Run para aplicar
Criar um serviço de amostra do Cloud Run em que será aplicada a aplicação do faturamento.
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]
}
Criar instância da VM
Crie uma instância de amostra do Compute Engine para 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 monitorar 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
}
Criar uma conta de serviço e definir permissões
Cria uma conta de serviço para as chamadas de função do 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
}
Definir permissões
O comando a seguir define os papéis e as permissões do IAM que autorizam o Cloud Build a implantar os serviços necessários.
A série de comandos implementa o seguinte: Concede permissão à conta de serviço da função do Cloud para gerenciar o Cloud Run. Concede permissão à conta de serviço da função do Cloud para interromper instâncias do Compute Engine. Concede permissã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]
}
Implantar uma Função do Cloud
O comando a seguir implanta uma Função do Cloud que desativa recursos quando um alerta é acionado.
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 da execução, você terá uma solução de controle de custos em execução no projeto. Além disso, é preciso ter todo o código para modificar ou estender essa solução para se adequar ao seu ambiente.