Terraform المتقدم وأنماط البنية ككود

مساحات العمل واستراتيجيات البيئات

18 دقيقة الدرس 2 من 28

مساحات العمل واستراتيجيات البيئات

كل قاعدة كود Terraform جادة تحتاج إلى إدارة ثلاث بيئات على الأقل: التطوير، والاختبار، والإنتاج. النهج السطحي — نسخ ملفات .tf إلى مجلدات منفصلة والحفاظ عليها بشكل متوازٍ — ينهار تحت ثقله خلال أسابيع. النهج الاحترافي يتطلب استراتيجية مدروسة منذ اليوم الأول، لأن الخيار الذي تتخذه هنا يُشكّل كل قرار في سير عمل CI/CD، وكيفية تحديد نطاق ضرر الأخطاء، والضغط المعرفي الذي يحمله كل مهندس.

ثمة ثلاثة أنماط رئيسية لإدارة البيئات المتعددة في Terraform: مساحات العمل (Workspaces)، ومجلد لكل بيئة، وفرع لكل بيئة. لكل منها حالات استخدام مشروعة وأوضاع فشل خطيرة. تستخدم فرق هندسة المنصات في كبرى الشركات أنماطاً مختلفة لطبقات مختلفة من بنيتها التحتية — إن فهم المقايضات يُمكّنك من الاختيار بوعي بدلاً من الوقوع في خيار عشوائي.

مساحات عمل Terraform: ما هي وما ليست عليه

مساحة العمل هي ملف حالة معزول داخل تكوين backend واحد. عند تشغيل terraform workspace new staging، ينشئ Terraform ملف حالة ثانياً مرتبطاً بتلك المساحة. ملفات التكوين مشتركة؛ والحالة فقط هي المختلفة. اسم مساحة العمل النشطة متاح عبر terraform.workspace، وهو سلسلة نصية مدمجة يمكن استخدامها في الاستيفاءات.

# إنشاء مساحات العمل والتنقل بينها terraform workspace new dev terraform workspace new staging terraform workspace new production terraform workspace list terraform workspace select production # استخدام اسم مساحة العمل في التكوين resource "aws_s3_bucket" "app_data" { bucket = "myapp-${terraform.workspace}-data" tags = { Environment = terraform.workspace } } # البحث عن المتغيرات بحسب مساحة العمل باستخدام خريطة locals locals { env_config = { dev = { instance_type = "t3.micro" min_size = 1 max_size = 2 } staging = { instance_type = "t3.small" min_size = 2 max_size = 4 } production = { instance_type = "m5.xlarge" min_size = 6 max_size = 20 } } env = local.env_config[terraform.workspace] }

تُعدّ مساحات العمل ممتازة للبيئات المؤقتة — فروع الميزات، وبيئات مراجعة طلبات السحب، واختبارات الأداء القصيرة — حيث تريد تشغيل نسخة مطابقة من Stack، واختبارها، ثم تدميرها بسلاسة. كما تُفيد حقاً في المشاريع البسيطة حيث تتشابه بيئات dev وstaging وprod إلى حد كبير ولا تُدار حسابات AWS منفصلة لكل بيئة.

مساحات العمل لا توفر عزلاً للبنية التحتية على مستوى الموارد الحقيقية. جميع مساحات العمل تشترك في نفس الـ backend، ونفس بيانات اعتماد المزود، وكل شيء آخر إن لم تكتب حراساً صريحاً. تشغيل terraform apply -workspace=production ببيانات اعتماد خاطئة أو خطة سيئة يمكنه تدمير بيئة الإنتاج بسهولة. والأخطر: لأن التكوينات تبدو متطابقة، لا تتوفر أي إشارة بصرية تُخبرك أنك تعمل على الإنتاج. لهذا السبب تحديداً، ابتعدت فرق كبرى مثل Spotify وStripe عن استخدام مساحات العمل للفصل بين الإنتاج والاختبار.

مجلد لكل بيئة: عزل صريح

النمط الذي توصي به HashiCorp وGruntwork ومعظم فرق هندسة المنصات في الشركات الكبيرة هو منح كل بيئة مجلدها الخاص (أو وحدة جذر خاصة بها)، مع تكوين backend خاص وملف حالة خاص. المنطق المشترك يعيش في الوحدات (modules)؛ ومجلدات البيئات هي مستهلكون رفيعو المستوى لتلك الوحدات بقيم متغيرات خاصة بكل بيئة.

# التخطيط القياسي للمجلدات infrastructure/ modules/ vpc/ # وحدة قابلة للإعادة — بدون provider أو backend eks/ rds/ environments/ dev/ main.tf # يستدعي الوحدات بقيم مناسبة لبيئة dev variables.tf terraform.tfvars backend.tf # يشير إلى حالة dev في S3 staging/ main.tf terraform.tfvars backend.tf # يشير إلى حالة staging في S3 production/ main.tf terraform.tfvars backend.tf # يشير إلى حالة prod في S3 بسياسة قفل أكثر صرامة # مثال: environments/production/backend.tf terraform { backend "s3" { bucket = "myorg-terraform-state-prod" key = "eks/terraform.tfstate" region = "us-east-1" dynamodb_table = "terraform-state-lock-prod" encrypt = true } }

الانضباط الجوهري هنا هو أن مجلد الإنتاج يتطلب بيانات اعتماد AWS منفصلة — عادةً دور IAM في حساب AWS إنتاجي مخصص تفترضه CI/CD فقط بعد بوابة موافقة يدوية. بيئة dev تعمل بحرية؛ والإنتاج محمي على مستوى بيانات الاعتماد، وليس فقط على مستوى السياسات داخل ملفات .tf. هذا هو نموذج AWS Organizations متعدد الحسابات: dev وstaging وproduction حسابات AWS منفصلة، لذا فإن تسرّب بيانات الاعتماد في dev لن يمس الإنتاج أبداً.

Directory-per-Environment with Multi-Account Isolation Git Repo environments/dev/ environments/staging/ environments/production/ CI/CD Pipeline Plan → Approve → Apply AWS Dev Account Auto-apply on merge IAM Role: ci-dev AWS Staging Acct Auto-apply on merge IAM Role: ci-staging AWS Prod Account Manual approval gate IAM Role: ci-prod S3 State: dev S3 State: staging S3 State: prod
نمط مجلد لكل بيئة: كل بيئة تستهدف حساب AWS مخصصاً بحاوية حالة ودور IAM خاص — نطاق الضرر محصور عند حدود الحساب.

فرع لكل بيئة: نمط يجب تجنبه

تحاول بعض الفرق عكس فصل البيئات في Git عبر الحفاظ على فروع طويلة الأمد: فرع dev، وفرع staging، وفرع main للإنتاج، مع نشر CI/CD لأي فرع يُدفع إليه. يظهر هذا النمط غالباً في الفرق التي انتقلت من سير عمل نشر التطبيقات حيث كان فرع لكل بيئة شائعاً.

في الواقع العملي، هذا النمط يُنشئ مشكلات حادة. تتباعد ملفات HCL بين الفروع حين تصل الإصلاحات العاجلة مباشرة إلى main دون إعادة نقلها؛ تعارضات الدمج ثلاثية الاتجاهات في ملفات .tf يصعب حلها صحيحاً؛ و"فرع الإنتاج" يُعطي إحساساً زائفاً بالعزل بينما يشترك في نفس backend للحالة. تاريخ Git يصبح المرجع الأساسي لبنيتك التحتية، لكن فرع Git ليس حارساً للبيئة.

الإجماع في الصناعة عام 2025: استخدم مجلداً لكل بيئة (أو تجريد Terragrunt DRY فوقه) للبيئات طويلة الأمد مثل dev/staging/prod؛ واستخدم مساحات العمل للبيئات المؤقتة قصيرة العمر مثل معاينات طلبات السحب واختبارات الأداء والبيئات التجريبية. أما فرع لكل بيئة فهو نمط مضاد — تجنبه تماماً.

اتخاذ القرار الصحيح لمنظومتك

استخدم مصفوفة القرار هذه عند اختيار استراتيجيتك:

  • حساب AWS واحد، تكوين بسيط، بيئات متشابهة في معظمها: مساحات العمل مقبولة. احتفظ بالحارس count = terraform.workspace == "production" ? 0 : 1 على الموارد الحساسة خلال التجارب.
  • حسابات AWS متعددة، امتثال للمعايير المؤسسية، أو أي احتمال لتطبيق عرضي بين البيئات: مجلد لكل بيئة مع backends منفصلة وبيانات اعتماد منفصلة. هذا هو الافتراضي لأي فريق يتجاوز 5 مهندسين.
  • تكرار كثير بين مجلدات البيئات: اعتمد Terragrunt (الدرس رقم 7) لتجفيف هذا التكرار — تحتفظ بعزل المجلدات مع التخلص من نسخ تكوينات backend ومزامنة استدعاءات الوحدات.
  • بيئات مؤقتة لطلبات السحب/الميزات: مساحات العمل مع إنشاء وتدمير آلي مرتبط بأحداث فتح/إغلاق طلبات السحب في نظام CI. سمّها بشكل حتمي: pr-${PR_NUMBER}.
# مثال: سير عمل CI لإنشاء وتدمير بيئة مؤقتة مبنية على مساحات العمل # .github/workflows/pr-env.yml (الخطوات ذات الصلة) # عند فتح طلب السحب: إنشاء مساحة العمل وتطبيق التكوين - name: Create PR environment run: | terraform workspace select pr-${{ github.event.pull_request.number }} \ || terraform workspace new pr-${{ github.event.pull_request.number }} terraform apply -auto-approve \ -var="environment=pr-${{ github.event.pull_request.number }}" # عند إغلاق طلب السحب: التدمير وتنظيف مساحة العمل - name: Destroy PR environment if: github.event.action == 'closed' run: | terraform workspace select pr-${{ github.event.pull_request.number }} terraform destroy -auto-approve terraform workspace select default terraform workspace delete pr-${{ github.event.pull_request.number }}
احرص دائماً على تأمين الوصول إلى الإنتاج على مستوى بيانات الاعتماد، وليس فقط على مستوى السياسات في كودك. مجلد بيئة الإنتاج يجب أن يكون قابلاً للنشر فقط من خلال حساب خدمة CI/CD مخصص يفترض دوراً بجلسة قصيرة الأمد محمية بـ OIDC Federation (GitHub Actions OIDC إلى دور IAM في AWS). لا ينبغي لأي مهندس أن يمتلك بيانات اعتماد دائمة للتطبيق المباشر على الإنتاج — كل تغيير يمر عبر الـ pipeline، وكل تغيير موثق في Git وفي CloudTrail.

استراتيجية البيئات هي من أعلى قرارات الرافعة في IaC تأثيراً. الاختيار الصحيح مبكراً يعني أن قاعدة كود Terraform تتوسع بسلاسة من ثلاث بيئات إلى ثلاثين. أما الاختيار الخاطئ، فيعني إعادة البناء تحت الضغط حين يُوقف تطبيق عشوائي لمساحة عمل dev الإنتاجَ في الثانية صباحاً — قصة عاشها كل فريق منصة تخطى هذا الدرس.