[Série][DBRE] Pipeline de IaC para provisionamento de bancos de dados no Azure – Criando Módulo Terraform para CosmosDB (MongoDB)

Fala minha gente! Espero que estejam todos bem!

Neste post iremos construir um módulo Terraform que será utilizado posteriormente em nossa pipeline no Azure DevOps, desta vez construiremos um IaC para provisionar um banco de dados CosmosDB!

Vamos iniciar criando os arquivos de provider.tf:

terraform {

  backend "local" {
  }
 
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = "3.48.0"
    }
  }
}

provider "azurerm" {
  features {}
  subscription_id = "16d873b7-07e2-482d-a0d7-d652b5d72e4a"
}

E rg.tf para criar nosso Resource Group aonde ficará nossos recursos do CosmosDB:

resource "azurerm_resource_group" "rg" {
  name     = var.rg
  location = var.regiao
}

Agora vamos criar um arquivo com nossas variáveis chamado variables.tf:

variable "subscription_id" {
    description = "Passar sua subscription do Azure aonde os recursos serão gerados"
}

variable "rg" {
    description = "Resource Group que será criado|utilizado na criação dos recursos de banco de dados"
}

variable "regiao" {
    description = "Região ao qual os recursos serão criados"
}

variable "ambiente" {
    type = map
    default = {
        d = "dev",
        h = "hml",
        p = "prd"
    }
}

variable "env" {
    default = "d"

    validation {
        condition = contains(["d","h","p"],var.env)
        error_message = "Argument 'env' must be either 'd' (dev), 'h' (hml) or 'p' (prd)"
    }
}

variable "nome_sistema" {
    description = "Nome do sistema ao qual os recursos serão destinados"
}

variable "tempo_expiracao_registro" {
    description = "TTL - Time To Live, tempo de expiração do dado na collection do CosmosDB. Default 7 Dias."
    default = 604800 
}

variable "shard_key" {
    description = "Nome da coluna para chave de particionamento|sharding"
}

variable "throughput" {
    description = "Capacidade de RU/s que a collection terá. Por padrão será o minimo de 400."
    default = 400
}

variable "keys" {
    description = "Colunas para determinar a chave de particionamento da tabela. Por default será a coluna _id"
    type        = list(string)
    default     = ["_id"] 
}

Agora com base nas variáveis criadas acima vamos criar nossos locals que tem por base algumas variáveis passadas, criaremos o arquivo locals.tf com o conteúdo:

locals {
    ambiente                = lookup(var.ambiente,var.env)
    default_ttl_seconds    = var.env == "p" && var.tempo_expiracao_registro > 604800 ? var.tempo_expiracao_registro : 86400 #1 dia

    tags = {
        env         = var.env
        ambiente    = local.ambiente
    }
}

Depois de criarmos nossa base do módulo vamos criar os recursos que é o nosso banco de dados CosmosDB. Para quem não esta familiarizado, o CosmosDB é um banco de dados NoSQL multi engine serverless onde podemos criar bancos de dados de varios tipos como NoSQL com Documentos + Linguagem SQL, PostgreSQL gerenciado, Cassandra (Wide-Column oriented), Tabela, Gremlin (Grafos) e por fim MongoDB que entrega document-json. Abaixo temos todas essas ofertas na console do Azure:

Este módulo que estamos criando tem o intuito de entregar um banco de dados CosmosDB com engine\api MongoDB, justamente para termos uma opção voltada a documentos entre os bancos que estamos provisionando em nossas pipelines, sendo assim, criaremos um arquivo cosmosdb_mongodb.tf com o conteúdo:

resource "azurerm_cosmosdb_account" "cosmosdbmongoacc" {
  name                = "${var.nome_sistema}-cosmosdb-account-${local.ambiente}"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  offer_type          = "Standard"
  kind                = "MongoDB"

  capabilities {
    name = "EnableAggregationPipeline"
  }

  capabilities {
    name = "mongoEnableDocLevelTTL"
  }

  capabilities {
    name = "MongoDBv3.4"
  }

  capabilities {
    name = "EnableMongo"
  }

  consistency_policy {
    consistency_level       = "BoundedStaleness"
    max_interval_in_seconds = 300
    max_staleness_prefix    = 100000
  }

  geo_location {
    location          = azurerm_resource_group.rg.location
    failover_priority = 1
  }

  tags                = merge(local.tags)

}

resource "azurerm_cosmosdb_mongo_database" "mongodb_database" {
  name                = "cosmosdb-mongo-${var.nome_sistema}-${local.ambiente}"
  resource_group_name = azurerm_resource_group.rg.name
  account_name        = azurerm_cosmosdb_account.cosmosdbmongoacc.name
}

resource "azurerm_cosmosdb_mongo_collection" "mongodb_collection" {
  name                = "cosmosdb-${var.nome_sistema}-${local.ambiente}"
  resource_group_name = azurerm_cosmosdb_account.cosmosdbmongoacc.resource_group_name
  account_name        = azurerm_cosmosdb_account.cosmosdbmongoacc.name
  database_name       = azurerm_cosmosdb_mongo_database.mongodb_database.name

  default_ttl_seconds = local.default_ttl_seconds
  shard_key           = var.shard_key
  throughput          = var.throughput

  index {
    keys   = var.keys
    unique = true
  }
}

Vamos então imprimir na saída da criação dos recursos os ids de criação do banco de dados e da collection, criando o arquivo output.tf:

output "cosmodb_database_id" {
    value = azurerm_cosmosdb_mongo_database.mongodb_database.id
}

output "cosmodb_collection_id" {
    value = azurerm_cosmosdb_mongo_collection.mongodb_collection.id
}

Agora por fim, iremos declarar os valores das nossas variáveis para não precisarmos digita-las durante a execução do módulo, crie o arquivo terraform.tfvars com o conteúdo a seguir:

subscription_id = "sua_subscription_id_aqui"
rg              = "TerraformAzureCosmosDBMongoDB"
regiao          = "eastus"
nome_sistema    = "webapp"
env             = "p"
shard_key       = "uniqueKey"
throughput      = 1000

Assim ficou a estrutura do nosso módulo terraform:

Vamos agora executar nosso módulo para verificar se todos os recursos serão executados com êxito, lembrando que você precisará executar o login no azure via cli para conseguir rodar o terraform:

az login #logue na Azure com sua conta
terraform init
terraform validate
terraform plan
terraform apply --auto-approve

Por fim temos nossos recursos criados e podemos ver no console do Azure:

Para nos conectarmos na nossa instancia de banco de dados mongodb precisamos ir em Settings (Configurações) no menu do lado esquerdo da tela e clicar em Connection String, então teremos as seguintes informações:

No meu caso que utilizo JetBrains DataGrip posso utilizar a URL de conexão a base destacada na imagem acima, basta escolher o Datasource Mongodb e configurar para passar apenas a URL de autenticação e clicar em Test Connection e depois em OK:

Pronto, mais um banco de dados provisionado com sucesso no Azure! Agora podemos destruir essa infraestrutura que não precisa ficar disponível neste momento, para isso basta executar:

terraform destroy

Agora vamos subir nosso código para o Github para ficar guardadinho lá esperando a pipeline que faremos posteriormente:

git add .
git commit -m "Modulo Terraform Azure CosmosDB"
git push

É isso por hoje gente, obrigado por me acompanhar nesta série maravilhosa onde estamos desenvolvendo nossa infraestrutura como código!

No próximo post iremos construir mais um banco de dados! Fiquem ligades!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: