تُعَد إدارة ضبط الخادم (يُشار إليها أيضًا باسم أتمتة تقانة المعلومات IT Automation) حلًا لتحويل إدارة بنيتك التحتية إلى الشيفرة البرمجية الأساسية، ولوصف جميع العمليات اللازمة لنشر خادم في مجموعة من سكربتات الإعداد المسبق Provisioning Scripts التي يمكن إصدارها وإعادة استخدامها بسهولة، ويمكنها تحسين التكامل لأيّ بنية خادم تحتية بصورة كبيرة بمرور الوقت.
تحدثنا في مقال سابق عن الفوائد الرئيسية لتنفيذ إستراتيجية إدارة الضبط لبنية الخادم التحتية، وكيفية عمل أدوات إدارة الضبط والعناصر المشتركة بين هذه الأدوات. سنوضح في هذا المقال عملية أتمتة إعداد الخادم المسبق باستخدام الأداة Chef، وهي أداة قوية لإدارة الضبط تستفيد من لغة برمجة روبي Ruby لأتمتة إدارة البنية التحتية وإعدادها المسبق، وسنركز على مصطلحات اللغة والصياغة والميزات اللازمة لإنشاء مثال مبسّط للأتمتة الكاملة لنشر خادم ويب Ubuntu 18.04 باستخدام أباتشي Apache.
تحتوي القائمة التالية على جميع الخطوات التي نحتاجها للأتمتة حتى الوصول إلى هدفنا:
-
حدّث ذاكرة
apt
المخبئية. - ثبّت أباتشي Apache.
- أنشئ مجلد المستند الجذر المُخصَّص.
-
ضع ملف
index.html
في المستند الجذر المخصص. - طبّق قالبًا لإعداد المضيف الوهمي المخصص.
- أعِد تشغيل أباتشي.
سنبدأ بإلقاء نظرة على المصطلحات التي تستخدمها أداة Chef، ثم سنتعرّف على ميزات اللغة الرئيسية التي يمكن استخدامها لكتابة الوصفات Recipes، وسنشاركك في النهاية المثال الكامل لتتمكّن من تجربته بنفسك.
ملاحظة: يهدف هذا المقال إلى تعريفك بلغة Chef وكيفية كتابة الوصفات لأتمتة إعداد خادمك المسبق. اطّلع على كيفية ضبط الأداة Chef لمعرفة الخطوات اللازمة لتثبيت هذه الأداة والبدء باستخدامها.
هذا المقال جزء من سلسلة حول إدارة ضبط الخوادم، وإليك روابط فصول السلسلة:
- مدخل إلى إدارة ضبط الخوادم Configuration Management
- مبادئ إدارة ضبط الخوادم Configuration Management: كتابة دليل تشغيل الأداة Ansible
- مبادئ إدارة ضبط الخوادم Configuration Management: كتابة ملفات البيان Manifests للأداة Puppet
- مبادئ إدارة ضبط الخوادم Configuration Management: كتابة الوصفات Recipes في الأداة Chef
البدء باستخدام الأداة Chef
يجب أن نتعرف أولًا على المصطلحات والمفاهيم المهمة التي قدمتها الأداة Chef قبل البدء بالعمل.
مصطلحات Chef
- خادم Chef: خادم مركزي يخزن المعلومات ويدير الإعداد المُسبق provisioning للعقد nodes.
- عقدة Chef: خادم فردي يديره خادم Chef.
- محطة عمل Chef: جهاز متحكِّم يُنشَأ فيه الإعداد المسبق ويُحمَّل على خادم Chef.
- الوصفة Recipe: ملف يحتوي على مجموعة من التعليمات (الموارد) لتنفيذها، إذ يجب أن تكون الوصفة موجودة في الدليل Cookbook.
- المورد Resource: جزء من الشيفرة البرمجية الذي يصرّح عن عنصر في النظام والإجراء الذي يجب تنفيذه، فمثلًا نصرّح عن مورد حزمة package مع إجراء التثبيت لتثبيت حزمةٍ ما.
- الدليل Cookbook: مجموعة من الوصفات والملفات الأخرى ذات الصلة المنظمة بطريقة مُعرَّفة مسبقًا لتسهيل مشاركة وإعادة استخدام أجزاء من الإعداد المسبق.
- السمات Attributes: هي تفاصيل حول عقدة معينة يمكن أن تكون السمات مؤتمتة، ويمكن تعريفها ضمن الوصفات.
- السمات المؤتمتة Automatic Attributes: هي المتغيرات العامة التي تحتوي على معلومات حول النظام مثل واجهات الشبكة ونظام التشغيل (المعروفة بالحقائق Facts في الأدوات الأخرى)، وتُجمَع هذه السمات المؤتمتة باستخدام أداة تسمى Ohai.
- الخدمات: تُستخدَم لبدء تغييرات حالة الخدمة مثل إعادة تشغيل الخدمة أو إيقافها.
تنسيق الوصفة Recipe
تُكتَب وصفات Chef باستخدام لغة روبي Ruby، والوصفة هي مجموعة من تعريفات الموارد التي ستنشئ مجموعة من التعليمات خطوة بخطوة لتنفّذها العقد، ويمكن مزج تعريفات الموارد مع شيفرة روبي البرمجية لمزيد من المرونة والتقسيم إلى وحدات Modularity.
إليك مثال بسيط لوصفة ستشغِّل apt-get update
ثم تثبّت vim
:
execute "apt-get update" do command "apt-get update" end apt_package "vim" do action :install end
كتابة الوصفات Recipes
أصبحت الآن على دراية بالمصطلحات الأساسية والتنسيق العام للوصفات في Chef، لذا سنتعرف على بعض ميزات الوصفات.
التعامل مع المتغيرات
يمكن تعريف المتغيرات المحلية ضمن الوصفات بوصفها متغيرات روبي المحلية العادية، حيث يوضح المثال التالي كيفية إنشاء متغير محلي يُستخدَم ضمن تعريف المورد لاحقًا:
package = "vim" apt_package package do action :install end
لهذه المتغيرات نطاق محدود، وتكون صالحة فقط ضمن الملف الذي عُرِّفت فيه، لذلك إذا أردتَ إنشاء متغير وإتاحته بصورة عامة، بحيث يمكنك استخدامه من أيٍّ من أدلتك أو وصفاتك، فيجب تعريف سمة مُخصَّصة.
استخدام السمات Attributes
تمثل السمات تفاصيلًا حول العقدة، حيث تحتوي أداة Chef على سمات مؤتمتة، وهي سمات تجمعها أداة تسمى Ohai وتحتوي على معلومات حول النظام (مثل المنصة واسم المضيف وعنوان IP الافتراضي)، ولكنها تتيح لك تعريف سماتك المُخصَّصة. للسمات مستويات أولوية مختلفة تُحدَّد حسب نوع السمة التي تنشِئها، تُعَد السمات default
الاختيار الأكثر شيوعًا، حيث لا يزال ممكنًا تعديلها لتكون أنواع سمات أخرى عند الرغبة في ذلك.
يوضح المثال التالي كيف سيبدو المثال السابق مع سمة العقدة default
بدلًا من متغير محلي:
node.default['main']['package'] = "vim" apt_package node['main']['package'] do action :install end
الممارسة الموصَى بها عند تعريف متغيرات العقدة هي تنظيمها بوصفها قيمًا مُعمَّاة مختصَرة Hashes باستخدام الدليل Cookbook الحالي المستخدَم بوصفه مفتاحًا. استخدمنا main
في حالتنا، لأن لدينا دليل بالاسم نفسه، مما يؤدي إلى تجنب الارتباك إذا أردت العمل مع أدلة متعددة يكون لها سمات بأسماء متماثلة. لاحظ أننا استخدمنا node.default
عند تعريف السمة، ولكن استخدمنا node
مباشرةً عند الوصول إلى قيمتها لاحقًا. يحدِّد استخدام node.default
أننا ننشئ سمة من النوع الافتراضي، ويمكن تعديل قيمة هذه السمة لتكون نوع سمة آخر ذي أولوية أعلى مثل السمات العادية normal
أو سمات التجاوز override
.
يمكن أن تكون أولوية السمات مربكة بعض الشيء في البداية، ولكنك ستعتادها بعد التدريب عليها، ولتوضيح هذا السلوك اطّلع على المثال التالي:
node.normal['main']['package'] = "vim" node.override['main']['package'] = "git" node.default['main']['package'] = "curl" apt_package node['main']['package'] do action :install end
الحزمة التي ستُثبَّت في المثال السابق هي الحزمة git
، إذ ستجعل الأولوية الأعلى للنوع override
تقييم node['main']['package']
ليكون git
بغض النظر عن ترتيب تعريف السمات.
استخدام الحلقات Loops
تُستخدَم الحلقات عادةً لتكرار مهمة باستخدام قيم دخل مختلفة، فمثلًا يمكنك إنشاء مهمة واحدة واستخدام حلقة لتكرار المهمة مع جميع الحزم المختلفة التي تريد تثبيتها بدلًا من إنشاء 10 مهام لتثبيت 10 حزم مختلفة. تدعم Chef جميع بنى حلقات روبي لإنشاء حلقات ضمن الوصفات، حيث تُعَد تعليمة each
خيارًا شائعًا للاستخدام البسيط:
['vim', 'git', 'curl'].each do |package| apt_package package do action :install end end
يمكنك إنشاء متغير أو سمة لتعريف المعاملات التي تريد استخدامها ضمن الحلقة بدلًا من استخدام مصفوفة مُضمَّنة، مما يجعل الأشياء أكثر تنظيمًا وأسهل في القراءة. يستخدم المثال السابق نفسه متغيرًا محليًا لتعريف الحزم التي يجب تثبيتها فيما يلي:
packages = ['vim', 'git', 'curl'] packages.each do |package| apt_package package do action :install end end
استخدام التعليمات الشرطية
يمكن استخدام التعليمات الشرطية لتحديد ما إذا كان يجب تنفيذ كتلة من الشيفرة البرمجية أم لا ديناميكيًا بناءً على متغير أو خرج أمرٍ ما مثلًا. تدعم الأداة Chef جميع تعليمات روبي الشرطية لإنشاء تعليمات شرطية ضمن الوصفات، وتدعم جميع أنواع الموارد خاصيتين تقيّيمان تعبيرًا قبل تحديد ما إذا كان يجب تنفيذ المهمة أم لا وهما: if_only
و not_if
.
سيتحقق المثال التالي من وجود php
قبل محاولة تثبيت التوسّع php-pear
، إذ سيستخدم الأمر which
للتحقق مما إذا كان هناك ملف php
تنفيذي مُثبَّت حاليًا على هذا النظام، فإذا أعاد الأمر which php
القيمة false
، فلن تُنفَّذ هذه المهمة:
apt_package "php-pear" do action :install only_if "which php" end
إذا أردنا تطبيق العكس أي تنفيذ أمر في جميع الأوقات باستثناء الوقت الذي يُقيَّم فيه الشرط على أنه true
، فسنستخدم التعليمة not_if
بدلًا من ذلك، حيث سيثبت المثال التالي php5
ما لم يكن النظام CentOS:
apt_package "php5" do action :install not_if { node['platform'] == 'centos' } end
لنطبّق الآن تقييمات أكثر تعقيدًا، فمثلًا إذا أردتَ تنفيذ عدة مهام وفق شرط محدّد، فيمكنك استخدام أيٍّ من تعليمات روبي الشرطية المعيارية. ينفّذ المثال التالي فقط apt-get update
عندما يكون النظام إما دبيان Debian أو أوبنتو Ubuntu:
if node['platform'] == 'debian' || node['platform'] == 'ubuntu' execute "apt-get update" do command "apt-get update" end end
تُعَد السمة node['platform']
سمة مؤتمتة من الأداة Chef، حيث استخدمنا المثال السابق فقط لتوضيح بنية شرطية أكثر تعقيدًا، ولكن يمكن استبدالها باختبار بسيط باستخدام السمة node['platform_family']
التي ستعيد "debian" لكل من نظامي دبيان وأوبنتو.
استخدام القوالب templates
تُستخدَم القوالب عادةً لإعداد ملفات الضبط، مما يسمح باستخدام المتغيرات والميزات الأخرى التي تهدف إلى جعل هذه الملفات أكثر تنوعًا وقابلية لإعادة الاستخدام. تستخدم الأداة Chef قوالب روبي المُضمَّنة Embedded Ruby -أو ERB اختصارًا، وهو التنسيق نفسه الذي تستخدمه الأداة Puppet، حيث تدعم هذه القوالب التعليمات الشرطية والحلقات والميزات الأخرى في لغة روبي.
يوضح المثال التالي قالب ERB لإعداد مضيف أباتشي الوهمي باستخدام متغير لتحديد المستند الجذر لهذا المضيف:
<VirtualHost *:80> ServerAdmin webmaster@localhost DocumentRoot <%= @doc_root %> <Directory <%= @doc_root %>> AllowOverride All Require all granted </Directory> </VirtualHost>
يجب إنشاء مورد template
لتطبيق القالب، ويوضح المثال التالي الطريقة التي ستطبِّق بها هذا القالب لاستبدال مضيف أباتشي الوهمي الافتراضي:
template "/etc/apache2/sites-available/000-default.conf" do source "vhost.erb" variables({ :doc_root => node['main']['doc_root'] }) action :create end
تضع الأداة Chef بعض الافتراضات عند التعامل مع الملفات المحلية لفرض التنظيم والتقسيم إلى وحدات Modularity، حيث ستبحث الأداة Chef عن ملف قالب vhost.erb
ضمن مجلد القوالب templates الذي يجب أن يكون في الدليل نفسه الذي توجد فيه هذه الوصفة.
تمتلك الأداة Chef نطاقًا أكثر صرامة للمتغيرات على عكس أدوات إدارة الضبط الأخرى التي رأيناها حتى الآن، وهذا يعني أنه يجب تقديم أيّ متغيرات تريد استخدامها ضمن القالب صراحةً عند تعريف المورد template
. استخدمنا في مثالنا التابع variables
لتمرير السمة doc_root
التي نحتاجها في قالب المضيف الوهمي.
تعريف وبدء الخدمات
تُستخدَم موارد الخدمة service للتأكد من تهيئة الخدمات وتفعيلها، ولبدء إعادة تشغيل الخدمة، ويجب التصريح عن موارد الخدمة في الأداة Chef قبل محاولة إعلامها، وإلّا فسيظهر خطأ.
لنأخذ المثال السابق لاستخدام القالب حيث ضبطنا مضيف أباتشي الوهمي. إذا أردتَ التأكد من إعادة تشغيل أباتشي بعد تغيير مضيف وهمي، فيجب أولًا إنشاء مورد خدمة service لخدمة أباتشي، ويوضح المثال التالي طريقة تعريف هذا المورد في Chef:
service "apache2" do action [ :enable, :start ] end
يجب الآن تضمين الخيار notify
لبدء إعادة التشغيل عند تعريف مورد القالب:
template "/etc/apache2/sites-available/000-default.conf" do source "vhost.erb" variables({ :doc_root => node['main']['doc_root'] }) action :create notifies :restart, resources(:service => "apache2") end
مثال عن وصفة Recipe
لنلقِ نظرة على الوصفة التي ستؤتمِت عملية تثبيت خادم ويب أباتشي على نظام لينكس أوبنتو Ubuntu كما ناقشنا سابقًا. يمكنك العثور على المثال الكامل بما في ذلك ملف القالب لإعداد أباتشي وملف HTML ليخدّمه خادم الويب على Github، ويحتوي المجلد على الملف Vagrantfile الذي يتيح لك اختبار الوصفة في إعداد مبسّط باستخدام آلة افتراضية تديرها أداة Vagrant.
إليك الوصفة الكاملة:
node.default['main']['doc_root'] = "/vagrant/web" execute "apt-get update" do command "apt-get update" end apt_package "apache2" do action :install end service "apache2" do action [ :enable, :start ] end directory node['main']['doc_root'] do owner 'www-data' group 'www-data' mode '0644' action :create end cookbook_file "#{node['main']['doc_root']}/index.html" do source 'index.html' owner 'www-data' group 'www-data' action :create end template "/etc/apache2/sites-available/000-default.conf" do source "vhost.erb" variables({ :doc_root => node['main']['doc_root'] }) action :create notifies :restart, resources(:service => "apache2") end
لنتعرّف على كل جزء من الوصفة السابقة بمزيد من التفصيل:
-
تبدأ الوصفة في السطر الأول بتعريف السمة
node['main']['doc_root']
، حيث كان بإمكاننا استخدام متغير محلي بسيط هنا، ولكن يجب أن تعرّف الوصفات المتغيرات العامة التي ستُستخدَم في الوصفات المُضمَّنة أو الملفات الأخرى في معظم حالات الاستخدام، لذا يجب إنشاء سمة بدلًا من متغير محلي، لأن المتغير المحلي له نطاق محدود. -
يشغّل مورد التنفيذ execute الأمرَ
apt-get update
في الأسطر 3-5. -
يثبّت المورد apt_package الحزمة
apache2
في الأسطر 7-10. -
يفعّل مورد الخدمة service ويبدأ الخدمة
apache2
في الأسطر 12-15، ويجب إعلام هذا المورد لاحقًا بإعادة تشغيل الخدمة، ويجب أن يأتي تعريف الخدمة قبل أيّ مورد يحاول إعلام الخدمة، وإلّا فستتلقّى خطأ. -
يستخدم المورد directory في الأسطر 17-22 القيمة التي تعرّفها السمة المخصصة
node['main']['doc_root']
لإنشاء مجلد يكون بمثابة المستند الجذر. -
يُستخدَم المورد cookbook_file في الأسطر 24-29 لنسخ ملف محلي إلى خادم بعيد، إذ سينسخ هذا المورد الملف
index.html
ويضعه في المستند الجذر الذي أنشأناه في مهمة سابقة. - يطبق مورد القالب template قالب مضيف أباتشي الوهمي ويعلِم خدمة apache2 بإعادة التشغيل في الأسطر 31-36.
الخلاصة
تُعَد Chef أداة قوية لإدارة الضبط وتستفيد من لغة روبي لأتمتة إعداد الخادم المسبق ونشره، وتمنحك حرية استخدام ميزات اللغة المعيارية لتحقيق أقصى قدر من المرونة مع توفير لغة DSL مُخصَّصة لبعض الموارد.
ترجمة -وبتصرُّف- للمقال Configuration Management 101: Writing Chef Recipes لصاحبته Erika Heidi.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.