Terraform والمستودعات الأحادية والامتثال كرمز

تحية للجميع. فتحت OTUS التوظيف لمجموعة جديدة في الدورة "منصة البنية التحتية القائمة على Kubernetes" ، فيما يتعلق بهذا قمنا بإعداد ترجمة لمواد مثيرة للاهتمام حول هذا الموضوع.




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


ربما المشكلة في أنفسنا؟

يجب أن تخلق الشفرة المكتوبة قيمة أو تحل مشكلة ما ، كما يمكن إعادة استخدامها في إلغاء البيانات المكررة. عادةً ما ينتهي هذا النوع من المناقشة بـ "دعونا نستخدم الوحدات" . نحن جميعًا نستخدم وحدات Terraform ، أليس كذلك؟ يمكنني أن أكتب العديد من القصص مع المشاكل بسبب الوحدات النمطية المفرطة ، لكن هذه قصة مختلفة تمامًا ، ولن أفعل ذلك.


لا لن أفعل. لا تصر ، لا ... حسنًا ، ربما لاحقًا.

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

... ولكن ماذا عن التبعيات؟ ماذا لو كان لدي 120 وحدة في 120 مستودعات مختلفة ، وتغيير وحدة واحدة يؤثر على 20 وحدة أخرى. هل هذا يعني أننا بحاجة إلى القيام بطلبات سحب 20 + 1 ؟ إذا كان الحد الأدنى لعدد المراجعين 2 ، فهذا يعني 21 × 2 = 44مراجعة. بجدية! نقوم ببساطة بشل الأمر عن طريق "تغيير وحدة واحدة" وسيبدأ الجميع في إرسال الميمات أو صور متحركة من Lord of the Rings ، وسيضيع بقية اليوم.


PR واحدة لإخطار الجميع ، PR واحدة لجمع الجميع معا ، تكبيل والغطس في الظلام

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

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

في هذه الحالة ، ليست المشكلة "كيف تعمل" ، ولكن "ما هو هيكل مستودعات git الخاصة بك" .



هذا مشابه لما شعرت به عندما طبقت الاقتراح أدناه لأول مرة.

دعنا نعود إلى الأساسيات. ما هي المتطلبات العامة لمستودع مع وحدات Terraform؟

  1. يجب وضع علامة عليه حتى لا تكون هناك تغييرات كسر.
  2. يجب أن يكون أي تغيير قادرًا على الاختبار.
  3. يجب أن تخضع التغييرات لمراجعة متبادلة.

ثم أقترح ما يلي - لا تستخدم المستودعات الصغيرة لوحدات Terraform. استخدم مستودعًا أحاديًا .

  • يمكنك وضع علامة على المستودع بالكامل عندما يكون هناك تغيير / متطلب
  • يمكن اختبار أي تغيير أو علاقات عامة أو دفع.
  • يمكن لأي تغيير أن يمر بالمراجعة.


لدي قوة!

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


مثال هيكل الدليل لمستودع أحادي. راجع تغيير tag_override؟

وبالتالي ، فإن تغيير الوحدة النمطية الذي يؤثر على 20 وحدة أخرى هو 1 PR فقط ! حتى إذا قمت بإضافة 5 مراجعين إلى هذه العلاقات العامة ، فستكون المراجعة سريعة جدًا مقارنة بالمستودعات الصغيرة. إذا كنت تستخدم Github ، فهذا أفضل! يمكنك استخدام CODEOWNERS للوحدات النمطية التي لديها مشرفون / مالكون ، ويجب أن يوافق هذا المالك على أي تغييرات تطرأ على هذه الوحدات.

عظيم ، ولكن كيف تستخدم مثل هذه الوحدة ، التي تقع في دليل المستودع الأحادي؟

سهل:

module "from_mono_repo" {
 source = "git::ssh://.../<org>/<repo>.git//<my_module_dir>"
 ...
}
module "from_mono_repo_with_tags" {
  source = "git::ssh://..../<org>/<repo>.git//<mod_dir>?ref=1.2.4"
  ...
}
module "from_micro_repo" {
  source = "git::ssh://.../<org>/<mod_repo>.git"
  ...
}
module "from_micro_repo_with_tags" {
  source = "git::ssh://.../<org>/<mod_repo>.git?ref=1.2.4"
  ...
}

