المستوى: متوسط — يفترض إنك بتشتغل Terraform على فريق وعندك backend بعيد (remote state).
قفل حالة Terraform: ليه اتنين apply في نفس الوقت بيخربوا الـ state
قفل الحالة (state locking) بيمنع أسوأ عطل في Terraform: تلف ملف الـ state لما اتنين بيعملوا apply في نفس اللحظة. سطر إعداد واحد بيحوّل الفوضى دي لطابور منظّم، وبيوفّر عليك ساعات استرجاع.
المشكلة باختصار
فريقك بيشغّل terraform apply من أكتر من مكان: مهندس من اللابتوب، وبايبلاين CI في نفس الوقت. الاتنين بيكتبوا على نفس ملف الـ state. النتيجة: ملف متضارب، موارد متسجّلة مرتين، أو موارد اتعملت في السحابة ومش موجودة في الـ state. ساعتها Terraform بيبقى أعمى عن نص بنيتك.
ليه ملف الـ state حسّاس لهذه الدرجة
تخيّل دفتر حسابات واحد على المكتب، واتنين محاسبين بيكتبوا فيه في نفس اللحظة. السطور بتتداخل والأرقام بتبوظ، ومحدش يعرف الرصيد الصح. ملف الـ state زي الدفتر ده بالظبط.
علميًا: ملف الـ state ملف JSON بيمثّل الخريطة بين الموارد في الكود والموارد الفعلية عند المزوّد، يعني aws_instance.web في الكود مربوط بـ i-0abc123 الحقيقي. Terraform بيقرأ الملف قبل أي تغيير عشان يعرف الموجود، وبيكتبه بعد التغيير. لو عمليتين كتبتا عليه بالتوازي، الكتابة الأخيرة بتدهس الأولى، وبتفقد موارد من التتبّع. ده مش bug في Terraform، ده سباق كتابة (write race) على مورد مشترك.
الحل: قفل الحالة (state locking)
الفكرة بسيطة: قبل ما Terraform يلمس الـ state، بياخد قفل. أي عملية تانية تحاول تشتغل في نفس الوقت بتترفض لحد ما القفل يتحرّر. ده mutex موزّع على ملف الـ state.
الطريقة الكلاسيكية على AWS: backend بتاع S3 لتخزين الـ state، وجدول DynamoDB للقفل. أول حاجة، اعمل جدول القفل مرة واحدة:
# جدول القفل لازم يكون مفتاحه الأساسي LockID من نوع String
aws dynamodb create-table \
--table-name terraform-locks \
--attribute-definitions AttributeName=LockID,AttributeType=S \
--key-schema AttributeName=LockID,KeyType=HASH \
--billing-mode PAY_PER_REQUEST \
--region eu-west-1
وبعدين اربط الـ backend بالجدول ده:
# backend.tf
terraform {
backend "s3" {
bucket = "myorg-tfstate-prod"
key = "network/terraform.tfstate"
region = "eu-west-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}