< Insights

Introdução ao uso otimizado do Backend S3 no Terraform: boas práticas e configurações essenciais

  • Cloud e Infraestrutura
  • Artigo

O estado do Terraform é um dos pilares da ferramenta, fundamental para gerenciar infraestrutura como código. Se você já utilizou o Terraform, certamente se deparou com o estado. Mas você sabia que ele vai além do básico?

Neste artigo, vamos explorar as melhores práticas para gerenciar o estado através de um backend S3, garantindo segurança, integridade e confiabilidade. Abordaremos tópicos como:

  • Uso do S3 para o backend: descubra como o S3 pode ser utilizado para armazenar o estado do Terraform de forma segura e escalável.
  • Solução do “ovo e da galinha”: aprenda a lidar com o problema da criação da infraestrutura do backend em si.
  • Migração do estado local: migre seu estado local para o backend S3 sem complicações.

Com base no repositório, este artigo te ajudará a usar o estado do Terraform de forma eficiente e segura, implementando melhores práticas para gerenciar sua infraestrutura.

Venha comigo e vamos juntos aprender sobre as boas práticas de uso do Terraform com backend S3.

Boas práticas Backend S3

Vale a pena um rápido lembrete do que é estado e o que é backend. O estado do terraform é uma estrutura de dados que representa toda a infraestrutura com sua configuração que foi provisionada até então. Por sua vez o backend nada mais é do que um mecanismo de persistência para armazenar esse estado.

Dito isso, quando se trata de backend na AWS, o S3 é o serviço mais usado para essa finalidade. Usando o S3, ganhamos um ambiente seguro e centralizado e naturalmente distribuído para compartilhar o estado entre os membros da equipe. Deste modo, surgem necessidades específicas de configuração e cuidados para garantir a segurança e integridade do estado da infraestrutura que serão descritos a seguir.

Configuração da política de acesso

É importante configurar a política de acesso para garantir que apenas as pessoas e service accounts autorizadas possam acessar e modificar o estado da infraestrutura. Imaginando o cenário, desenvolvedores acessam o estado do ambiente de desenvolvimento para leitura identificando as alterações realizadas em códigos, porém somente a service account destinada para a ferramenta de continuous integration (CI) realiza o deploy no ambiente após merge do código. Considerando esse cenário, será utilizado o AWS Identity and Access Management (IAM) para criar usuários, grupos, roles e políticas de acesso conforme a necessidade do projeto e ambientes.

Segue um exemplo para a política de acesso que realiza a separação de usuários para somente leitura, leitura e escrita e negação total para não vinculados. Deste modo, você consegue realizar o controle de acesso de forma granular.

# file: iam.tf
data "aws_iam_policy_document" "backend_infra" {
statement {
sid = "ReadOnlyUsers"
actions = [
"s3:GetObject",
"s3:GetObjectAcl",
"s3:ListBucket",
]
resources = [
aws_s3_bucket.backend_infra.arn,
"${aws_s3_bucket.backend_infra.arn}/*"
]
principals {
type = "AWS"
identifiers = var.users_ready_only
}
}
statement {
sid = "ReadWriteUsers"
actions = [
"s3:*Object"
]
resources = [
aws_s3_bucket.backend_infra.arn,
"${aws_s3_bucket.backend_infra.arn}/*"
]
principals {
type = "AWS"
identifiers = var.users_write_permissions
}
}
statement {
sid = "AllExceptUser"
effect = "Deny"
actions = [
"s3:GetObject"
]
resources = [
aws_s3_bucket.backend_infra.arn,
"${aws_s3_bucket.backend_infra.arn}/*"
]
not_principals {
identifiers = concat(var.users_write_permissions, var.users_ready_only)
type = "AWS"
}
}
}
# file: s3.tf
resource "aws_s3_bucket_policy" "backend_infra" {
bucket = aws_s3_bucket.backend_infra.id
policy = data.aws_iam_policy_document.backend_infra.json
}

Configuração do versionamento do S3

Suponha que no momento do deploy houve uma instabilidade no CI que resultou no corrompimento e perda do arquivo de estado atual.

Para prevenir ou ajudar a resolver esse tipo de situação, existem duas possibilidades para auxiliar neste processo. A primeira é a utilização do versionamento do AWS S3 e a segunda é a utilização do AWS DynamoDB para lockstate.