ما هي عيوب هذا النوع من الهياكل؟ حسنًا ، إذا حاولت اختبار "كل وحدة" باستخدام PR / change ، فيمكنك الحصول على 1.5 ساعة من خطوط الأنابيب CI. تحتاج إلى العثور على الوحدات المعدلة في العلاقات العامة. أفعل ذلك على هذا النحو:

changed_modules=$(git diff --name-only $(git rev-parse origin/master) HEAD | cut -d "/" -f1 | grep ^aws- | uniq)

هناك عيب آخر: عندما تقوم بتشغيل "terraform init" ، فإنه يقوم بتحميل المستودع بأكمله في دليل .terraform. ولكن لم يسبق لي أن واجهت مشكلة مع هذا ، حيث أقوم بتشغيل الأنابيب الخاصة بي في حاويات AWS CodeBuild قابلة للتطوير. إذا كنت تستخدم Jenkins و Jenkins Slaves المستمر ، فقد تكون لديك هذه المشكلة.


لا تجعلنا نبكي.

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

بصراحة ، بعد العمل في هذا الوضع ، يجب اعتبار اقتراح استخدام المستودعات الصغيرة لوحدات التضاريس بمثابة جريمة.

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

للتحقق من هوية الرمز ، يوفر terraform معلمة ممتازة تسمى -detailed-exitcode. فقط قم بتشغيل:

> terraform plan -detailed-exitcode

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

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

على سبيل المثال ، لا يُسمح لأحد بإنشاء مجموعة S3 عامة غير مشفرة .

وبالتالي ، فبدلاً من التحقق مما إذا كان قد تم إنشاء مجموعة S3 بالفعل ، في الواقع ، بناءً على مجموعة من السياسات ، تحقق لمعرفة ما إذا كانت التعليمات البرمجية الخاصة بك تقوم بإنشاء مورد أم لا. كيف افعلها؟ يوفر Terraform Enterprise أداة رائعة لهذا ، Sentinel .

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

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


شعار التوافق مع Terraform

أولاً وقبل كل شيء ، يستخدم التوافق مع Terraform التنمية السلوكية (BDD).

Feature: Ensure that we have encryption everywhere.

    Scenario: Reject if an S3 bucket is not encrypted
        Given I have aws_s3_bucket defined
        Then it must contain server_side_encryption_configuration

تحقق مما إذا كان التشفير ممكّنًا.

إذا لم يكن ذلك كافيًا لك ، يمكنك الكتابة بمزيد من التفاصيل:

Feature: Ensure that we have encryption everywhere.

    Scenario: Reject if an S3 bucket is not encrypted with KMS
        Given I have aws_s3_bucket defined
        Then it must contain server_side_encryption_configuration
        And it must contain rule
        And it must contain apply_server_side_encryption_by_default
        And it must contain sse_algorithm
        And its value must match the "aws:kms" regex

نتعمق أكثر ونتحقق من استخدام KMS للتشفير.

رمز terraform لهذا الاختبار:

resource "aws_kms_key" "mykey" {
 description             = "This key is used to encrypt bucket objects"
 deletion_window_in_days = 10
}

resource "aws_s3_bucket" "mybucket" {
 bucket = "mybucket"

 server_side_encryption_configuration {
   rule {
     apply_server_side_encryption_by_default {
       kms_master_key_id = "${aws_kms_key.mykey.arn}"
       sse_algorithm     = "aws:kms"
     }
   }
 }
}

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

لمزيد من المعلومات حول التوافق مع التضاريس ، انظر هذا العرض التقديمي .

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

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

لذلك ، عند استخدام terraform ، نقوم ببناء مستودعات git على النحو التالي:



بالطبع ، هذا متغطرس جدًا. لكني كنت محظوظًا (أو لست محظوظًا؟) للعمل مع هيكل أكثر تفصيلاً في العديد من المنظمات. لسوء الحظ ، لم ينتهي كل هذا بشكل جيد للغاية. يجب إخفاء النهاية السعيدة في الرقم 3.

اسمحوا لي أن أعرف إذا كان لديك أي قصص نجاح مع المستودعات الصغيرة ، فأنا مهتم حقًا!



ندعوك إلى درس مجاني ، حيث سننظر في مكونات منصة البنية التحتية المستقبلية ونرى كيفية تقديم طلبنا بشكل صحيح .

All Articles