الدروس المستفادة من اختبار أكثر من 200000 سطر من كود البنية التحتية


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


النسخة الروسية


إنها ترجمة خطابي ( فيديو RU ) في DevopsConf 2019-05-28 .



البنية التحتية كتاريخ باش



دعونا نتخيل أنك تدخل في مشروع وتسمع شيئًا مثل: "نحن نستخدم البنية التحتية كنهج رمز ". لسوء الحظ ، ما يعنيه حقًا هو البنية التحتية كتاريخ bash أو وثائق مثل bash history . هذا هو الوضع الحقيقي تقريبا. على سبيل المثال ، وصف دينيس ليسينكو هذا الموقف في كلمته حول كيفية استبدال البنية التحتية والتوقف عن القلق (RU) . شارك دينيس القصة حول كيفية تحويل سجل bash إلى بنية تحتية راقية.


دعونا نتحقق من تعريف شفرة المصدر: a text listing of commands to be compiled or assembled into an executable computer program . إذا كنا نريد أن نقدم البنية التحتية كسجل باش مثل رمز. هذا هو النص وقائمة الأوامر. يصف كيف تم تكوين الخادم. علاوة على ذلك ، فهو:


  1. Reproducible : يمكنك الحصول على محفوظات bash وتنفيذ الأوامر وربما الحصول على بنية تحتية عاملة.
  2. الإصدار : أنت تعرف من قام بتسجيل الدخول ومتى وما تم.
    لسوء الحظ ، إذا فقدت الخادم ، فلن تتمكن من فعل أي شيء لأنه لا يوجد سجل باش ، فقد فقدته مع الخادم.

ما يجب القيام به؟


البنية التحتية كرمز



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


DRY



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


  • SSH لاستضافة وتشغيل القيادة.
  • SCP ملف.
  • تعديل التكوين.
  • تشغيل الخدمة.
  • ...
  • PROFIT!

أعتقد أن اصنع CM ، وليس باش هو نهج جيد. ومع ذلك ، يتم استخدام bash فقط في الحالات القصوى والمحدودة ، كما في بداية المشروع. لذلك ، كان باش اختيارًا جيدًا ومعقولًا في بداية المشروع. كان الوقت يدق. كنا نواجه طلبات مختلفة لإنشاء عمليات تثبيت جديدة بتكوين مختلف قليلاً. كنا نعمل على تثبيت SSHing في عمليات التثبيت ، ونقوم بتشغيل الأوامر لتثبيت جميع البرامج المطلوبة ، وتحرير ملفات التكوين عن طريق البرامج النصية ، وأخيرا تكوين SDS عبر واجهة برمجة تطبيقات Web HTTP rest. بعد كل ذلك تم تكوين التثبيت والعمل. كانت هذه ممارسة شائعة إلى حد ما ، ولكن كان هناك الكثير من البرامج النصية للباش وأصبح منطق التثبيت أكثر تعقيدًا كل يوم.


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


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



هناك طريقة تجفيف (لا تكرر نفسك). الفكرة الرئيسية هي إعادة استخدام الكود الموجود بالفعل. يبدو بسيطا للغاية. في حالتنا ، كان DRY يعني: تقسيم التكوينات والبرامج النصية.


الصلبة ل CFM



كان المشروع ينمو ، نتيجة لذلك ، قررنا استخدام Ansible. كانت هناك أسباب لذلك:


  1. باش لا ينبغي أن يحتوي على منطق معقد .
  2. كان لدينا قدر من الخبرة في Ansible.

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


مبدأ المسؤولية الفردية



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


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


المبادئ المفتوحة مغلقة



يجب أن تكون كيانات البرامج ... مفتوحة للتمديد ، لكن يجب إغلاقها للتعديل.


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


مبدأ استبدال Liskov



يجب أن تكون الكائنات في برنامج قابلة للاستبدال مع مثيلات أنواعها الفرعية دون تغيير صحة ذلك البرنامج.


لنكن متفتحين. SOLID من الممكن استخدامها في CFM بشكل عام ، لم يكن مشروعًا محظوظًا. أود أن أصف مشروعًا آخر. وهو حل خارج الصندوق. وهو يدعم قواعد بيانات مختلفة وخوادم التطبيقات وواجهات التكامل مع أنظمة الجهات الخارجية. سأستخدم هذا المثال لوصف بقية SOLID


على سبيل المثال ، في حالتنا ، هناك اتفاق داخل فريق البنية التحتية: إذا قمت بنشر دور ibm java أو oracle java أو openjdk ، فسيكون لديك ثنائي java قابل للتنفيذ. نحن في حاجة إليها لأن أدوار Ansible ذات المستوى الأعلى تعتمد على ذلك. أيضًا ، يسمح لنا بتبديل تطبيق java دون تعديل منطق تثبيت التطبيق.


لسوء الحظ ، لا يوجد سكر بناء جملة لذلك في Ansible playbooks. هذا يعني أنه يجب عليك وضعه في الاعتبار أثناء تطوير أدوار Ansible.


مبدأ فصل الواجهة



العديد من واجهات العميل الخاصة أفضل من واجهة للأغراض العامة.


في البداية ، كنا نضع منطق تثبيت التطبيق في قواعد اللعبة المنفردة ، ونحاول تغطية جميع الحالات وقطع الحواف. لقد واجهنا المشكلة التي يصعب الحفاظ عليها ، لذلك قمنا بتغيير نهجنا. لقد فهمنا أن العميل يحتاج إلى واجهة منا (أي https في 443 منفذًا) وتمكنا من الجمع بين أدوارنا Ansible لكل بيئة محددة.


مبدأ انعكاس التبعية



يجب على المرء أن "يعتمد على التجريد ، وليس على التململ".


  • يجب ألا تعتمد الوحدات عالية المستوى على الوحدات منخفضة المستوى. يجب أن يعتمد كلاهما على التجريد (مثل واجهات).
  • يجب ألا تعتمد التجريدات على التفاصيل. يجب أن تعتمد التفاصيل (تطبيقات ملموسة) على التجريد.

أود أن أصف هذا المبدأ عبر النمط المضاد.


  1. كان هناك عميل مع سحابة خاصة.
  2. كنا نطلب VMs في السحابة.
  3. كان منطق النشر الخاص بنا يعتمد على برنامج hypervisor الذي يوجد به جهاز VM.

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


تفاعل



البنية التحتية ليست رمزًا فقط ، بل أيضًا حول رمز التفاعل <-> DevOps و DevOps <-> DevOps و IaC <-> الأشخاص.


عامل الحافلة



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


زوج DevOpsing



هو مثل البرمجة الزوج. بمعنى آخر ، هناك مهندسان من DevOps ويستخدمون لوحة مفاتيح للكمبيوتر المحمول واحدة لتكوين البنية التحتية: تكوين الخادم ، وإنشاء دور Ansible ، إلخ. يبدو رائعا ، ومع ذلك ، لم تنجح بالنسبة لنا. كانت هناك بعض الحالات المخصصة عندما عملت جزئيا.


  • Onboarding : يحصل المعلمون والشخص الجديد على مهمة حقيقية من العمل المتراكم والعمل معًا - نقل المعرفة من معلمه إلى الشخص.
  • نداء الحادث : أثناء استكشاف الأخطاء وإصلاحها ، هناك مجموعة من المهندسين ، يبحثون عن حل. النقطة الأساسية هي أن هناك شخص يقود هذا الحادث. يشارك الشخص الشاشة والأفكار. يتبعه أشخاص آخرون بعناية ويلاحظون حيل باش والأخطاء وسجلات تحليل الخ.

مراجعة الكود



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


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

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


رمز النمط



كان الوقت يمر ، كنا نناقش في بعض الأحيان أثناء المراجعة لأن المراجع والمرسل قد يستخدمان نمطًا مختلفًا من التعليمات البرمجية: 2 مسافات أو 4 أو camelCase أو snake_case . قمنا بتنفيذها ، ومع ذلك ، لم يكن نزهة.


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

سيد البناء الأخضر



بعد ذلك ، كانت الخطوة الأكثر إيلاما هي تقييد الدفع إلى الفرع الرئيسي للجميع. فقط عن طريق دمج الطلبات والاختبارات الخضراء يجب أن تكون على ما يرام. وهذا ما يسمى الأخضر بناء ماستر . بمعنى آخر ، أنت متأكد بنسبة 100٪ من إمكانية نشر البنية الأساسية الخاصة بك من الفرع الرئيسي. إنها ممارسة شائعة جدًا في تطوير البرامج:


  • يوجد مستودع يحتوي على وصف البنية الأساسية الخاصة بك.
  • الجميع يقومون بتغييراتهم في فرع مخصص.
  • لكل فرع ، نحن نجري اختبارات.
  • لا يمكنك الدمج في الفرع الرئيسي في حالة فشل الاختبارات.

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


اختبار IAC



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


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


IaC اختبار الهرم



اختبار IaC: تحليل ثابت


يمكنك إنشاء البنية الأساسية بأكملها من نقطة الصفر لكل التزام ، ولكن عادةً ما توجد بعض العقبات:


  • الثمن هو الستراتوسفير.
  • يتطلب الكثير من الوقت.

نأمل أن هناك بعض الحيل. يجب أن يكون لديك الكثير من الاختبارات البسيطة والسريعة والبدائية في مؤسستك.


باش صعب


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


  • الحصول على جميع الملفات من الدليل الحالي.
  • انسخ الملفات إلى دليل آخر باسم معدل.

الفكرة الأولى هي:


 for i in * ; do cp $i /some/path/$i.bak done 

جيد جدا ومع ذلك ، ماذا لو كان اسم الملف يحتوي على مساحة ؟ نحن شباب ذكيون ، نستخدم علامات الاقتباس:


 for i in * ; do cp "$i" "/some/path/$i.bak" done 

هل انتهينا؟ كلا! ماذا لو كان الدليل فارغ؟ فشل Globing في هذه الحالة.


 find . -type f -exec mv -v {} dst/{}.bak \; 

هل انتهينا؟ ليس بعد ... لقد نسينا أن اسم الملف قد يحتوي على حرف \n .


 touch x mv x "$(printf "foo\nbar")" find . -type f -print0 | xargs -0 mv -t /path/to/target-dir 

أدوات التحليل الثابت


يمكنك التقاط بعض المشكلات من المثال السابق عبر Shellcheck . هناك الكثير من الأدوات المشابهة لذلك ، يطلق عليها اسم linters ويمكنك معرفة الأنسب لمعرفك IDE ، والمكدس ، والبيئة.


لغةأداة
سحقShellcheck
ياقوتRuboCop
الثعبانPylint
Ansibleالوبر الشبق

اختبار IAC: اختبارات الوحدة



كما ترون لا يمكن للسجاد التقاط كل شيء ، يمكنهم التنبؤ فقط. إذا واصلنا التفكير في أوجه التشابه بين تطوير البرمجيات والبنية التحتية ككود ، فيجب أن نذكر اختبارات الوحدات. هناك الكثير من أنظمة اختبارات الوحدات مثل shunit و JUnit و RSpec و pytest . ولكن هل سمعت عن اختبارات وحدة Ansible ، الشيف ، Saltstack ، CFengine؟


عندما كنا نتحدث عن SOLID for CFM ، ذكرت أن بنيتنا الأساسية يجب أن تكون مصنوعة من الطوب / الوحدات البسيطة. الآن حان الوقت:


  1. قسّم البنية التحتية إلى وحدات / فواصل بسيطة ، أي أدوار غير مرئية.
  2. إنشاء بيئة أي عامل الميناء أو VM.
  3. قم بتطبيق استراحة / وحدة واحدة بسيطة على البيئة.
  4. تأكد من أن كل شيء على ما يرام أم لا.
    ...
  5. PROFIT!

اختبار IaC: أدوات اختبار الوحدة


ما هو اختبار CFM والبنية التحتية الخاصة بك؟ أي يمكنك فقط تشغيل برنامج نصي أو يمكنك استخدام حل جاهز للإنتاج مثل:


CFMأداة
AnsibleTestinfra
طاهINSPEC
طاهServerspec
saltstackجوس

دعونا نلقي نظرة على testinfra ، أود أن أتحقق من أن المستخدمين test1 ، test2 موجودون وأنهم جزء من مجموعة sshusers :


 def test_default_users(host): users = ['test1', 'test2' ] for login in users: assert host.user(login).exists assert 'sshusers' in host.user(login).groups 

ما هو الحل الامثل؟ لا توجد إجابة واحدة لهذا السؤال ، ومع ذلك ، فقد قمت بإنشاء خريطة الحرارة وقارنت التغييرات في هذه المشاريع خلال 2018-2019:



أطر اختبار IaC


بعد ذلك ، يمكنك مواجهة سؤال حول كيفية تشغيله معًا؟ من ناحية ، يمكنك أن تفعل كل شيء بمفردك إذا كان لديك عدد كبير من المهندسين ، ولكن من ناحية أخرى ، يمكنك استخدام حلول جاهزة للإنتاج مفتوحة المصدر:


CFMأداة
Ansibleجزيء
طاهاختبار المطبخ
TerraformTerratest

قمت بإنشاء خريطة الحرارة وقارنت التغييرات في هذه المشاريع خلال 2018-2019:



جزيء مقابل Testkitchen



في البداية ، حاولنا اختبار الأدوار غير المرئية عبر testkitchen داخل hyper-v :


  1. إنشاء VMs.
  2. تطبيق الأدوار Ansible.
  3. تشغيل Inspec.

استغرق الأمر 40-70 دقيقة لأدوار Ansible 25-35. كان طويلاً للغاية بالنسبة لنا.



كانت الخطوة التالية استخدام جنكينز / عامل ميناء / Ansible / جزيء. إنها نفس الفكرة تقريبًا:


  1. لينت Ansible playbooks.
  2. لينت Ansible الأدوار.
  3. تشغيل حاوية عامل ميناء.
  4. تطبيق الأدوار Ansible.
  5. تشغيل testinfra.
  6. تحقق العاطفة.


استغرق البحث عن 40 أدوار واختبار عشرة منهم حوالي 15 دقيقة.



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


اختبار IAC: اختبارات التكامل



على المستوى التالي من هرم اختبار IaC ، هناك اختبارات التكامل . اختبارات التكامل للبنية التحتية تبدو وكأنها اختبارات للوحدة:


  1. قسّم البنية التحتية إلى وحدات / فواصل بسيطة ، أي أدوار غير مرئية.
  2. إنشاء بيئة أي عامل الميناء أو VM.
  3. تطبيق مزيج من كسر بسيط / وحدة للبيئة.
  4. تأكد من أن كل شيء على ما يرام أم لا.
    ...
  5. PROFIT!

بمعنى آخر ، أثناء اختبارات الوحدة ، نتحقق من وحدة واحدة بسيطة (أي دور Ansible ، برنامج نصي بيثون ، وحدة Ansible ، إلخ) للبنية التحتية ، ولكن في حالة اختبارات التكامل ، نتحقق من تكوين الخادم بالكامل.


اختبار IAC: اختبارات نهاية إلى نهاية



على رأس هرم اختبار IaC ، هناك اختبارات نهاية إلى نهاية . في هذه الحالة ، لا نتحقق من الخادم المخصص أو البرنامج النصي أو وحدة البنية التحتية الخاصة بنا ؛ نحن نتحقق من أن البنية التحتية بأكملها تعمل معًا بشكل صحيح. لسوء الحظ ، لا يوجد حل خارج النطاق لذلك أو لم أسمع عنها (من فضلك ، أخبرني إذا كنت تعرف عنها). عادةً ما يعيد الناس اختراع العجلة ، لأنه يوجد طلب على اختبارات نهاية للبنية التحتية. لذلك ، أود أن أشارك تجربتي ، آمل أن تكون مفيدة لشخص ما.



بادئ ذي بدء ، أود أن أصف السياق. إنه حل خارج المؤسسة ، وهو يدعم قواعد بيانات مختلفة وخوادم التطبيقات وواجهات التكامل مع أنظمة الجهات الخارجية. عادة ، عملائنا هم مؤسسة ضخمة مع بيئة مختلفة تماما. لدينا معرفة بتركيبات بيئات مختلفة ونخزنها كملفات تكوين لرسو السفن المختلفة. أيضًا ، هناك تطابق بين ملفات docker-compose والاختبارات ، نقوم بتخزينها في وظائف Jenkins.



كان هذا المخطط يعمل فترة سجل هادئة من الوقت عندما حاولنا خلال بحث openhift ترحيله إلى Openshift. استخدمنا نفس الحاويات تقريبًا (الجحيم DRY مرة أخرى) وقمنا بتغيير البيئة المحيطة فقط.



نواصل البحث ووجدنا APB (Ansible Playbook Bundle). الفكرة الرئيسية هي أن تقوم بحزم كل الأشياء المطلوبة في حاوية وتشغيل الحاوية داخل Openshift. فهذا يعني أن لديك حل قابل للتكرار وقابل للاختبار.



كان كل شيء على ما يرام حتى واجهنا مشكلة أخرى: كان علينا الحفاظ على بنية تحتية غير متجانسة لاختبار البيئات. نتيجة لذلك ، فإننا نخزن معرفتنا بكيفية إنشاء البنية التحتية وإجراء الاختبارات في وظائف Jenkins.


استنتاج



البنية التحتية كرمز هي مزيج من:


  • التعليمات البرمجية.
  • تفاعل الناس.
  • اختبار البنية التحتية.

Source: https://habr.com/ru/post/ar467169/


All Articles