Executando verificação de segurança...
1

Atualizar AWS RDS PostgresSQL 9.6.22 para 12.7 com Terraform

Histórico

Escrevi inicialmente esse post no github quando o fim do suporte do PostgresSQL 9.6 estava se aproximando (18 Jan 2022).
A ideia desse tutorial é auxiliar na atualização do seu Banco de Dados RDS Postgres da versão 9.6 para 12.7. Dito isso, atualizar para outras versões não deve ser um processo tão diferente.

Pré-Requisitos:

Esse passo-a-passo utiliza as seguintes ferramentas:

  • Terraform
  • Origem: AWS RDS Postgres v9.6.22
  • Destino: AWS RDS Postgres v12.7
    *Para saber qual versão do Postgres você pode usar como destino, entre no console RDS na AWS, selecione o seu banco de dados e clique em modificar. Então, na versão da Engine, veja as opções disponíveis. Tome nota da versão de destino apropriada, porém não faça a alteração no console.
  • AWS CLI (command line interface) versão 2:
# Comando
$ aws --version
# Saída
aws-cli/2.2.16 Python/3.8.8 Linux/5.11.0-25-generic exe/x86_64.ubuntu.20 prompt/off
  • E que aws cli v2 esteja configurada para sua conta da AWS.

Passo 1 - Declare suas Variáveis de Ambiente:

No console da AWS, adquira todas as informações que você irá precisar e exporte os valores usando o comando export do bash (terminal).
Eu as dividi em duas seções:
1.1 - Valores que você já possui na sua conta da AWS:

export NAME_DB_SOURCE="nome-atual-do-seu-bd"
export INSTANCE_PARAMETER_GROUP_NAME="default.postgres9.6"
export ENGINE="postgresql"
export ENGINE_VERSION="9.6"
export DB_SUBNET_GROUP_NAME="nome-da-subnet-atual-do-bd-1234567890123456789"
export AVAILABILITY_ZONE=us-east-1a
export SECURITY_GROUP1="sg-1234567890"
export SECURITY_GROUP2="sg-0987654321"
export DB_INSTANCE_CLASS=db.t3.micro

Para mais informações sobre a subnet do BD: DB_SUBNET_GROUP_NAME

1.2 - Valores novos que serão utilizados para atualização:

export NAME_DB_INSTANCE_SNAPSHOT="snapshot-do-bd-atual-$(date '+%F')"
export NAME_DB_INSTANCE_SNAPSHOT_ENCRYPTED="snapshot-do-bd-atual-$(date '+%F')-encriptado"
export KMS_KEY_ID=xxxx-xxxx-xxxx-xxxx
export INSTANCE_ID="nome-do-novo-bd"
export ENGINE_TARGET_VERSION=12.7

Passo 2 - Crie um Backup (Snapshot) do seu Banco Atual:

# Criando o snapshot
aws rds create-db-snapshot \
    --db-instance-identifier $NAME_DB_SOURCE \
    --db-snapshot-identifier $NAME_DB_INSTANCE_SNAPSHOT >> log

# Comando para aguardar a criação do snapshot
aws rds wait db-snapshot-available \
    --db-snapshot-identifier $NAME_DB_INSTANCE_SNAPSHOT

Passo 2.1 - Encriptando o Snapshot (Opcional):

aws rds copy-db-snapshot \
    --source-db-snapshot-identifier $NAME_DB_INSTANCE_SNAPSHOT \
    --target-db-snapshot-identifier $NAME_DB_INSTANCE_SNAPSHOT_ENCRYPTED \
    --kms-key-id $KMS_KEY_ID \
    --copy-tags >> log
# Comando para aguardar a criação do snapshot
aws rds wait db-snapshot-available \
    --db-snapshot-identifier $NAME_DB_INSTANCE_SNAPSHOT_ENCRYPTED

Passo 3 - Pegue o ARN do Snapshot e Exporte no Bash:

Quando você concluir o passo 2, pegue o ARN do snapshot no console da AWS e exporte o valor no bash.
*Se você encriptou o snapshot, utilize o arn criado após o passo 2.1.
Exportando valor no bash:

# Exportando o ARN do snapshot no terminal
export ARN_INSTANCE_SNAPSHOT_DEST=arn:aws:rds:us-east-1:1234567890:snapshot:snapshot-of-current-db-2022-01-17-encriptado

Passo 4 - Criando a Nova Instância do BD a Partir do Snapshot:

# Criando nova instância do BD a partir do Snapshot
aws rds restore-db-instance-from-db-snapshot \
    --db-instance-identifier $INSTANCE_ID \
    --db-snapshot-identifier $ARN_INSTANCE_SNAPSHOT_DEST \
    --db-parameter-group-name $INSTANCE_PARAMETER_GROUP_NAME \
    --db-subnet-group-name $DB_SUBNET_GROUP_NAME \
    --availability-zone $AVAILABILITY_ZONE \
    --vpc-security-group-ids $SECURITY_GROUP1 $SECURITY_GROUP2 \
    --no-enable-iam-database-authentication \
    --deletion-protection \
    --copy-tags-to-snapshot >> log

# Comando para esperar até ela ficar pronta
aws rds wait db-instance-available \
    --db-instance-identifier $INSTANCE_ID

Passo 5 - Atualize a Nova Instância Para a Versão Destino Escolhida:

# Atualizar a versão da engine do BD
aws rds modify-db-instance \
  --db-instance-identifier $INSTANCE_ID \
  --engine-version $ENGINE_TARGET_VERSION \
  --allow-major-version-upgrade \
  --apply-immediately

# Comando para esperar até ela ficar pronta
aws rds wait db-instance-available \
    --db-instance-identifier $INSTANCE_ID

Pós-Atualização

Se tudo ocorreu como esperado, agora você tem 2 cópias do seu BD. A original, na versão 9.6, e a nova, na versão 12.7.
Os próximos passos devem incluir:

  • Atualizar a aplicação para apontar para o novo BD
  • Importar a nova instância do BD utilizando Terraform

Passo 6 - Atualize a Aplicação para Apontar para o Novo BD

Essa etapa é mais específica para cada projeto. Porém, basta buscar todas as referências que se tinha ao BD antigo (pesquise pelo nome do BD, por exemplo) e troque-as pelas informações novas (novo nome, etc.).

Passo 7 - Importe os Novos Componentes para o Estado do Terraform (Novo BD, KMS, Novo Cluster e o que mais que for Aplicável)

Para importar o novo BD, primeiro você precisa defini-lo no seu código terraform (não substitua por cima do original, apenas crie uma nova instância):

resource "aws_db_instance" "db-postgres-12-7" {
  allocated_storage      = 50
  engine                 = "postgres"
  engine_version         = "12.7"
  identifier             = "nome-do-novo-bd"
  instance_class         = "db.t3.micro"
  username               = "db-username"
  name                   = "db-name"
  password               = "db-password"
  parameter_group_name   = "default.postgres12.7"
  db_subnet_group_name   = "subnet-group"
  vpc_security_group_ids = "vpc-id"
  skip_final_snapshot    = true

  tags = "tags"
}

Após criada as instâncias no código, teremos que exectuar o método para importar as instâncias ao estado do Terraform. Com base na própria documentação do Terraform (e mesmo que o projeto execute com um backend remoto), o comando de importação roda localmente (diferente de comandos como o Apply, que rodam no seu ambiente Terraform Cloud).
A própria documentação diz (tradução livre):
"(...) o import command não vai ter acesso à informações do seu backend remoto, tal como variáveis do seu workspace."

Para user o comando Terraform import com seu estado remoto, você precisará configurar localmente variáveis equivalentes à do seu workspace remoto.

Com isso em mente, você está a poucos passos para completar essa atualização do BD.

Rode o seguinte comando do Terraform import:

$ terraform import aws_db_instance.db-postgres-12-7 nome-do-novo-bd

Os 2 últimos passo são:

  • Terraform Plan (para validar que suas mudançãs estão corretas):
$ terraform plan
  • Terraform Apply (aplicar as mudanças na sua infraestrutura):
$ terraform apply
Carregando publicação patrocinada...