O S3 permite o versionamento de objetos, o que significa que cada vez que o estado da infraestrutura é alterado, uma nova versão é criada. Isso permite que as diferentes versões possam ser comparadas e revertidas de forma rápida, se necessário.

Esta configuração é muito útil, além disso, a implementação é simples e pode ser realizada através do código abaixo.

# file: s3.tf
resource "aws_s3_bucket_versioning" "backend_infra" {
bucket = aws_s3_bucket.backend_infra.id
versioning_configuration {
status = "Enabled"
}
}

Utilização DynamoDB para lockstate

O DynamoDB pode ser usado pelo Terraform para armazenar o lockstate do backend, o que garante que o estado não seja modificado por mais de um usuário ao mesmo tempo.

Realizar lock do estado é recomendado para ambientes de produção, onde o estado da infraestrutura é mais crítico e não pode ser modificado por mais de um usuário ao mesmo tempo. Para ambientes de desenvolvimento e homologação, o lockstate pode ser desabilitado, já que o estado da infraestrutura tem uma necessidade de deploy constante para testes e validações.

A implementação do DynamoDB para lockstate é simples e pode ser realizada através do código abaixo.

# file: dynamodb.tf
resource "aws_dynamodb_table" "backend_infra" {
name = "terraform-state-lock"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}

Utilização de criptografia

O S3 oferece suporte à criptografia de dados em repouso, o que significa que é possível criptografar o estado da infraestrutura armazenado no S3. Deve-se ressaltar a importância de criptografar o estado, já que várias informações sensíveis podem estar armazenadas no estado do Terraform, como senhas ou informações como número da sua conta AWS utilizada, entre outros dados.

Por padrão, o serviço do S3 utiliza a criptografia por AES-256, mas é possível customizar essa criptografia com outros serviços, inclusive com o AWS KMS, usado para gerenciamento de chaves de criptografia.

A implementação da criptografia utilizando o AWS KMS é simples e pode ser realizada através do código abaixo.

# file: kms.tf
resource "aws_kms_key" "encrypt_state" {
count = var.activate_kms ? 1 : 0

description = "Key to protect S3 objects"
key_usage = "ENCRYPT_DECRYPT"
deletion_window_in_days = 7
is_enabled = true

tags = merge(
{ Name = "${local.deployment_project}-kms-custom-key" },
var.tags
)}

resource "aws_kms_alias" "kms_s3_key_alias" {
count = var.activate_kms ? 1 : 0

name = "alias/${var.project_name}/${var.environment}/s3-state-key"
target_key_id = aws_kms_key.encrypt_state[0].key_id
}
# file: s3.tf
resource "aws_s3_bucket_server_side_encryption_configuration" "backend_infra" {
bucket = aws_s3_bucket.backend_infra.bucket
rule {
dynamic "apply_server_side_encryption_by_default" {
for_each = var.activate_kms ? [1] : []
content {
kms_master_key_id = aws_kms_key.encrypt_state[0].arn
sse_algorithm = "aws:kms"
}
}
dynamic "apply_server_side_encryption_by_default" {
for_each = var.activate_kms ? [] : [1]
content {
sse_algorithm = "aws:kms"
}
}
}
}

Utilização de logging no S3

Uma boa auditoria é essencial para garantir a segurança. A AWS oferece uma boa rastreabilidade através do CloudTrail, mas para obter melhor rastreabilidade e controle é recomendado o uso de logging com o S3.

Segue um exemplo de recursos para adicionar um bucket de logging ao S3 principal.

# file: s3_logging.tf
resource "aws_s3_bucket" "logging" {
bucket = "${local.deployment_project}-bucket-logging"
[...]
}

resource "aws_s3_bucket_acl" "logging" {
bucket = aws_s3_bucket.logging.id
acl = "private"
}

resource "aws_s3_bucket_public_access_block" "logging" {
bucket = aws_s3_bucket.logging.id
[...]
}

resource "aws_s3_bucket_lifecycle_configuration" "logging" {
bucket = aws_s3_bucket.logging.bucket
[...]
}
# file: s3.tf
resource "aws_s3_bucket_logging" "backend_infra" {
bucket = aws_s3_bucket.backend_infra.id

target_bucket = aws_s3_bucket.logging.id
target_prefix = "${local.deployment_project}/"
}

Até aqui foram apresentados alguns recursos que podem ser utilizados para configurar e otimizar o backend S3 do Terraform. Lembrando que para conferir na integra esses códigos encontram-se neste repositório.

Infraestrutura Backend S3

