Terraform Drift بالعربي: اكشف تغييرات البنية قبل ما تكسر الإنتاج
هتعرف هنا تعمل فحص يومي يكشف أي تغيير اتعمل خارج Terraform، قبل ما أول terraform apply يرجّعه أو يسبب downtime غير متوقع.
المشكلة باختصار
الـ drift معناه إن الواقع على AWS أو Azure أو GCP بقى مختلف عن الكود والـ state اللي Terraform شايفهم. مثال بسيط: مهندس on-call فتح AWS Console أثناء incident ووسّع CIDR في Security Group من 10.0.0.0/16 إلى 0.0.0.0/0 عشان يحل مشكلة بسرعة. الخدمة رجعت تشتغل، بس الكود لسه بيقول القيمة القديمة.
اللي بيحصل فعلاً إن Terraform عند أول plan هيقارن الكود والـ state بالواقع. حسب توثيق HashiCorp، Terraform يعمل refresh أثناء plan وapply، وده ممكن يخليك تكتشف تغييرات اتعملت خارج workflow المعتاد. المشكلة إن الاكتشاف وقت deploy متأخر. أفضل طريقة هنا إنك تعمل فحص مستقل يوميًا أو كل 6 ساعات.
الفكرة الأساسية: افصل كشف drift عن deploy
ركز في النقطة دي: فحص drift مش لازم يغير البنية. استخدم terraform plan -refresh-only عشان تشوف الفرق بين الـ state والواقع بدون تعديل الموارد نفسها. توثيق Terraform يوضح إن -refresh-only هدفه تحديث فهم Terraform للـ state والقيم الخارجة من الموارد، وليس تنفيذ تغيير على البنية.
لو عندك 3 بيئات، وكل بيئة فيها 80 resource، فحص واحد يوميًا غالبًا يكلفك من 2 إلى 8 دقائق حسب عدد providers وسرعة APIs. الرقم مش ثابت، لكنه نطاق عملي في repos متوسطة. المكسب إنك تعرف drift خلال 24 ساعة بدل ما تكتشفه وقت release.
Workflow عملي على GitHub Actions
الافتراض إن عندك Terraform داخل مجلد infra، وإن credentials متخزنة كـ GitHub Secrets. GitHub Actions يدعم on.schedule بصيغة cron، وأقصر تكرار رسميًا هو كل 5 دقائق، لكن لفحص drift اليومي مش محتاج التكرار العالي ده.
name: terraform-drift-check
on:
schedule:
- cron: "15 5 * * *"
workflow_dispatch:
jobs:
drift:
runs-on: ubuntu-latest
permissions:
contents: read
defaults:
run:
working-directory: infra
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v4
with:
terraform_version: "1.14.6"
terraform_wrapper: false
- name: Terraform init
run: terraform init -input=false
- name: Detect drift without changing resources
run: |
set +e
terraform plan -refresh-only -detailed-exitcode -no-color -input=false > drift.txt
code=$?
cat drift.txt
if [ "$code" = "0" ]; then
echo "No drift detected"
exit 0
fi
if [ "$code" = "2" ]; then
echo "Drift detected"
exit 1
fi
echo "Terraform failed"
exit "$code"