استخدام المتغيرات (Variables) والحلقات (Loops) داخل Ansible

دقائق القراءة: 6

مقدمة

عندما تبدأ ببناء 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

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *