اذهب إلى المحتوى

كتابة الوصفات Recipes في الأداة Chef لإدارة ضبط الخوادم


Ola Abbas

تُعَد إدارة ضبط الخادم (يُشار إليها أيضًا باسم أتمتة تقانة المعلومات IT Automation) حلًا لتحويل إدارة بنيتك التحتية إلى الشيفرة البرمجية الأساسية، ولوصف جميع العمليات اللازمة لنشر خادم في مجموعة من سكربتات الإعداد المسبق Provisioning Scripts التي يمكن إصدارها وإعادة استخدامها بسهولة، ويمكنها تحسين التكامل لأيّ بنية خادم تحتية بصورة كبيرة بمرور الوقت.

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

تحتوي القائمة التالية على جميع الخطوات التي نحتاجها للأتمتة حتى الوصول إلى هدفنا:

  1. حدّث ذاكرة apt المخبئية.
  2. ثبّت أباتشي Apache.
  3. أنشئ مجلد المستند الجذر المُخصَّص.
  4. ضع ملف index.html في المستند الجذر المخصص.
  5. طبّق قالبًا لإعداد المضيف الوهمي المخصص.
  6. أعِد تشغيل أباتشي.

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

ملاحظة: يهدف هذا المقال إلى تعريفك بلغة Chef وكيفية كتابة الوصفات لأتمتة إعداد خادمك المسبق. اطّلع على كيفية ضبط الأداة 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.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...