استخدام الوحدات (Modules) في Terraform لتنظيم الكود وإعادة استخدامه

دقائق القراءة: 6

استخدام الوحدات Modules في Terraform لتنظيم الكود وإعادة استخدامه

عندما تبدأ مشاريع Infrastructure as Code صغيرة، قد يبدو وضع كل الموارد داخل ملف واحد أمراً مقبولاً. لكن مع نمو البيئات السحابية وظهور أكثر من شبكة وخادم وقاعدة بيانات، يتحول الملف الواحد إلى كتلة يصعب قراءتها وصيانتها ومراجعتها داخل فرق DevOps.

هنا تظهر أهمية الوحدات Modules في Terraform. فهي تسمح لك بتجميع منطق بناء مورد أو مجموعة موارد في مكوّن قابل لإعادة الاستخدام، بنفس الفكرة التي نستخدم بها الدوال في البرمجة أو القوالب في أنظمة النشر المؤتمت.

إذا كنت قد قرأت مقال البنية التحتية ككود IaC: لماذا يجب أن نتخلى عن إنشاء السيرفرات يدوياً؟، فالوحدات تمثل الخطوة الطبيعية التالية للانتقال من كتابة موارد متفرقة إلى بناء معمارية نظيفة، معيارية، وقابلة للتوسع ضمن بيئات التطوير والاختبار والإنتاج.

ما هي الوحدات Modules في Terraform؟

الوحدة هي مجلد يحتوي ملفات Terraform تمثل وظيفة محددة، مثل إنشاء شبكة VPC أو خادم EC2 أو مجموعة قواعد Security Group. ويمكن استدعاء هذه الوحدة من مشروع رئيسي مع تمرير مدخلات واستقبال مخرجات.

تقنياً، أي مجلد Terraform هو وحدة. حتى المشروع الجذري نفسه يسمى Root Module. لكن المقصود عملياً هو الوحدات الفرعية Child Modules التي تعزل أجزاء البنية التحتية في طبقات مستقلة.

لماذا نستخدم الوحدات في البيئات السحابية الكبيرة؟

في المشاريع الحقيقية، نادراً ما تنشئ خادماً واحداً فقط. غالباً ستبني شبكة، ثم طبقة تطبيق، ثم موازن حمل، ثم تخزين، ثم قواعد بيانات مُدارة، ثم سياسات صلاحيات. كتابة كل ذلك في ملفات متداخلة يجعل المراجعة البرمجية صعبة، ويزيد احتمال تكرار الأخطاء عبر البيئات.

  • تقليل التكرار عبر إعادة استخدام نفس منطق الإنشاء أكثر من مرة.
  • توحيد المعايير بين بيئات dev وstaging وproduction.
  • تبسيط المراجعة داخل أنظمة CI/CD مثل GitHub Actions وJenkins.
  • فصل المسؤوليات بين فرق الشبكات والأمن والتطبيقات.
  • تسهيل اختبار التغييرات قبل تطبيقها على البنية الحية.

وهذا يتكامل مباشرة مع فكرة إدارة حالة البنية التحتية Terraform State وكيف تحافظ عليها من الضياع، لأن التنظيم الجيد يقلل الفوضى ويجعل تتبع الموارد وتغيراتها أكثر وضوحاً.

البنية القياسية لمجلدات الوحدات

أفضل ممارسة شائعة هي فصل الوحدات في مجلد مستقل، ثم استدعاؤها من المشروع الرئيسي. هذا النمط يساعد على بناء مكتبة داخلية من الوحدات الجاهزة للاستخدام في مشاريع متعددة.

project/
├── main.tf
├── variables.tf
├── outputs.tf
├── terraform.tfvars
└── modules/
    ├── network/
    │   ├── main.tf
    │   ├── variables.tf
    │   └── outputs.tf
    └── compute/
        ├── main.tf
        ├── variables.tf
        └── outputs.tf

داخل كل وحدة، يفضل أن يحتوي الملف main.tf على الموارد، وvariables.tf على المدخلات، وoutputs.tf على القيم المصدّرة لباقي الوحدات أو للمشروع الرئيسي.

مثال عملي: إنشاء وحدة لشبكة سحابية

لنفرض أنك تريد إنشاء وحدة لبناء شبكة VPC. بدلاً من تكرار نفس الكود لكل بيئة، ضع المنطق داخل وحدة قابلة لإعادة الاستخدام.

ملف الوحدة: modules/network/main.tf

resource "aws_vpc" "this" {
  cidr_block = var.vpc_cidr

  tags = {
    Name = var.vpc_name
  }
}

resource "aws_subnet" "public" {
  vpc_id     = aws_vpc.this.id
  cidr_block = var.public_subnet_cidr

  tags = {
    Name = "${var.vpc_name}-public-subnet"
  }
}

ملف المتغيرات: modules/network/variables.tf

variable "vpc_name" {
  type = string
}

variable "vpc_cidr" {
  type = string
}

variable "public_subnet_cidr" {
  type = string
}

ملف المخرجات: modules/network/outputs.tf

output "vpc_id" {
  value = aws_vpc.this.id
}

output "public_subnet_id" {
  value = aws_subnet.public.id
}

استدعاء الوحدة من المشروع الرئيسي

بعد تجهيز الوحدة، يمكن استدعاؤها بسهولة من Root Module. هذه النقطة هي جوهر الفائدة: نفس الوحدة يمكن توظيفها مرات متعددة مع قيم مختلفة.

module "network" {
  source             = "./modules/network"
  vpc_name           = "prod-vpc"
  vpc_cidr           = "10.0.0.0/16"
  public_subnet_cidr = "10.0.1.0/24"
}

وبعدها تستطيع ربط وحدة أخرى، مثل وحدة خوادم التطبيق، باستخدام المخرجات القادمة من وحدة الشبكة. هذا الأسلوب يعزز الفصل المنطقي بين طبقات البنية التحتية ويمنع التشابك غير الضروري.

مثلاً، إذا كنت تعمل على بيئة تحتوي تطبيقات معبأة داخل Docker، فمن المفيد قراءة مشكلة “الكود يعمل على جهازي فقط” وكيف يحلها Docker نهائياً؟ لأن الوحدات في Terraform تنظّم البنية التحتية تماماً كما تنظّم الحاويات تشغيل التطبيقات بصورة قابلة للتكرار.

كيف تربط الوحدات مع أنابيب CI/CD؟

في البيئات الاحترافية، لا يتم تشغيل terraform apply يدوياً على كل تعديل. بل يُفضَّل دمجه مع أنابيب التحقق والتخطيط والموافقة. عند تعديل وحدة معينة، يمكن للـ Pipeline تنفيذ فحص تنسيق، ثم plan، ثم انتظار الموافقة قبل التطبيق.

  • استخدم فروعاً منفصلة لكل تعديل على الوحدات.
  • اعرض ناتج terraform plan داخل طلب الدمج Pull Request.
  • امنع التطبيق المباشر على الإنتاج دون مراجعة ثانية.
  • احتفظ بإصدارات مستقرة من الوحدات المهمة.

ولفهم هذا المسار بشكل أعمق، راجع ما هو الـ CI/CD؟ ولماذا نؤتمت عمليات اختبار ونشر الأكواد؟، ثم مقدمة في GitHub Actions: كتابة أول مسار عمل Workflow.

لا تقم بتعديل وحدة مستخدمة في الإنتاج مباشرة دون اختبارها في بيئة معزولة. أي تغيير في مورد مشترك مثل VPC أو جدار ناري قد يؤدي إلى Downtime واسع أو عزل خدمات حرجة عن الشبكة.

أفضل الممارسات عند تصميم الوحدات

1) اجعل الوحدة تؤدي مهمة واحدة فقط

الوحدة الجيدة ليست مشروعاً كاملاً داخل مجلد واحد. الأفضل أن تبني وحدة للشبكة، وأخرى للحوسبة، وثالثة لقواعد الأمان. هذا التقسيم يرفع قابلية الاختبار وإعادة الاستخدام ويمنع التضخم الوظيفي.

2) صمم مدخلات واضحة ومحدودة

لا تملأ الوحدة بعشرات المتغيرات غير الضرورية. ابدأ بما تحتاجه فعلاً، واستخدم قيماً افتراضية مدروسة. كل متغير إضافي يزيد تعقيد الاستدعاء ويضعف تجربة المطور الذي سيستخدم الوحدة لاحقاً.

3) صدّر فقط المخرجات المهمة

المخرجات Outputs يجب أن تكون مفيدة لوحدات أخرى، مثل subnet_id أو security_group_id. تصدير كل شيء يجعل الواجهة الخارجية للوحدة فوضوية وغير مستقرة.

4) وثّق استخدام الوحدة

أضف ملف README يشرح الهدف والمتغيرات والأمثلة. في الفرق الكبيرة، التوثيق الجيد يقلل الاعتماد على الذاكرة الفردية ويجعل نقل المعرفة أسرع وأكثر أماناً.

احرص على عدم تمرير الأسرار الحساسة مثل كلمات المرور أو مفاتيح API مباشرة داخل ملفات المتغيرات العادية. استخدم مخازن أسرار آمنة، وادمجها مع نظام الأتمتة وفق مبدأ أقل الصلاحيات.

أخطاء شائعة يجب تجنبها

  • إنشاء وحدة عملاقة تدير كل شيء من الشبكة حتى التطبيق.
  • ربط الوحدات ببعضها بشكل دائري يسبب تعقيداً في الاعتماديات.
  • تجاهل الإصدارات، ما يجعل التعديلات تكسر مشاريع قديمة تعتمد على نفس الوحدة.
  • نسخ نفس الوحدة إلى عدة مشاريع بدلاً من إدارتها كمصدر مشترك.
  • إهمال مراجعة الأوامر الأساسية مثل أوامر Terraform الأساسية المذهلة Init, Plan, Apply, Destroy قبل تشغيل التغييرات.

الخلاصة

الوحدات Modules في Terraform ليست مجرد تحسين شكلي للكود، بل هي أساس هندسي لإدارة بنية تحتية قابلة للتوسع والمراجعة والصيانة. من خلالها تنتقل من كتابة موارد متكررة إلى بناء مكوّنات معيارية يمكن اختبارها ومشاركتها واستخدامها بثقة عبر فرق وبيئات متعددة.

وكلما كانت البنية السحابية أكبر، زادت أهمية هذا الأسلوب. فإذا كنت قد بدأت فعلاً في كتابة أول ملف Terraform لإنشاء سيرفر VPS سحابي برمجياً، فالخطوة التالية المنطقية هي تحويل هذا الكود إلى وحدات نظيفة يمكن لفريقك الاعتماد عليها ضمن رحلة الأتمتة السحابية الاحترافية.

4 comments

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *