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: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYEl 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:
- Lee el estado almacenado en S3.
- Calcula su checksum.
- Compara ese valor con el
Digestalmacenado 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 applyen 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 planTerraform 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 contentes 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:
- Confirmar que no hay ejecuciones de Terraform activas.
- Verificar que ningún pipeline esté utilizando el mismo backend.
- Comprobar el estado almacenado en S3.
- Revisar la entrada correspondiente en DynamoDB.
- Comparar el
Calculated checksumcon elStored checksummostrado 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
- https://www.rubenortiz.es/tag/terraform/
- https://stackoverflow.com/questions/57984714/error-refreshing-state-state-data-in-s3-does-not-have-the-expected-content
¿Te ha ayudado este artículo?
☕ Invítame a un café