Terraform: error de checksum entre S3 y DynamoDB

Hace poco me encontré con un problema curioso en un backend remoto de Terraform. De repente, cualquier operación (plan, refresh o apply) empezó a fallar con un error relacionado con el estado remoto. Terraform nos dice que hay un error de checksum entre S3 y el valor almacenado en DynamoDB.

El mensaje era similar a este:

Error: state data in S3 does not have the expected content

The checksum calculated for the state stored in S3 does not match the checksum
stored in DynamoDB.

Calculated checksum: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Stored checksum:     YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY

El problema

En este escenario, Terraform utilizaba:

  • Un bucket S3 para almacenar el archivo terraform.tfstate.
  • Una tabla DynamoDB para gestionar el bloqueo y la información asociada al estado remoto.

Cuando Terraform accede al backend:

  1. Lee el estado almacenado en S3.
  2. Calcula su checksum.
  3. Compara ese valor con el Digest almacenado en DynamoDB.

En nuestro caso, ambos valores no coincidían.

Ante esta inconsistencia, Terraform se negaba a continuar para evitar trabajar sobre un estado que pudiera estar corrupto o desactualizado.

Primeras comprobaciones

Antes de modificar nada, comprobamos varios puntos básicos:

  • Que no hubiera ningún terraform apply en ejecución.
  • Que ningún pipeline de CI/CD estuviera trabajando sobre el mismo estado.
  • Que el error se reprodujera tanto desde un entorno local como desde los pipelines.

Como el problema aparecía independientemente del lugar desde el que ejecutáramos Terraform, pudimos descartar rápidamente un problema relacionado con la máquina local o con la configuración del pipeline.

Localizando la discrepancia

El siguiente paso fue revisar la tabla DynamoDB asociada al backend remoto.

Mediante AWS CLI buscamos la entrada correspondiente al estado afectado:

aws dynamodb scan \
  --table-name <tabla-locks>

Entre los resultados apareció un registro similar al siguiente:

{
  "LockID": {
    "S": "<ruta-al-state>-md5"
  },
  "Digest": {
    "S": "valor-antiguo"
  }
}

El valor almacenado en Digest coincidía exactamente con el checksum que Terraform identificaba como incorrecto.

Esto confirmaba que existía una desincronización entre el contenido actual del state almacenado en S3 y el valor registrado en DynamoDB.

La solución

Terraform ya nos estaba indicando qué valor esperaba encontrar:

Calculated checksum: valor-correcto
Stored checksum:     valor-antiguo

Después de verificar que el archivo de estado almacenado en S3 era válido y confirmar que no había ninguna operación de Terraform en curso, actualizamos manualmente el campo Digest de DynamoDB para que coincidiera con el checksum calculado por Terraform.

Por ejemplo:

aws dynamodb update-item \
  --table-name <tabla-locks> \
  --key '{"LockID":{"S":"<ruta-state-md5>"}}' \
  --update-expression "SET Digest = :d" \
  --expression-attribute-values '{":d":{"S":"valor-correcto"}}'

Este tipo de modificación debe hacerse con precaución. No conviene cambiar el Digest simplemente para hacer desaparecer el error: primero hay que estar seguros de que el state almacenado en S3 es el correcto y de que no existe ninguna ejecución concurrente.

Resultado

Después de actualizar el Digest, volvimos a ejecutar:

terraform plan

Terraform pudo acceder de nuevo al backend remoto y el plan se ejecutó correctamente.

No fue necesario:

  • Regenerar el estado.
  • Restaurar una versión anterior.
  • Modificar el código Terraform.
  • Recrear ningún recurso.

El problema era únicamente una desincronización entre el checksum almacenado en DynamoDB y el contenido real del fichero de estado en S3.

Lecciones aprendidas

Cuando aparece un error como:

state data in S3 does not have the expected content

es fácil asumir inmediatamente que el terraform.tfstate está corrupto. Sin embargo, no siempre es así.

El archivo almacenado en S3 puede ser perfectamente válido y la inconsistencia encontrarse únicamente en el Digestregistrado en DynamoDB.

Antes de realizar cualquier modificación conviene seguir este orden:

  1. Confirmar que no hay ejecuciones de Terraform activas.
  2. Verificar que ningún pipeline esté utilizando el mismo backend.
  3. Comprobar el estado almacenado en S3.
  4. Revisar la entrada correspondiente en DynamoDB.
  5. Comparar el Calculated checksum con el Stored checksum mostrado por Terraform.

Solo después de estas comprobaciones tiene sentido plantearse una corrección manual del Digest.

En este caso, unos minutos revisando cómo funciona el backend remoto evitaron perder mucho más tiempo buscando un problema en el código Terraform que, en realidad, no existía.

Links

¿Te ha ayudado este artículo?

☕ Invítame a un café

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Rubenortiz.es
Información sobre privacidad

Este sitio web utiliza cookies para ofrecerte la mejor experiencia de usuario posible. La información sobre cookies se almacena en tu navegador y realiza funciones como reconocerte cuando vuelve a nuestro sitio web y ayudarme a comprender qué secciones de la web resultan más interesantes y útiles.