Todas as práticas mencionados podem ser usadas para configurar o backend S3 e podem ser adaptadas a qualquer projeto. Porém podemos ponderar sobre duas situações: qual a infraestrutura mínima necesssária em termos custo/benefício e qual o ideal para um ambiente produtivo.

Para uma infraestrutura mínima, pode ser suficiente apenas criar um bucket S3 e usá-lo como backend. Porém para um ambiente produtivo, vale a pena adicionar outros recursos para dar mais robustez e segurança ao seu backend. Por exemplo, podemos usar o mecanismo de locking de state com o Dynamo e adicionar logging via S3.

Caso você ainda esteja com dúvidas, a infraestrutura inicial proposta possui uma base de recursos para seu projeto que contempla criptografia e logs. Segue o link do código para criação da infraestrutura inicial proposta neste artigo.

Após a criação do backend S3, você deve estar se perguntando, mas e o estado da infraestrutura do backend do Terraform que acabei de criar, vai ficar local? A resposta é sim, mas tem maneiras de se contornar isso, pensando que essa infraestrutura não será alterada após sua criação, é possível configurar o projeto Terraform para utilizar os recursos de backend criados e realizar a migração desses estados para o bucket S3.

No próximo tópico vamos abordar esse cenário, considerando que você já possui um projeto criado no Terraform, como fazer a migração do estado local para o backend S3.

Migrando o estado local para o S3

Executei meu código Terraform e só vi esse artigo agora, o que fazer? Calma, não se desespere, é possível migrar o estado do seu projeto Terraform para o backend S3. Após executar a sua infraestrutura backend conforme descrito anteriormente, é possível configurar o seu projeto Terraform para utilizar o backend S3 e migrar o estado local para o bucket S3.

Uma das maneiras de realizar esse tipo de configuração é através de um arquivo de que contém as informações necessárias, no caso apresentado é o backend.hcl, que pode ser carregado pelo Terraform através da inclusão de dois parâmetro através do comando terraform init , são eles: -backend=true e -backend-config=backend.hcl.

Todas as variáveis utilizadas para esse arquivo de configuração, é possível ser encontradas neste link da documentação do Terraform. A seguir será apresentado um exemplo de arquivo de configuração para o backend S3 em relação a variáveis obrigatórias.

bucket         = nome-do-meu-bucket-s3-de-estado-terraform
key = terraform.tfstate
# Lembre-se que o S3 não possui o conceito de pastas. O prefixo é uma analogia.

Considerando o repositório de exemplo, o arquivo de configuração do backend S3 para o projeto Terraform utilizado, encontra-se neste link.

Uma vez que as configurações de backend estão corretas, basta executar o comando abaixo. Neste momento, será solicitado a migração do estado local para o bucket S3, basta digitar yes e aguardar a migração e inicialização.

terraform init -backend=true -backend-config=backend.hcl

Pronto! Se a inicialização ocorreu sem erros, você terá os seus arquivos de estado sendo carregados para o S3.

Conclusão

Neste artigo, foram apresentadas boas práticas para utilização do backend S3 em projetos Terraform, além da importancia de cada uma delas, focando em auditoria e proteção de dados. Vale ressaltar que os recursos aqui apresentados são específicos da cloud AWS e cada recurso utilizado tem custos atualizados por região, sempre antes de iniciar um projeto de infraestrutura verifique os custos de todos os componentes necessários, backend remoto e projeto principal.

Após a definição dos componentes da infraestrutura, realize a utilização de estado remoto para seu projeto Terraform, pois além de ser uma boa prática, é uma maneira de garantir a segurança e integridade do seu projeto. Além disso, como uma boa prática bônus, é possível realizar o gerenciamento por workspaces, sendo uma maneira de separar os ambientes de seu projeto.

Foi demonstrado o procedimento detalhado para configurar o backend em projetos Terraform por meio de um arquivo de configuração específico. Adicionalmente, foi explicado de maneira abrangente o processo de migração do estado local para o backend S3, garantindo uma transição eficiente e segura.

Lembrando que os códigos apresentados neste artigo encontram-se no repositório por meio do link.

Insights do nosso time

Obtenha insights do nosso time de especialistas sobre metodologias de desenvolvimento de software, linguagens, tecnologia e muito mais para apoiar o seu time na operação e estratégia de negócio.
Saiba mais sobre a Objective
Pergunte algo sobre nossa expertise, serviços e consultoria.