مدونة عمار الخوالده

نظرة في الـ Infrastructure as Code - IaC

قُصاصة

البنية التحتية (Infrastructure) هي مجموع المكونات والموارد التي تعمل معا كقاعدة لتشغيل مشروعك، كالسيرفرات المطلوبة للتشغيل أو لتخزين البيانات، والشبكات والـ IPs وإعداداتها، أو الـ Domains وإعدادات الـ DNS وغيرها.

كل جزء من أجزاء الـ Infrastructure تحصل عليه من أحد مزودي الخدمة، وإدارة هذه الموارد أو المكونات تتم عادة بالدخول إلى لوحة تحكم خاصة بكل مزود خدمة وإنشاء الموارد أو تعديلها.

فأدخل مثلا إلى لوحة تحكم مزود خدمة السيرفرات لإنشاء بعض السيرفرات والـ Firewalls وإعدادات الشبكة فيما بينها، ثم أدخل إلى مزود خدمة الـ DNS لتعديل إعدادات الـ DNS، ثم إلى مزود خدمة الإيميلات والـ SMTP… وهكذا

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

من الممارسات التي تسهل إدارة البنية التحتية هي الـ Infrastructure as Code والمعروفة اختصارا بـ IaC. وهي تجهيز البنية التحتية من خلال ملفات تكتب كـ Code قابل للتنفيذ بدلا من فعل ذلك يدويا.

تُكتب إعدادات البنية التحتية بإحدى طريقتين:

  • Imperative - بطريقة الأوامر

  • Declarative - بطريقة تعريفية

الطريقة الأولى مشابهة للبرمجة الاعتيادية على شكل خطوات من الأوامر، فربما تستخدم بمجموعة من ملفات Bash أو بلغة برمجة أخرى، فالـ Code هنا عبارة عن سلسلة من الأوامر التي يتم تنفيذها لإعداد الـ Infrastructure، فتكون على شكل:

  • اتصل بـ API مزود الخدمة لانشاء ثلاثة سيرفرات
  • اتصل بالـ API مرة أخرى لإضافة مفتاح SSH
  • اتصل بالـ SSH لتنفيذ مزيد من الأوامر لإعداد السيرفرات.

بينما الـ Declarative هو أسلوب تعريفي، تصف باستخدامه النتيجة المراد الوصول إليها، فالـ Code في هذا الأسلوب يصف عدد السيرفرات ومواصفاتها، وإعدادات الشبكة التي تربطها، لا الأوامر التي تقوم بإنشائها.

عند ذِكر الـ IaC يُقصد غالبا الـ Declarative لأنه أبسط للوصول إلى النتيجة المطلوبة، وفي الواقع قد تستخدم خليطا معظمه Declerative مع تنفيذ بعض الأوامر باستخدام Bash غالبا.

مثال مختصر باستخدام أداة Terraform:

 1# إعدادات الشبكة
 2resource "hcloud_network" "default_private_network" {
 3  name     = "private-network"
 4  ip_range = "10.0.0.0/24"
 5}
 6
 7resource "hcloud_network_subnet" "private_subnet" {
 8  network_id   = hcloud_network.default_private_network.id
 9  type         = "cloud"
10  network_zone = "eu-central"
11  ip_range     = "10.0.0.0/24"
12}
13
14locals {
15  postgres_private_ip = "10.0.0.3"
16}
17
18
19# إنشاء السيرفرات
20resource "hcloud_server" "postgres" {
21  name        = "postgres"
22  image       = "ubuntu-24.04"
23  server_type = "cx23"
24  location = "nbg1"
25  network {
26    network_id = hcloud_network.default_private_network.id
27    ip         = local.postgres_private_ip
28  }
29}
30
31resource "hcloud_server" "apps_server" {
32  name        = "Apps-Server"
33  image       = "ubuntu-24.04"
34  server_type = "cx23"
35  location = "nbg1"
36  network {
37    network_id = hcloud_network.default_private_network.id
38    ip         = "10.0.0.5"
39  }
40}
41
42# إعدادات الـ DNS
43
44resource "cloudflare_dns_record" "A_my_app_ammardev" {
45  type = "A"
46  name = "my_app"
47  content = hcloud_server.apps_server.ipv4_address
48  ttl = 3600
49  proxied = false
50}

تنفيذ هذا الـ code باستخدام Terraform يضمن:

  • إنشاء شبكة بالإعدادات المحددة (على مزود خدمة hcloud)

  • إنشاء سيرفرين بالمواصفات المحددة وإضافتهما إلى الشبكة

  • إنشاء DNS Record على CloudFlare يشير إلى IP السيرفر الذي تم انشاؤه مسبقا

المثال باستخدام Terraform لكن الأدوات كثيرة وغير محصورة بها، غالبا تُستخدم عدة أدوات لتحقيق أهداف مختلفة.

أهمية الـ IaC تكمن في عدة أمور:

  • ضمان نفس النتيجة عند إعادة التنفيذ سواء لإعادة انشاء البيئة أو لإنشاء بيئات أخرى (production, staging… إلخ)

  • وجود كل شيء مكتوبا يعد توثيقا ممتازا يمكن الرجوع إليه لمعرفة عناصر الـ Infrastructure وارتباطها ببعضها.

  • إضافة ملفات الإعدادات إلى Git يضمن:

    • تتبع التغيرات التي تحصل مع الوقت

    • التراجع السريع عن التغييرات

    • وجود آلية منظمة لمراجعة التغييرات قبل الموافقة عليها