طبقة البنية التحتية كرمز
طبقة البنية التحتية كرمز
تُعدّ طبقة البنية التحتية كرمز (IaC) هيكل العمود الفقري للمنصة بأكملها. كل شيء آخر — Kubernetes وخطوط أنابيب CI/CD وعوامل المراقبة وأدوات الأمان — يعتمد على ما يُوفّره Terraform وكيفية هيكلته. إذا نُفِّذت هذه الطبقة بشكل سيئ، تتحوّل IaC إلى أبطأ جزء وأخطره في سلسلة التسليم: تعارض أقفال الحالة يُعيق الفرق، وحوادث الأثر التدميري الواسع تُوقف الإنتاج، والانجراف بين البيئات يُنتج أخطاءً يستحيل إعادة إنتاجها. إذا نُفِّذت بشكل صحيح، تصبح غير مرئية — يُقدّم المهندسون طلبات سحب، تُطبّقها خطوط الأنابيب بأمان، وتُصلح المنصة نفسها.
تغطي هذه الدرس ثلاثة أشياء تمتلكها كل فرقة منصة في شركات التكنولوجيا الكبرى: تخطيط المستودع الذي يتوسّع لما يزيد عن 50 مهندساً، واستراتيجية الحالة التي تجعل الأثر التدميري قيداً تصميمياً من الدرجة الأولى، وكتالوج الوحدات الداخلية الذي يمنع كل فريق من إعادة اختراع مجموعة عقد EKS ذاتها.
تخطيط المستودع: نهج Monorepo
في Netflix وAirbnb وStripe، تعيش البنية التحتية في مستودع أحادي واحد مع تطبيق صارم لقواعد CODEOWNERS. يُقدّم نهج polyrepo حدوداً أمنية أحدّ (لا يستطيع مهندسو المنتج حتى قراءة HCL للطبقة الأساسية) لكنه يفقد القدرة على تتبّع التبعيات عبر الطبقات ومراجعة التغييرات الذرية. في هذا المشروع الختامي نستخدم الـ monorepo. شجرة الدلائل أدناه هي التخطيط القياسي — كل مسار يعكس قراراً متعمداً:
دلائل الطبقات المرقّمة (01-foundation و02-platform و03-workloads) تُشفّر ترتيب التبعية. قاعدة CI ترفض أي طلب سحب يحاول مراجعة مخرجات باتجاه أعلى — يمكن لـ workloads قراءة مخرجات platform، لكن يجب ألا تعتمد platform أبداً على ملف حالة workload.
modules/ وجميع مسارات 01-foundation/ موافقة فريق المنصة. لا ينبغي لمهندس منتج أن يتمكن من دمج تغيير على CIDR الـ VPC أو إصدار مستوى تحكم EKS دون مراجعة. يُنفّذ GitHub CODEOWNERS مع حماية الفروع و"مراجعات مطلوبة من أصحاب الكود" هذا الأمر تلقائياً.
استراتيجية الحالة: العزل كقيد من الدرجة الأولى
الحالة هي حدّ الأثر التدميري. يمكن لأمر terraform apply واحد تدمير ما يعيش في ملف حالته فحسب — لا شيء آخر. الانقسام الثلاثي الطبقات في شجرة الدلائل يُقابله مباشرةً ثلاثة ملفات حالة منفصلة لكل بيئة. الطبقة الأولى (foundation) تُلمَس مرة كل ربع سنة؛ الطبقة الثالثة (workloads) تُلمَس عشرات المرات يومياً. يجب ألا تتشارك قفلاً أبداً.
ملف backend.tf الخاص بكل طبقة يتبع نمطاً متطابقاً. دلو S3 ذاته يُوفَّر بواسطة طبقة foundation في حساب الأمان، مع التحقق من الإصدار، والتشفير من جهة الخادم (SSE-KMS)، وحذف MFA. يُوفّر DynamoDB جدول قفل الحالة:
terraform_remote_state عبر حدود الثقة. إذا استطاع فريق المنتج A قراءة ملف حالة foundation مباشرةً، يمكنه قراءة كل مخرج حساس — بيانات اعتماد RDS الرئيسية، معرّفات الشبكات الفرعية الخاصة، أسماء موارد KMS. النمط المعتمد هو نشر القيم غير الحساسة عبر الطبقات إلى SSM Parameter Store كجزء من تطبيق الطبقة الأدنى، وجعل الطبقات العليا تقرأها عبر مصادر بيانات aws_ssm_parameter.
لمشاركة المخرجات عبر الطبقات، يبدو النمط هكذا — تكتب طبقة platform وتقرأ طبقات workloads:
كتالوج الوحدات الداخلية
في أي شركة بها أكثر من ثلاثة مهندسين للمنصة، تُنتج كتابة الوحدات العشوائية تكاثراً لمجموعات عقد EKS غير متوافقة خفياً، ومثيلات RDS بلا لقطات نهائية، ودلاء S3 مع تمكين الوصول العام بصمت. يحل كتالوج الوحدات هذا بجعل الشيء الصحيح هو الشيء السهل: يكتب مهندس المنتج module "payments_db" ويحصل على التشفير، ومجموعات المعاملات، وحماية الحذف، وتنبيهات CloudWatch مجاناً.
للوحدة الداخلية الاحترافية ثلاث خصائص تميّزها عن الغلاف السريع:
- إعدادات افتراضية محكومة تُشفّر السياسة. التشفير مُفعَّل افتراضياً ولا يمكن تعطيله عبر متغير. حماية الحذف في RDS تأخذ القيمة الافتراضية
trueوتتطلّب تغييرallow_major_version_upgrade = falseصراحةً. الأمان خروج، لا دخول — وحتى عند ذلك، تحجب بوابات سياسات Conftest التكوينات غير الآمنة في CI قبل الموافقة على أي plan. - مُصدَّرة بإصدارات ومتتبَّعة في سجل التغييرات. تعيش الوحدات تحت
modules/في الـ monorepo. لكل وحدة ملفCHANGELOG.md. يُشير المستهلكون إلى وسم git:source = "git::https://github.com/company/infra//modules/rds-postgres?ref=v3.2.1". تُعلَن رفعات الإصدار الرئيسية في النشرة الداخلية للمنصة؛ تُهاجر الفرق في جدولها الخاص، لكن فريق المنصة يُعلن انتهاء صلاحية الإصدارات القديمة بتاريخ إيقاف صارم. - المخرجات تغطي 100% مما يحتاجه المستهلكون. وحدة لا تُخرج ARN الخاص بها تُجبر المستهلكين على استخدام مصادر البيانات وتُنشئ اقتراناً ضمنياً بين ترتيب التطبيق وملف الحالة. يجب أن يكون لكل مورد تُوفّره الوحدة مخرج مقابل له.
فيما يلي واجهة وحدة rds-postgres الداخلية المُجرَّدة لكن الممثِّلة للإنتاج. الوحدة الكاملة تمتد لنحو 180 سطراً من HCL؛ الواجهة هي ما يهم:
v3.2.1 → v3.2.2) يجب أن يكون متوافقاً للخلف — إضافة متغير اختياري بقيمة افتراضية هو تغيير رقعي. الإصدار الثانوي يُضيف موارد جديدة. الإصدار الرئيسي يكسر الواجهة أو يزيل موارد. عند دمج رفعة رئيسية، افتح قضية تتبّع تسرد كل بيئة لا تزال على الإصدار القديم، وحدّد موعد انتهاء صلاحية 60 يوماً.
تُنشئ استراتيجية الحالة وكتالوج الوحدات معاً حلقة فضيلة: لأن كل وحدة جذرية صغيرة (طبقة واحدة، بيئة واحدة)، تكون الخطط سريعة (أقل من 30 ثانية لوحدة workload)، وتعمل سياسات Conftest على JSON الخطة قبل أن يوافق أي إنسان. تنكشف دلو S3 المُهيَّأة بشكل خاطئ أو العلامة المطلوبة المفقودة بواسطة conftest test --policy policy/ plan.json في خط أنابيب طلب السحب، لا في وقت التطبيق، وبالتأكيد لا في الإنتاج.
مع استقرار هذا الأساس IaC، تُوفّر الدرس التالي منصة Kubernetes فوقه — تكوين مجموعة EKS وإدارة الإضافات عبر Helm وTerraform، ومُوسِّع العقد Karpenter الذي يجعل طبقة الحوسبة مرنة على نطاق فائق.