استخدام المتغيرات (Variables) والحلقات (Loops) داخل Ansible
مقدمة
عندما تبدأ ببناء Playbooks صغيرة في Ansible قد يبدو كل شيء بسيطاً: تثبيت حزمة، تشغيل خدمة، ونسخ ملف إعداد. لكن عند الانتقال إلى بيئات تشغيل حقيقية تضم عدة خوادم وأدوار متعددة وطبقات Web وApplication وDatabase، تصبح المتغيرات والحلقات أساساً لا غنى عنه لتقليل التكرار ورفع قابلية الصيانة.
فهم Variables وLoops لا يختصر عدد الأسطر فقط، بل يحول ملفات الأتمتة إلى بنية هندسية مرنة يمكن إعادة استخدامها داخل بيئات Development وStaging وProduction دون نسخ مكرر وخطر عالٍ للخطأ. وإذا كنت قرأت سابقاً مقال ما هو Ansible؟ وكيف تتحكم في 100 سيرفر Linux من حاسوبك المكتبي؟، فهذه المرحلة هي الانتقال من الاستخدام الأساسي إلى التصميم الاحترافي.
ما المقصود بالمتغيرات داخل Ansible؟
المتغيرات في Ansible هي قيم ديناميكية تُستخدم لتخصيص السلوك حسب الخادم أو البيئة أو التطبيق. بدلاً من كتابة اسم الحزمة أو رقم المنفذ أو اسم المستخدم بشكل ثابت داخل كل Task، يمكن حفظها في متغير واستدعاؤها في أي موضع.
هذه الفكرة مهمة جداً في بيئات Infrastructure as Code لأنك غالباً تدير أكثر من سيرفر، وأكثر من إصدار للتطبيق، وقد تحتاج لتبديل الإعدادات حسب المجموعة المعرفة في كتابة ملفات الجرد (Inventory) لتعريف وتصنيف الخوادم.
مثال أساسي على تعريف متغيرات داخل Playbook
---
- name: Install and configure nginx
hosts: web
become: true
vars:
package_name: nginx
service_name: nginx
app_port: 8080
tasks:
- name: Install package
apt:
name: "{{ package_name }}"
state: present
update_cache: true
- name: Ensure service is running
service:
name: "{{ service_name }}"
state: started
enabled: true
لاحظ أن الصياغة {{ variable_name }} تعتمد على محرك القوالب Jinja2. هذا يسمح بإدخال القيم في الملفات والأوامر وأسماء المسارات وحتى الشروط.
أهم أماكن تعريف المتغيرات
من الناحية الهندسية، اختيار مكان تعريف المتغير لا يقل أهمية عن اسم المتغير نفسه. التنظيم الجيد يمنع التعارضات ويُسهل إدارة البيئات الكبيرة.
- داخل
Playbookباستخدامvars. - داخل ملفات
group_varsلتخصيص إعدادات مجموعة خوادم كاملة. - داخل ملفات
host_varsلإعطاء كل خادم إعدادات مستقلة. - عبر
extra-varsعند تشغيل الأمر من الطرفية. - داخل الأدوار
rolesعند بناء هيكلية قابلة للتوسعة.
مثال على group_vars
# group_vars/web.yml
nginx_worker_processes: 4
nginx_listen_port: 80
app_root: /var/www/myapp
هذا الأسلوب مناسب عندما يكون لديك أكثر من خادم Web يحتاج إلى الإعدادات نفسها، وهو نمط شائع في البيئات التي تُدار بالتوازي مع CI/CD مثل ما شرحناه في ما هو الـ CI/CD؟ ولماذا نؤتمت عمليات اختبار ونشر الأكواد؟.
الحلقات داخل Ansible ولماذا هي مهمة؟
الحلقات تسمح بتكرار المهمة نفسها على عدة عناصر، مثل تثبيت مجموعة حزم، إنشاء عدة مستخدمين، أو نسخ ملفات متعددة. بدلاً من كتابة خمس مهام متشابهة، تكتب مهمة واحدة مع loop.
تثبيت عدة حزم بحلقة واحدة
---
- name: Install common packages
hosts: all
become: true
tasks:
- name: Install required packages
apt:
name: "{{ item }}"
state: present
update_cache: true
loop:
- git
- curl
- htop
- vim
المتغير الخاص بكل عنصر في الحلقة هو item بشكل افتراضي. ويمكنك استخدامه مع الوحدات modules المختلفة، وليس فقط مع تثبيت الحزم.
إنشاء عدة مستخدمين بخصائص مختلفة
---
- name: Create application users
hosts: app
become: true
vars:
app_users:
- { name: "deploy", shell: "/bin/bash" }
- { name: "monitor", shell: "/usr/sbin/nologin" }
tasks:
- name: Create users
user:
name: "{{ item.name }}"
shell: "{{ item.shell }}"
state: present
loop: "{{ app_users }}"
هنا أصبحت الحلقة أكثر قوة، لأن كل عنصر عبارة عن كائن يحتوي عدة حقول. هذا النمط ممتاز في أتمتة فرق العمليات التي تحتاج لتوحيد حسابات الوصول، إعدادات الخدمات، أو ملفات التهيئة على عدد كبير من الخوادم.
دمج المتغيرات والحلقات في سيناريو عملي
القوة الحقيقية تظهر عندما تجمع Variables مع Loops لإدارة ملفات متعددة أو تطبيقات مكررة بطريقة نظيفة. مثال شائع هو نشر عدة ملفات إعداد لخدمة Nginx أو عدة مواقع افتراضية.
---
- name: Deploy nginx virtual hosts
hosts: web
become: true
vars:
vhosts:
- server_name: app1.example.com
root_path: /var/www/app1
- server_name: app2.example.com
root_path: /var/www/app2
tasks:
- name: Create document roots
file:
path: "{{ item.root_path }}"
state: directory
mode: "0755"
loop: "{{ vhosts }}"
- name: Deploy vhost configuration
template:
src: nginx-vhost.conf.j2
dest: "/etc/nginx/sites-available/{{ item.server_name }}.conf"
loop: "{{ vhosts }}"
- name: Enable vhost
file:
src: "/etc/nginx/sites-available/{{ item.server_name }}.conf"
dest: "/etc/nginx/sites-enabled/{{ item.server_name }}.conf"
state: link
loop: "{{ vhosts }}"
هذا الأسلوب يجعل إضافة موقع جديد عملية بسيطة: أضف عنصراً جديداً إلى المتغير vhosts فقط. لا حاجة لتكرار ثلاث مهام جديدة لكل موقع.
أفضل الممارسات في التسمية والتنظيم
في المشاريع الكبيرة، سوء تسمية المتغيرات يؤدي إلى ارتباك أكبر من غياب الأتمتة نفسها. لذلك من الأفضل اعتماد أسماء واضحة مرتبطة بالسياق، مثل nginx_listen_port بدلاً من port.
- استخدم أسماء متغيرات تصف الخدمة أو الدور بوضوح.
- اجمع الإعدادات العامة في
group_varsوالإعدادات الخاصة فيhost_vars. - تجنب القيم الصلبة
Hardcoded Valuesداخل المهام. - استخدم الحلقات فقط عندما يكون هناك تكرار منطقي حقيقي.
- اختبر القوالب والمهام على بيئة تجريبية قبل تطبيقها على الإنتاج.
لا تضع الأسرار الحساسة مثل كلمات المرور أو مفاتيح
APIمباشرة داخل ملفات المتغيرات العادية. استخدمAnsible Vaultأو آليات إدارة أسرار آمنة، خصوصاً إذا كان المشروع مرتبطاً بخط نشر تلقائي أو مستودع مشترك بين الفريق.
العلاقة بين Ansible وباقي أدوات الأتمتة
في البيئات الحديثة لا يعمل Ansible بمعزل عن بقية المنظومة. كثير من الفرق تبني الصور عبر Docker ثم تستخدم Ansible لتهيئة الخوادم أو نشر ملفات البنية المحيطة. ويمكنك ربط ذلك مع مقدمة في GitHub Actions: كتابة أول مسار عمل (Workflow) لتشغيل Playbook تلقائياً بعد نجاح الاختبارات.
كما أن إدارة المتغيرات في Ansible تتقاطع مفاهيمياً مع تمرير المتغيرات البيئية (Environment Variables) للحاويات بشكل آمن، لأن الهدف في الحالتين هو فصل الإعدادات عن الكود، وتسهيل التبديل بين البيئات دون تعديل جوهر التطبيق.
قبل تشغيل أي حلقة تقوم بإنشاء مستخدمين أو تعديل ملفات خدمات حرجة أو إعادة تشغيل
Load Balancerأو خدمة ويب إنتاجية، استخدم نمط التحقق التدريجي وجرّب على عدد محدود من الخوادم لتقليل احتمالاتDowntime.
خاتمة
استخدام المتغيرات والحلقات داخل Ansible ليس مجرد تحسين شكلي لملفات YAML، بل هو انتقال فعلي نحو أتمتة قابلة للتوسع والاختبار وإعادة الاستخدام. كلما ازداد عدد الخوادم والخدمات والبيئات، أصبحت هذه الأدوات حجر الأساس في تقليل التكرار ورفع موثوقية النشر.
إذا كنت قد أتقنت بالفعل أول Playbook لك: تثبيت البرامج (مثل Nginx و Node) آلياً بلغة YAML، فالخطوة التالية المنطقية هي تنظيم متغيراتك بعناية، ثم استخدام الحلقات لبناء مهام مرنة تعمل على نطاق واسع. بهذه الطريقة يتحول Ansible من أداة تنفيذ أوامر إلى منصة تشغيل هندسية متقدمة تدعم احتياجات فرق DevOps الحديثة.
3 comments