المحتوى عن 'ansible'.



مزيد من الخيارات

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المُحتوى


التصنيفات

  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • نصائح وإرشادات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • مقالات عامة
  • التجارة الإلكترونية

التصنيفات

  • PHP
    • Laravel
    • ووردبريس
  • جافاسكريبت
    • Node.js
    • jQuery
    • AngularJS
    • Cordova
  • HTML5
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • سي شارب #C
    • منصة Xamarin
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • برمجة أندرويد
  • لغة Swift
  • لغة R
  • سير العمل
    • Git
  • صناعة الألعاب
    • Unity3D
  • مقالات عامّة

التصنيفات

  • تجربة المستخدم
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
    • كوريل درو
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • مقالات عامّة

التصنيفات

  • خواديم
    • الويب HTTP
    • قواعد البيانات
    • البريد الإلكتروني
    • DNS
    • Samba
  • الحوسبة السّحابية
    • Docker
  • إدارة الإعدادات والنّشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • مقالات عامة

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • استسراع النمو
  • المبيعات

التصنيفات

  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • مقالات عامة

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
  • أندرويد
  • iOS
  • macOS
  • ويندوز

التصنيفات

  • شهادات سيسكو
    • CCNA
  • شهادات مايكروسوفت
  • شهادات Amazon Web Services
  • شهادات ريدهات
    • RHCSA
  • شهادات CompTIA
  • مقالات عامة

أسئلة وأجوبة

  • الأقسام
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة البرمجة
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات
    • أسئلة الشهادات المتخصصة

التصنيفات

  • ريادة الأعمال
  • العمل الحر
  • التسويق والمبيعات
  • البرمجة
  • التصميم
  • DevOps

تمّ العثور على 9 نتائج

  1. يعتبر Ansible حلًا مناسبًا لأتمتة الأعمال التقنية البسيطة، فإن وجدت نفسك تقوم بتثبيت ووردبريس بشكل متكرر ومُمل، فقد يوفّر عليك Ansible الكثير من الوقت، وباستخدام بعض الأسطر بلغة YAML (وهي لغة توصيف واضحة ومباشرة) سنقوم بأتمتة عملية تثبيت ووردبريس على خادوم يعمل بنظام تشغيل Ubuntu 14.04، وفق الخطوات بصورة أوتوماتيكية. سنستخدم خادومين: أحدهما الخادوم الباني ويتم تشغيل Ansible عليه، والآخر الذي سنقوم بتثبيت ووردبريس عليه باستخدام Ansible. المتطلبات الأولية قبل المتابعة في المقال، سنحتاج للأمور التالية: خادوم يعمل بنظام تشغيل Ubuntu 14.04. سنقوم بتثبيت Ansible على هذا الخادوم (ونشير إليه في المقال بـ الخادوم الباني). سنقوم بتسجيل الدخول إلى هذا الخادوم وجميع الأوامر والملفّات المذكورة في المقال على هذا الخادوم، خادوم آخر يعمل بنظام تشغيل Ubuntu 14.04. سنقوم بتثبيت ووردبريس عليه باستخدام Ansible (وسنشير إليه في المقال بـ خادوم ووردبريس)، حساب مستخدم عادي -على كِلا الخادومين- لا يملك صلاحيات مدير نظام، لكنّه يملك صلاحية تنفيذ الأمر sudo، إضافة مفتاح SSH الخاص بالمستخدم -الذي أنشأناه على الخادوم الباني- إلى المفاتيح المصادقة authorized_keys للمستخدم الذي أنشأناه على خادوم ووردبريس، وينبغي تنفيذ هذه العملية على الخادوم الباني ورفع المفاتيح إلى خادوم ووردبريس. تنفيذ أوامر sudo بدون تأكيد باستخدام كلمة مرور إنّ من الأسرع -ولكن أقل أمانًا- تنفيذ أوامر sudo على خادوم ووردبريس بدون الحاجة لإدخال كلمة مرور تأكيد في كل مرّة. لإعطاء المستخدم على خادوم ووردبريس هذه الإمكانية، سنقوم بتعديل ملف sudoers باستخدام الأمر visudo على سطر الأوامر: $ visudo ومن ثم سنضيف السطر التالي في نهاية الملف: sammy ALL=(ALL) NOPASSWD: ALL ملاحظة: لا تنس استبدال اسم المستخدم (sammy في هذه الحالة) باسم المستخدم الموجود لديك، وتأكد من وضع السطر في نهاية الملف حتى لا يتم تجاوزه بالصلاحيات الافتراضية الموجودة في الملف. نصيحة: قم دومًا باستخدام الأمر visudo عند تعديل ملف sudoers، لأن الأمر سيقوم بالتحقق من التعديلات قبل حفظ الملف ويحميك بالتالي من ارتكاب أخطاء في الملف قد تؤدي إلى منعك من الدخول. حالما تنتهي من تنفيذ العملية السابقة سيغدو بإمكانك تنفيذ الأمر التالي على خادوم ووردبريس بدون إدخال كلمة مرور لتأكيده: $ sudo echo "Hello" وفي بقية المقال، تستطيع تنفيذ الأمر ansible-playbook بدون المُعامل K- كي تتجنب الحاجة لإدخال كلمة المرور للتأكيد بشكل يدوي: $ ansible-playbook playbook.yml -i hosts -u sammy الخطوة الأولى: تثبيت Ansible سنقوم الآن بتثبيت Ansible على الخادوم الباني، ونبدأ بتسجيل الدخول عبر SSH إلى الخادوم وتنفيذ الأمر التالي: $ sudo apt-get install ansible -y وتستطيع التأكد من تثبيت Ansible بتنفيذ الأمر: $ ansible --version حيث ينبغي أن يكون الخرج مشابهًا (وليس بالضرورة مطابقًا) لما يلي: ansible 1.5.4 الخطوة الثانية: إعداد بنية الملفات الآن وبعد أن انتهينا من تثبيت Ansible، دعونا نقوم بإعداد بنية الملفات من أجل Ansible playbook. سنقوم بإنشاء مجلّد على النحو التالي: $ cd ~ $ mkdir wordpress-ansible && cd wordpress-ansible سنقوم الآن بإنشاء ملفّين: الأول يدعى playbook.yml (حيث سنقوم بكتابة الأوامر الخاصة بتثبيت ووردبريس فيه) والثاني يدعى hosts (وهذا يُخبر Ansible عن الخواديم التي سيتم تنفيذ الأوامر عليها): $ touch playbook.yml $ touch hosts إنّ من الأفضل فصل الأوامر بحسب الأدوار، ومن الممكن اعتبار الأدوار كأجزاء من الممكن إعادة استخدامها، وسنقوم في هذا المشروع بإنشاء 4 أدوار: server php mysql wordpress سنقوم بإنشاء مجلد الأدوار في الجذر الرئيسي للمجلد الذي أنشأناه سابقًا wordpress-ansible/~ بتنفيذ الأمر التالي: $ mkdir roles && cd roles والآن سنقوم بتجهيز الأدوار باستخدام أداة من أدوات Ansible تدعى ansible-galaxy، حيث سنقوم من أجل كل دور بتنفيذ الأمر ansible-galaxy init كالتالي: $ ansible-galaxy init server $ ansible-galaxy init php $ ansible-galaxy init mysql $ ansible-galaxy init wordpress ستلاحظ بأن هذا الأمر سيقوم بإنشاء هيكل ملفات متكامل لكل دور من الأدوار، وهذه الخطوة هي إحدى الأمور التي ينصح بها في توثيق Ansible. ما يهمّنا غالبًا هو التعامل مع محتوى ملف tasks/main.yml لكل دور. عند الوصول إلى هذه المرحلة سيكون لدينا الهيكل التالي: [.] |_ playbook.yml |_ hosts |_ [roles] |_ [server] |_ ... |_ [php] |_ ... |_ [mysql] |_ ... |_ [wordpress] |_ ... الخطوة الثالثة: إنشاء الـ Playbook سنقوم الآن بكتابة الأوامر التي ستقوم بتثبيت ووردبريس على خادوم ووردبريس. ملف المخزون hosts يُخبر هذا الملف Ansible بالخواديم التي نرغب بتثبيت ووردبريس عليها، ومن الممكن تنفيذ الأوامر للخواديم أو مجموعة الخواديم المعرّفة في ملف المخزون hosts. سنقوم بتحرير ملف hosts باستخدام محرر nano أو أي محرر آخر تفضّله وكتابة التالي: [wordpress] wordpress_server_ip ملاحظة: من الممكن وضع أي عدد نرغب به من العناوين الرقمية IPs تحت مجموعة [wordpress]. سيؤدي هذا إلى تنفيذ الأوامر على جميع الخواديم المذكورة على افتراض أننا نملك صلاحية استخدام هذه الخواديم. سيمكّننا هذا من تثبيت ووردبريس على أي عدد من الخواديم دفعة واحدة. ملف Playbook يمكن اعتبار هذا الملف كتعريف لتطبيق ووردبريس الذي سنقوم بتثبيته. سيحتوي الملف على جميع الأدوار التي قمنا بإنشائها بغرض تجهيز تطبيق مفيد (ووردبريس في حالتنا). سنقوم بداية بتحرير الملف باستخدام محرر nano أو أي محرر آخر ترغب به: $ nano ~/wordpress-ansible/playbook.yml ومن ثم سنضيف المحتويات التالية إلى الملف، والتي ستُخبر Ansible أية أدوار سيتم تنفيذها على أية خواديم (سيتم تنفيذ الأدوار المذكورة في حالتنا على مجموعة العناوين الرقمية المدرجة في مجموعة wordpress المسجّلة في ملف hosts الذي أنشأناه سابقًا): - hosts: wordpress roles: - server - php - mysql - wordpress والآن لنعد إلى الجذر الرئيسي: $ cd ~/wordpress-ansible/ سنتأكد الآن من أنه من الممكن إجراء اتصال ما بين الخادوم الباني وخادوم ووردبريس من خلال تنفيذ ملف playbook الذي لن يقوم بأي شيء سوى التحقق من الاتصال: $ ansible-playbook playbook.yml -i hosts -u sammy -K ستُطالب بإدخال كلمة المرور لتأكيد الأمر، ولا تنس أن تقوم باستبدال اسم المستخدم بالموجود لديك. سيظهر لنا خرج يشبه التالي عند تنفيذ الأمر: ansible-playbook playbook.yml -i hosts -u sammy -K PLAY [wordpress] ************************************************************** GATHERING FACTS *************************************************************** ok: [188.166.68.134] PLAY RECAP ******************************************************************** 188.166.68.134 : ok=1 changed=0 unreachable=0 failed=0 والذي سيؤكد لنا بأن الاتصال قد تم بنجاح، دون أن يتم تنفيذ أي تعديلات لأننا لم نقم بتحديد أي أوامر لتنفيذها حتى الآن. إن فشل تنفيذ الأمر فتأكّد من أن باستطاعتك تسجيل الدخول إلى خادوم ووردبريس من الخادوم الباني باستخدام مفتاح SSH الذي قمت بنسخه في البداية. الخطوة الثالثة: إنشاء الأدوار دور Server سنقوم بداية بتعريف الأوامر التي سيتم تنفيذها على الخادوم ولهذا الغرض سنقوم بتحرير أوامر دور server. ستقوم الأوامر التي سنصرّح عنها بتثبيت جميع البرمجيات التي سنحتاجها على السيرفر الهدف. نبدأ بتنفيذ الأمر التالي: $ nano roles/server/tasks/main.yml قم بإضافة المحتويات التالية وتأكد من وجود سطر واحد فقط يحتوي على --- (حيث يوجد هذا السطر سلفًا بشكل افتراضي): --- - name: Update apt cache apt: update_cache=yes cache_valid_time=3600 sudo: yes - name: Install required software apt: name={{ item }} state=present sudo: yes with_items: - apache2 - mysql-server - php5-mysql - php5 - libapache2-mod-php5 - php5-mcrypt - python-mysqldb سيقوم المحتوى السابق بما يلي: تحديث خبء apt-cache (تنفيذ الأمر apt-get update)، تثبيت Apache ،MySQL ،PHP وبرمجيات أخرى مرتبطة باستخدام apt-get install. وإن كنت مهتمًّا بمعرفة تفاصيل ما نقوم بتثبيته، فيمكنك الاطلاع على هذا المقال حول تثبيت LAMP على Ubuntu 14.04 بشكل يدوي. سنقوم الآن بتنفيذ ansible-playbook مرة أخرى على النحو التالي: $ ansible-playbook playbook.yml -i hosts -u sammy -K ويفترض هذه المرة أن يكون الخرج بما يشبه التالي: ansible-playbook playbook.yml -i hosts -u sammy -K PLAY [wordpress] ************************************************************** GATHERING FACTS *************************************************************** ok: [188.166.68.134] TASK: [server | Update apt cache] ********************************************* ok: [188.166.68.134] TASK: [server | Install required software] ************************************ changed: [188.166.68.134] => (item=apache2,mysql-server,php5-mysql,php5,libapache2-mod-php5,php5-mcrypt,python-mysqldb) PLAY RECAP ******************************************************************** 188.166.68.134 : ok=3 changed=1 unreachable=0 failed=0 وبعد التنفيذ، ينبغي أن تكون قادرًا على استعراض الصفحة الافتراضية لـ Apache عبر فتح العنوان http://wordpress_server_ip في المتصفح. ملاحظة: إن توقّف تنفيذ الأمر بشكل نهائي عند سطر [TASK: [server | Update apt cache فمن المحتمل أن يكون هناك نقص في الصلاحيات المطلوبة على الخادوم الهدف، لذا تأكّد من أن الوصول باستخدام sudo تم إعداده بشكل صحيح على خادوم ووردبريس. دور PHP سنقوم الآن بتجهيز الأوامر التي تستهدف PHP، ولهذا الغرض سنقوم بتحرير الملف الخاص بهذا الدور: $ nano roles/php/tasks/main.yml ومن ثم سنضيف المحتوى التالي (تأكّد من وجود سطر واحد فقط يحتوي على --- في بداية الملف): --- - name: Install php extensions apt: name={{ item }} state=present sudo: yes with_items: - php5-gd - libssh2-php سيقوم المحتوى السابق بتثبيت الملحقات extensions الضرورية لـ PHP وهي: php5-gd و libssh2-php. دور MySQL سنقوم الآن بإعداد قاعدة بيانات MySQL لموقع ووردبريس، وذلك في دور mysql. سنحتاج من أجل القيام بذلك إلى بعض المتغيّرات، والتي من الممكن تخزينها في ملف المتغيرات الافتراضية defaults/main.yml: $ nano roles/mysql/defaults/main.yml سنضيف في الملف اسم قاعدة البيانات، اسم المستخدم الخاص بالقاعدة، كلمة المرور الخاصة بالمستخدم وبنفس الترتيب، ولا تنس أن تستخدم كلمة مرور معقّدة لأغراض أمنية: --- wp_mysql_db: wordpress wp_mysql_user: wordpress wp_mysql_password: wp_db_password والآن نستخدم nano لتحرير ملف المهام: $ nano roles/mysql/tasks/main.yml ونضيف المحتوى التالي: --- - name: Create mysql database mysql_db: name={{ wp_mysql_db }} state=present - name: Create mysql user mysql_user: name={{ wp_mysql_user }} password={{ wp_mysql_password }} priv=*.*:ALL يقوم المحتوى السابق بـ: إنشاء قاعدة بيانات MySQL، إنشاء مستخدم MySQL، إعطاء المستخدم صلاحية الوصول إلى قاعدة البيانات. وكما ترى فسيتم استخدام قيم المتغيرات بشكل تلقائي من ملف defaults/main.yml عند تنفيذ الأوامر. ملاحظة: توفّر أدوات Ansible أداة ansible-vault والتي تسمح بتخزين كلمات المرور بصورة مشفّرة حتى لا تكون قابلة للقراءة في الملف، ولكن الحديث عن هذا خارج إطار حديثنا الآن. دور WordPress والآن نأتي للحظة التي كنا ننتظرها.. تثبيت ووردبريس. نبدأ بتحرير ملف المهام كالمعتاد: $ nano roles/wordpress/tasks/main.yml وسنقوم بنسخ المحتوى التالي إليه: --- - name: Download WordPress get_url: url=https://wordpress.org/latest.tar.gz dest=/tmp/wordpress.tar.gz validate_certs=no sudo: yes سيقوم المحتوى السابق بتحميل ووردبريس إلى مجلد tmp/ (ويمكن للحذرين أن ينتبهوا إلى أننا قمنا بتعطيل التحقق من الشهادة الأمنية، لأنه سيمنع عملية التحميل). بعد اكتمال التحميل سنقوم بفك ضغط الملف إلى var/www/، وهو المسار الذي يستخدمه Apache لتخزين محتوى الويب، وبالتالي سنضيف الجزء التالي لمحتوى الملف أيضًا: - name: Extract WordPress unarchive: src=/tmp/wordpress.tar.gz dest=/var/www/ copy=no sudo: yes وبعد أن يتم فك ضغط الملفات، سنقوم بتحديث مسار الجذر الافتراضي DocumentRoot في ملف إعدادات Apache كي يشير إلى موقع ووردبريس: - name: Update default Apache site sudo: yes lineinfile: dest=/etc/apache2/sites-enabled/000-default.conf regexp="(.)+DocumentRoot /var/www/html" line="DocumentRoot /var/www/wordpress" notify: - restart apache sudo: yes لاحظ أننا استخدمنا الكتلة notify، والتي نحتاجها عند الرغبة بإعادة تشغيل خدمات بعد أن يتم تنفيذ مهمّة بنجاح، ولا يتم تنفيذ معالجات notify إلا عندما يحصل تغيير على حالة المهمّة. سنقوم بإضافة المعالج الخاص بنا لإعادة تشغيل Apache باستخدام restart apache ويتم ذلك في الملف roles/wordpress/handlers/main.yml: $ nano roles/wordpress/handlers/main.yml نضيف المحتوى التالي: --- - name: restart apache service: name=apache2 state=restarted sudo: yes ويتم تنفيذ هذه المهمّة عندما تتغير حالة المهمّة التي تحتوي على الكتلة notify: restart apache، مما يؤدي إلى إعادة تشغيل الخدمة. إعداد ووردبريس بالعودة إلى roles/wordpress/tasks/main.yml، سنقوم الآن بتجهيز إعدادات موقع ووردبريس، فنقوم أولًا بنسخ ملف الإعدادات config الافتراضي: - name: Copy sample config file command: mv /var/www/wordpress/wp-config-sample.php /var/www/wordpress/wp-config.php creates=/var/www/wordpress/wp-config.php sudo: yes ومن ثم نقوم بتغيير بعض الثوابت في الملف لتتطابق مع معلومات الاتصال بقاعدة البيانات: - name: Update WordPress config file lineinfile: dest=/var/www/wordpress/wp-config.php regexp="{{ item.regexp }}" line="{{ item.line }}" with_items: - {'regexp': "define\\('DB_NAME', '(.)+'\\);", 'line': "define('DB_NAME', '{{wp_mysql_db}}');"} - {'regexp': "define\\('DB_USER', '(.)+'\\);", 'line': "define('DB_USER', '{{wp_mysql_user}}');"} - {'regexp': "define\\('DB_PASSWORD', '(.)+'\\);", 'line': "define('DB_PASSWORD', '{{wp_mysql_password}}');"} sudo: yes حيث ستقوم المهمّة بجلب معلومات الاتصال بالقاعدة من ملف المتغيّرات الافتراضية الذي قمنا بتحريره سابقًا. بعد الانتهاء من الخطوات السابقة بنجاح، سيكون قد أصبح لدينا ملفّين لدور wordpress، وفيما يلي النسخة الكاملة لمحتوى الملفّين.. ملف roles/wordpress/tasks/main.yml: --- - name: Download WordPress get_url: url=https://wordpress.org/latest.tar.gz dest=/tmp/wordpress.tar.gz validate_certs=no - name: Extract WordPress unarchive: src=/tmp/wordpress.tar.gz dest=/var/www/ copy=no sudo: yes - name: Update default Apache site sudo: yes lineinfile: dest=/etc/apache2/sites-enabled/000-default.conf regexp="(.)+DocumentRoot /var/www/html" line="DocumentRoot /var/www/wordpress" notify: - restart apache - name: Copy sample config file command: mv /var/www/wordpress/wp-config-sample.php /var/www/wordpress/wp-config.php creates=/var/www/wordpress/wp-config.php sudo: yes - name: Update WordPress config file lineinfile: dest=/var/www/wordpress/wp-config.php regexp="{{ item.regexp }}" line="{{ item.line }}" with_items: - {'regexp': "define\\('DB_NAME', '(.)+'\\);", 'line': "define('DB_NAME', '{{wp_mysql_db}}');"} - {'regexp': "define\\('DB_USER', '(.)+'\\);", 'line': "define('DB_USER', '{{wp_mysql_user}}');"} - {'regexp': "define\\('DB_PASSWORD', '(.)+'\\);", 'line': "define('DB_PASSWORD', '{{wp_mysql_password}}');"} sudo: yes ملف roles/wordpress/handlers/main.yml: --- - name: restart apache service: name=apache2 state=restarted sudo: yes ونكون قد انتهينا. لنقم الآن بتشغيل ansible-playbook لآخر مرة لإعداد موقع ووردبريس: $ ansible-playbook playbook.yml -i hosts -u sammy -K وبعد تنفيذ الأمر ينبغي أن نكون قادرين على تصفّح الموقع عبر طلب عنوانه http://your_server_ip في المتصفح ويمكن الآن متابعة إعداد موقع ووردبريس بشكل يدوي عند هذه المرحلة. الخلاصة تهانينا! ستتمكن الآن من تثبيت مواقع ووردبريس على أي عدد من الخواديم التي تعمل بنظام تشغيل Ubuntu باستخدام أمر واحد: $ ansible-playbook playbook.yml -i hosts -u sammy -K وكل ما تحتاج للقيام به هو إضافة العنوان الرقمي IP إلى قائمة الخواديم المستهدفة في ملف hosts والتأكّد من أن الصلاحيات قد تم إعدادها مسبقًا على الخادوم الهدف. تناولنا في المقال بصورة سريعة كيفية استخدام Ansible لتثبيت مواقع ووردبريس بشكل اوتوماتيكي، وقد تكون مهتمًّا ببعض التحسينات الإضافية الممكنة: تعلّم كيفية استضافة أدوارك الخاصة في الـ Ansible Galaxy. أتمتة عملية الإعداد النهائية لموقع ووردبريس حتى لا يكون هناك حاجة للقيام بأي إعداد يدوي للموقع المطلوب إطلاقًا. ترجمة -وبتصرّف- للمقال How To Automate Installing WordPress on Ubuntu 14.04 Using Ansible لصاحبه Christo Crampton.
  2. تمّ تصميم أنظمة إدارة الإعدادات لتجعل التحكّم بعدد كبير من الخواديم أمرًا سهلًا لمديري الأنظمة وفرق العمليّات، فهي تسمح لنا بالتحكّم بالعديد من الأنظمة المختلفة بطريقة مؤتمتة من موقع مركزي واحد. وبينما تتوافر العديد من أنظمة إدارة الإعدادات الشائعة من أجل أنظمة Linux، مثل Chef وPuppet، فهي غالبًا معقدة أكثر من حاجة الناس، تُشكّل Ansible بديلًا رائعًا لهذه الخيارات لأنّها تحتوي على عقبات أقل بكثير عند البدء معها. سنناقش في هذا الدّرس كيفيّة تثبيت Ansible على خادوم Ubuntu وسنمر على بعض الأساسيات حول كيفيّة استخدام هذه البرمجيّة. كيف تعمل Ansible؟تعمل Ansible عن طريق إعداد أجهزة العملاء من خلال حاسوب يمتلك مكوّنات Ansible مثبّتة ومُعدّة عليه. تتواصل عبر قنوات SSH الاعتياديّة من أجل استعادة المعلومات من الأجهزة عن بُعد remote، إصدار الأوامر، ونسخ الملفّات، ولهذا السبب لا يتطلّب نظام Ansible تثبيت أي برمجيّات إضافيّة على حواسيب العملاء. هذه هي إحدى الطرق التي تُبسِّط فيها Ansible إدارة الخواديم، فيُمكِن إحضار أي خادوم يمتلك منفذ SSH مُعرَّض تحت مظلّة إعدادات Ansible بغض النظر عن الطور الذي يتواجد فيه ضمن دورة حياته. أي حاسوب نستطيع إدارته عبر SSH نستطيع أيضًا إدارته عبر Ansible. تتخذ Ansible نهج الوحدات modules ممّا يجعل من السهل تمديدها كي تستخدم وظائف من النظام الأساسي للتعامل مع حالات محدّدة، يُمكِن كتابة الوحدات باستخدام أيّة لغة وهي تتخاطب بواسطة JSON المعياريّة. إنّ ملفّات الإعدادات مكتوبة بشكل رئيسي بصيغة تسلسل البيانات YAML نظرًا لطبيعتها التعبيرية وتشابهها مع لغات الرقم markup الشائعة، تتمكن Ansible من التفاعل مع العملاء إمّا من خلال أداة سطر الأوامر أو عبر scripts للإعدادات تُدعى Playbooks. تثبيت Ansible على Ubuntuللبدء باستكشاف Ansible كوسيلة لإدارة خواديمنا المختلفة نحتاج إلى تثبيت برمجيّة Ansible على جهاز واحد على الأقل، سنستخدم خادوم Ubuntu من أجل هذا القسم. إنّ أفضل طريقة للحصول على Ansible في Ubuntu هي إضافة PPA المشروع (أرشيف الحِزَم الشخصية personal package archive) إلى نظامنا. للقيام بذلك على نحو فعال نحتاج لتثبيت الحزمة python-software-properties والتي ستعطينا القدرة على العمل مع PPA بسهولة: sudo apt-get update sudo apt-get install python-software-propertiesبعد أن يتم تثبيت الحزمة نستطيع إضافة Ansible PPA بكتابة الأمر التالي: sudo add-apt-repository ppa:rquillo/ansible نضغط ENTER لقبول إضافة الـ PPA. نحتاج بعدها لتحديث دليل حِزَم نظامنا بحيث يكون على دراية بالحِزَم المتوفرة في PPA، نستطيع بعدها تثبيت برمجيّة Ansible: sudo apt-get update sudo apt-get install ansible نمتلك الآن كافّة البرمجيّات المطلوبة لإدارة خواديمنا من خلال Ansible. إعداد مفاتيح SSHتتخاطب Ansible بالدرجة الأولى كما أشرنا سابقًا مع حواسيب العملاء عبر SSH، وعلى الرغم من أنّها تمتلك القدرة على التعامل مع استيثاق SSH authentication مُعتمِد على كلمة السر فتساعد مفاتيح SSH على إبقاء الأمور أبسط. بإمكاننا إعداد مفاتيح SSH بطريقتين مختلفتين اعتمادًا على إذا ما كنّا نمتلك مسبقًا المفتاح الذي نريد استخدامه. 1- إنشاء زوج مفاتيح SSH جديدإن لم تكن تمتلك مسبقًا زوج مفاتيح SSH ترغب في استخدامه من أجل إدارة Ansible فبإمكانك إنشاء واحد الآن على خادوم Ansible. سنقوم بإنشاء زوج مفاتيح SSH على خادوم Ansible من أجل استيثاقه مع المضيفين الذين يديرهم. نقوم بإنشاء زوج مفاتيح RSA key-pair بكتابة ما يلي عن طريق المستخدم الذي نتحكّم بـ Ansible من خلاله: ssh-keygen سيتم سؤالنا عن تحديد موقع الملف لزوج المفاتيح التي تم إنشاؤها، عبارة سر passphrase، وتأكيد عبارة السّر، نضغط Enter في جميع هذه المراحل لقبول القيم الافتراضيّة. ستكون المفاتيح الجديدة متاحة في دليل ~/.ssh الخاص بالمستخدم، يُدعى المفتاح العام (والذي يمكننا مشاركته) بـ id_rsa.pub، يُدعى المفتاح الخاص (والذي نبقيه بأمان) بـ id_rsa. نستطيع إضافتها إلى لوحة تحكّم DigitalOcean على سبيل المثال (إن كنت على Digital Ocean) للسماح لنا بتضمين مفتاح SSH الخاص بنا في الخواديم الجديدة التي أنشأناها، سيسمح هذا لخادوم Ansible بالدخول إلى الخواديم الجديدة عبر SSH فورًا بدون الحاجة لأي استيثاق آخر. لفعل هذا نضغط على الرابط “SSH Keys” الموجود في قائمة التصفح على اليسار، نضغط في الشاشة الجديدة على زر “Add SSH Key” الموجود في الزاوية العلوية اليمنى: ندخل الاسم الذي نريد ربطه مع هذا المفتاح في الحقل العلوي، ونكتب على خادوم Ansible ما يلي للحصول على محتويات مفتاحنا العام: cat ~/.ssh/id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDzmGgsqjSFuOBbjZB1sgquKpp3Ty+FgqoLrzjKbbk9VGOH6kM37aAhyxxmTQfe69lhYi/WCai+mrXOyY9IiQbUfZ4jsfPE9DS3zHhmnGiBWA7pedCTJ/Nhf06dmhAJIbExW3uDghbPbzbSA5Ihn1x0F5FXtSMDoFtyjcwUwJxc2z/kk9TKcFSl8qqf4IYBYE7c+EKaYRBjjDP4AQmiwjTPuipsmub7C0OGF0dTMatIa0lok6rwy91nmhCQV6polG0+Fsk4YrY8Yh5xz6wE0lOvc8BwP9nL0zsnw6Ey0MHV9BbMqtyD6x/fCurpIkMHJK4nv79rToSWA0AwoP/bJXh7 demo@ansible0 السلسلة النصية التي تعود لنا هي التي نحتاج لصقها في الحقل الثاني في لوحة تحكّم DigitalOcean: نضغط على “Create SSH Key” لإضافة مفتاحنا إلى لوحة التحكم، نستطيع الآن تضمين مفتاح SSH العام إلى الخواديم الجديدة التي نضيفها مما يسمح لنا بالتواصل مع خادوم Ansible، نحتاج فقط إلى اختيار المفتاح في القسم “Add optional SSH Keys” من عملية إنشاء خادوم جديد: 2- نقل زوج مفاتيح SSH موجود إلى Ansibleإن كنت تمتلك مسبقًا زوج مفاتيح SSH تريد استخدامه من أجل الاستيثاق مع خواديمك فبإمكانك نقل الإعتمادات credentials إلى خادوم Ansible الجديد بدلًا من إنشاء زوج جديد، يمتلك هذا ميّزة بأن يجعلها تعمل تلقائيًّا مع أي خواديم قمت بإعدادها مسبقًا لتستخدم هذا المفتاح. وعلى الحاسوب الآخر حيث قمنا بإعداد استيثاق مفتاح SSH من أجل الخواديم نحصل على المفتاح العام بكتابة ما يلي: cat ~/.ssh/id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDzmGgsqjSFuOBbjZB1sgquKpp3Ty+FgqoLrzjKbbk9VGOH6kM37aAhyxxmTQfe69lhYi/WCai+mrXOyY9IiQbUfZ4jsfPE9DS3zHhmnGiBWA7pedCTJ/Nhf06dmhAJIbExW3uDghbPbzbSA5Ihn1x0F5FXtSMDoFtyjcwUwJxc2z/kk9TKcFSl8qqf4IYBYE7c+EKaYRBjjDP4AQmiwjTPuipsmub7C0OGF0dTMatIa0lok6rwy91nmhCQV6polG0+Fsk4YrY8Yh5xz6wE0lOvc8BwP9nL0zsnw6Ey0MHV9BbMqtyD6x/fCurpIkMHJK4nv79rToSWA0AwoP/bJXh7 demo@ansible0نحتاج على خادوم Ansible إلى إنشاء دليل مخفي لتخزين المفاتيح، نقوم بتسميته .ssh كي يعلم برنامج SSH أين يجده: mkdir ~/.ssh نقوم بقفل النفاذ إلى هذا الدليل لكي نتمكن نحن فقط من دخوله أو الكتابة إليه: chmod 700 ~/.ssh ننتقل الآن إلى الدليل ونفتح ملفًّا يُدعى id_rsa.pub باستخدام محرّر النصوص: cd ~/.ssh nano id_rsa.pubنلصق خَرْج مفتاحنا العام من حاسوبنا الرئيسي إلى هذا الملف: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDzmGgsqjSFuOBbjZB1sgquKpp3Ty+FgqoLrzjKbbk9VGOH6kM37aAhyxxmTQfe69lhYi/WCai+mrXOyY9IiQbUfZ4jsfPE9DS3zHhmnGiBWA7pedCTJ/Nhf06dmhAJIbExW3uDghbPbzbSA5Ihn1x0F5FXtSMDoFtyjcwUwJxc2z/kk9TKcFSl8qqf4IYBYE7c+EKaYRBjjDP4AQmiwjTPuipsmub7C0OGF0dTMatIa0lok6rwy91nmhCQV6polG0+Fsk4YrY8Yh5xz6wE0lOvc8BwP9nL0zsnw6Ey0MHV9BbMqtyD6x/fCurpIkMHJK4nv79rToSWA0AwoP/bJXh7 demo@ansible0 نقوم بحفظ وإغلاق الملف، ونتحقّق من امتلاكه للأذونات الصحيحة بكتابة: chmod 644 id_rsa.pub الآن وبالعودة إلى حاسوبنا المحلّي المضبوط من أجل نفاذ مفاتيح SSH نكتب: cat ~/.ssh/id_rsa -----BEGIN RSA PRIVATE KEY----- MIIEpgIBAAKCAQEA85hoLKo0hbjgW42QdbIKriqad08vhYKqC684ym25PVRjh+pD N+2gIcl8Zk0H3uvZYWIv1gmsfpq1zsmPSIkG1H2eI7HzxPQ0qMx4ZpxogVgO6XnQ kyfzYX9OnZoQCSGxMVt7g4IWz2820gOSIZ9cdBeRV7UjA6Bbco3MFMCcXNs/5JPU ynBUpfKqn+CGAWBO3PhCmmEQY4wz+AEJosI0z7oqbJrm/AtDhhdHUzGrSGtJaJOq . . . . . . cqsqOEzXAoGBAPMJJ8RrKUBuSjVNkzebst9sBgNadmaoQUoMHUDr8KpCZhWAoHB7 1VKmq7VSphQSruI31qy2M88Uue1knC/nQr1bE1DITZgezETSsDqsAMBo8bqDN6TT qVJgG+TS9BRC+IowuzMVV5mzrfJjkrb+GG+xWSXrTLZMbeeTf+D0SfVo -----END RSA PRIVATE KEY----- سيكون الخَرْج طويلًا جدًّا. نعود الآن إلى خادوم Ansible، نحتاج إلى إنشاء ملف جديد في الدليل ~/.ssh: nano id_rsa نقوم بداخله بلصق نتائج الأمر السابق على حاسوبنا المحلّي: -----BEGIN RSA PRIVATE KEY----- MIIEpgIBAAKCAQEA85hoLKo0hbjgW42QdbIKriqad08vhYKqC684ym25PVRjh+pD N+2gIcl8Zk0H3uvZYWIv1gmsfpq1zsmPSIkG1H2eI7HzxPQ0qMx4ZpxogVgO6XnQ kyfzYX9OnZoQCSGxMVt7g4IWz2820gOSIZ9cdBeRV7UjA6Bbco3MFMCcXNs/5JPU ynBUpfKqn+CGAWBO3PhCmmEQY4wz+AEJosI0z7oqbJrm/AtDhhdHUzGrSGtJaJOq . . . . . . cqsqOEzXAoGBAPMJJ8RrKUBuSjVNkzebst9sBgNadmaoQUoMHUDr8KpCZhWAoHB7 1VKmq7VSphQSruI31qy2M88Uue1knC/nQr1bE1DITZgezETSsDqsAMBo8bqDN6TT qVJgG+TS9BRC+IowuzMVV5mzrfJjkrb+GG+xWSXrTLZMbeeTf+D0SfVo -----END RSA PRIVATE KEY----- نتأكّد من تضمين أسطر التحديد الموجودة في البداية والنهاية، فهي مطلوبة لكي يكون ملف المفتاح صالحًا، نحفظ الملف ونغلقه. نحتاج لتغيير الأذونات لإبقاء هذا الملف بأمان: chmod 600 id_rsa ستكون Ansible عند هذه النقطة قادرة على استخدام مفاتيح SSH هذه من أجل التواصل مع أي خادوم يمتلك المفتاح مُضمَّنًا عليه. إعداد مضيفي Ansibleتقوم Ansible بتتبّع جميع الخواديم التي يعلم عنها عن طريق ملف المضيفين “hosts”، نحتاج إلى إعداد هذا الملف أوّلًا قبل أن نتمكّن من بدء التواصل مع حواسيبنا الأخرى. نفتح الملف مع صلاحيّات جذريّة root كما يلي: sudo nano /etc/ansible/hosts سنرى ملفًّا يمتلك الكثير من أمثلة الإعدادات، وسيعمل أيّ منها لدينا فعليًّا، لذلك من أجل البدء نقوم بتعليق كافّة أسطر هذا الملف بإضافة “#” قبل كل سطر. سنبقي هذه الأمثلة في هذا الملف لتساعدنا في الإعداد إن أردنا تنفيذ حالات أكثر تعقيدًا في المستقبل. بعد أن يتم تعليق كافّة الأسطر نستطيع البدء بإضافة المضيفين الفعليين لدينا. يكون ملف المضيفين مرنًا إلى حدٍّ ما ويمكن إعداده بعدّة طرق مختلفة، تبدو الصياغة التي سنستخدمها كما يلي: [group_name] alias ansible_ssh_host=server_ip_address إنّ group_name هو وسم تنظيمي يسمح لنا بالإشارة لأي من الخواديم المدرجة بكلمة واحدة، الكنية هي مجرّد اسم للإشارة إلى ذلك الخادوم. لذا نتخيل في حالتنا أننا نمتلك ثلاثة خواديم نريد إعدادها مع Ansible، تكون هذه الخواديم قابلة للوصول من خلال خادوم Ansible بكتابة: ssh root@server_ip_address لن يتم سؤالنا عن كلمة سر إن أعددنا هذا بشكل صحيح، سنفترض أنّ عناوين IP لخواديمنا هي 192.0.2.1، 192.0.2.2، و192.0.2.3، سنقوم بإعداد هذا بحيث نستطيع الإشارة إليها بشكل مفرد كـ host1، host2، وhost3، أو كمجموعة باسم servers. هذه هي الكتلة التي ينبغي إضافتها إلى ملف المضيفين من أجل تحقيق هذا: [servers] host1 ansible_ssh_host=192.0.2.1 host2 ansible_ssh_host=192.0.2.2 host3 ansible_ssh_host=192.0.2.3 يمكن للمضيفين أن يكونوا ضمن مجموعات متعدّدة، وتستطيع المجموعات إعداد مُعامِلات parameters من أجل كل أعضائها، فلنجرّب هذا الآن. إن حاولنا مع إعداداتنا الحاليّة الاتصال بأي من المضيفين عن طريق Ansible فسيفشل الأمر (بافتراض أنّك لا تعمل عن طريق المستخدم الجذري root)، يحدث هذا لأنّه تم تضمين مفاتيح SSH من أجل المستخدم الجذري على الأنظمة البعيدة وستحاول Ansible الاتصال بشكل افتراضي بواسطة المستخدم الحالي، ستعطينا محاولة الاتصال هذا الخطأ: host1 | FAILED => SSH encountered an unknown error during the connection. We recommend you re-run the command using -vvvv, which will enable SSH debugging output to help diagnose the issue نستخدم على خادوم Ansible مستخدمًا يُدعى demo، ستحاول Ansible الاتصال إلى كل مضيف باستخدام ssh demo@server، لن يعمل هذا إن كان المستخدم demo غير موجود على النظام البعيد. نستطيع إنشاء ملف يُخبِر جميع الخواديم في المجموعة servers بالاتصال عن طريق المستخدم الجذري root. لفعل هذا نقوم بإنشاء دليل في بنية إعدادات Ansible يُدعى group_vars، ونستطيع ضمن هذا المجلّد إنشاء ملفّات مُنسّقة عن طريق YAML لكل مجموعة نريد إعدادها: sudo mkdir /etc/ansible/group_vars sudo nano /etc/ansible/group_vars/serversبإمكاننا وضع إعداداتنا هنا، تبدأ ملفّات YAML بـ “—” لذا تأكّد ألّا تنسى ذلك الجزء: --- ansible_ssh_user: rootنحفظ الملف ونغلقه عند الانتهاء. إن أردنا تحديد تفاصيل الإعدادات لكل خادوم بغض النظر عن مجموعته المرتبط بها فبإمكاننا وضع هذه التفاصيل في ملف في المسار /etc/ansible/group_vars/all، يمكن إعداد المضيفين بشكل مفرد بواسطة إنشاء ملفّات في دليل في المسار /etc/ansible/host_vars. استخدام أوامر Ansible بسيطةالآن بعد أن قمنا بإعداد المضيفين وضبطنا تفاصيل الإعدادات بشكلٍ كافٍ للسماح لنا بالاتصال بنجاح إلى مضيفينا، فبإمكاننا تجربة الأمر الأول لنا. نقوم بعمل ping لكل الخواديم التي أعددناها عن طريق كتابة: ansible -m ping allhost1 | success >> { "changed": false, "ping": "pong" } host3 | success >> { "changed": false, "ping": "pong" } host2 | success >> { "changed": false, "ping": "pong" } وهو اختبار بسيط للتأكّد من امتلاك Ansible لاتصال مع كافّة مضيفيه. تعني “all” كافّة المضيفين، وكان بإمكاننا بسهولة تحديد مجموعة كما يلي: ansible -m ping serversنستطيع أيضًا تحديد مضيف بشكل فردي: ansible -m ping host1بإمكاننا تحديد عدّة مضيفين بفصلهم بواسطة نقطتين: ansible -m ping host1:host2المقطع -m ping من الأمر هو تعليمة لـ Ansible كي تستخدم الوحدة “ping”، وهي بشكل مبسّط عبارة عن أوامر نستطيع تنفيذها على مضيفينا عن بُعد، تعمل الوحدة “ping” بعدّة طرق مثل أداة ping العاديّة في Linux، ولكن تقوم بدلًا من ذلك بالتحقّق من أجل اتصال Ansible. لا تأخذ الوحدة ping فعليًّا أيّة مُعطيات arguments، ولكن بإمكاننا تجربة أمر آخر لنرى كيفيّة عمل ذلك، نقوم بتمرير المعطيات إلى script بكتابة –a. تسمح لنا وحدة الصدفة “shell” بإرسال أمر طرفيّة terminal إلى المضيف البعيد واستعادة النتائج، على سبيل المثال لإيجاد استخدام الذاكرة على جهاز مضيفنا host1 نستطيع استخدام: ansible -m shell -a 'free -m' host1 host1 | success | rc=0 >> total used free shared buffers cached Mem: 3954 227 3726 0 14 93 -/+ buffers/cache: 119 3834 Swap: 0 0 0 الخاتمةينبغي أن تمتلك الآن خادوم Ansible مضبوطًا للتواصل مع الخواديم التي ترغب بالتحكم بها، تحقّقنا قدرة Ansible على التواصل مع كل مضيف واستخدمنا الأمر ansible لتنفيذ مهام بسيطة عن بُعد. وعلى الرغم من أنّ هذا مفيد لنا، لم نقم بتغطية أقوى ميّزة في Ansible في هذا الدّرس وهي الـ Playbooks، لقد قمنا بإعداد أساس رائع من أجل العمل مع خواديمنا من خلال Ansible، ولكن الجزء الأكبر سيتم الحديث عنه في درس لاحق عند تغطية كيفيّة استخدام الـ Playbooks لأتمتة الإعدادات لحواسيبنا عن بُعد. ترجمة -وبتصرّف- لـ How to Install and Configure Ansible on an Ubuntu 12.04 VPS لصاحبه Justin Ellingwood.
  3. هذا الدّرس هو جزء من سلسلة دروس حول نشر تطبيقات PHP باستخدام Ansible على Ubuntu، تحدّثنا في الأجزاء الأولى عن الخطوات الأساسيّة لنشر تطبيق، وفي بقيّة الأجزاء تكلمنا عن مواضيع أكثر تقدّمًا مثل قواعد البيانات، عفاريت الطابور queue daemons، وجدولة المهام (عبر cron). سنقوم في هذا الدّرس بالبناء على ما تعلمناه في الدروس السابقة عن طريق تحويل الـ playbook في Ansible من دعمها لتطبيق واحد إلى دعمها لنشر تطبيقات PHP متعدّدة على خادوم أو عدّة خواديم، سنتحدث في هذا الجزء عن إعداد المتغيرات، وسنكمل في الجزء اللاحق عن إضافة المزيد من التطبيقات ونشرها. سنستخدم تطبيقات Lumen بسيطة كجزء أمثلتنا، ولكن يُمكِن تعديل هذه التعليمات بسهولة لتدعم أطر عمل وتطبيقات أخرى في حال كانت متواجدة لديك، من المفضّل أن تستخدم تطبيقات الأمثلة حتى تجد نفسك متآلفًا مع القيام بالتغييرات للـ playbook. المتطلبات الأساسيةتحتاج من أجل متابعة الدّرس إلى: الخادومين الاثنين اللذين قمنا بإعدادهما في الأجزاء السابقة.خادوم Ubuntu جديد (ثالث) يتم إعداده مثل خادوم PHP الأصلي الموجود في الأجزاء السابقة، مع مستخدم sudo غير جذري ومفاتيح SSH، حيث سنستخدمه لإظهار كيفيّة نشر تطبيقات متعدّدة إلى خواديم متعدّدة باستخدام Ansible Playbook واحدة، سنشير لعناوين IP لخادوم PHP الأصلي وخادوم PHP الجديد بـ your_first_server_ip و your_second_server_ip على الترتيب.ملف etc/hosts/ مُحدَّث على حاسوبك المحلّي مع إضافة الأسطر التالية له، تستطيع تعلّم المزيد حول هذا الملف في الخطوة السادسة من هذا الدّرس.your_first_server_ip laravel.example.com one.example.com two.example.com your_second_server_ip laravel.example2.com two.example2.comأمثلة المواقع التي سنستخدمها في هذا الدّرس هي laravel.example.com، one.example.com، و two.example.com، إن أردت استخدام نطاقك الخاص ستحتاج لتحديث تسجيلات DNS النشطة لديك بدلًا من ذلك. الخطوة الأولى – إعداد متغيرات الـ Playbookسنقوم في هذه الخطوة بإعداد متغيّرات الـ playbook لتعريف تطبيقنا الجديد. في الدروس السابقة قمنا بكتابة خصائص الإعدادات بشكل حرفي وهو أمر طبيعي بالنسبة للعديد من الـ playbooks التي تقوم بتنفيذ مهام محدّدة من أجل تطبيق محدّد، أمّا عندما نريد دعم عدّة تطبيقات أو توسيع مدى الـ playbook الخاصّة بنا فلن يعود هنالك معنى من كتابة كل شيء حرفيًّا. وكما شاهدنا سابقًا تزوّدنا Ansible بمتغيرات نستطيع استخدامها في تعريفات المهام وقوالب الملفّات، ما لم نشاهده حتى الآن هو كيفيّة تعيين المتغيرات، في أعلى الـ playbook بجانب مُعامِلات hosts وtasks نستطيع تعريف مُعامِل vars وتعيين متغيراتنا هناك. نقوم بالانتقال إلى الدليل ansible-php الذي تحدثنا عنه في الدّروس السابقة: cd ~/ansible-php/ نفتح الـ playbook الحاليّة من أجل تحريرها: nano php.yml ينبغي أن تبدو بداية الملف كما يلي: Top of original php.yml --- - hosts: php sudo: yes tasks: . . . نستطيع من أجل تعريف المتغيرات إضافة القسم vars فقط، بجانب hosts، sudo، وtasks، ولإبقاء الموضوع بسيط سنبدأ مع متغيّر بسيط جدًّا من أجل المستخدم www-data كما يلي: Updated vars in php.yml --- - hosts: php sudo: yes vars: wwwuser: www-data tasks: . . . نقوم بعدها بتحديث كافّة المرّات التي ورد فيها المستخدم www-data ونضع بدلًا منها المتغيّر {{ wwwuser }}. نضغط على CTRL+\ من أجل البحث والاستبدال باستخدام nano، سنشاهد مُحث prompt يقول: Search (to replace):. نكتب www-data ونضغط ENTER، سيتغيّر المُحِث إلى: Replace with:نكتب هنا {{ wwwuser }} ونضغط ENTER مرّة أخرى، سيأخذنا nano عبر كل مثال من www-data ويسألنا: Replace this instanace?نستطيع أن نضغط y لاستبدال كل واحدة منها، أو نضغط a لاستبدالها كلّها. ملاحظة: تأكّد من عدم تغيير تعريف المتغير الذي أضفناه للتو في أعلى الملف، يجب أن يكون هنالك 11 مثال من www-data نحتاج إلى استبدالها. وقبل أن نكمل هنالك شيء نحتاج للانتباه له فيما يتعلّق بالمتغيرات، بإمكاننا بشكل طبيعي إضافتها كما يلي عندما تكون في سطر أطول: Example task in php.yml - name: create /var/www/ directory file: dest=/var/www/ state=directory owner={{ wwwuser }} group={{ wwwuser }} mode=0700 ومع ذلك إن كان المتغيّر هو القيمة الوحيدة في السلسلة نحتاج إلى وضعه ضمن علامتي اقتباس كي يستطيع مُحلِّل YAML فهمه بشكل صحيح: Updated task in php.yml - name: Run artisan migrate shell: php /var/www/laravel/artisan migrate --force sudo: yes sudo_user: "{{ wwwuser }}" when: dbpwd.changed يجب أن يحدث هذا في الـ playbook في كل مرّة نحصل فيها على: sudo_user: {{ wwwuser }}نستطيع استخدام بحث واستبدال عام بنفس الطريقة ووضع: sudo_user: "{{ wwwuser }}" بدلًا من: sudo_user: {{ wwwuser }}ينبغي وجود أربعة أسطر تحتاج إلى هذا التغيير. وبعد أن ننتهي من تغييرها نقوم بحفظ وتشغيل الـ playbook: ansible-playbook php.yml --ask-sudo-pass ينبغي ألّا توجد مهام متغيّرة، وهو يعني أنّ المتغيّر wwwuser يعمل بشكل صحيح. الخطوة الثانية – تعريف المتغيرات المتداخلة من أجل الإعدادات المعقدةسننظر في هذا القسم إلى المتغيّرات المتداخلة من أجل خيارات الإعدادات المعقدة. قمنا في الخطوة السابقة بإعداد متغيّر بسيط، ولكن يمكن أيضًا أن نُداخِل بين المتغيّرات وأن نُعرِّف قائمة من المتغيّرات، يزودنا هذا بالوظيفة التي نحتاجها لتعريف قائمة من المواقع التي نرغب بإعدادها على خادومنا. دعونا في البداية ننظر إلى مستودع git الحالي الذي قمنا بإعداده في الـ playbook: Existing git task in php.yml - name: Clone git repository git: > dest=/var/www/laravel repo=https://github.com/do-community/do-ansible-adv-php.git update=yes version=example نستطيع استخراج المعلومات المفيدة التالية: الاسم name (دليل)، المستودع repository، الفرع branch، والنطاق domain، وبما أنّنا نقوم بإعداد تطبيقات متعدّدة سنحتاج أيضًا إلى اسم نطاق من أجله للإجابة عليه، سنستخدم laravel.example.com ولكن إن كنت تملك نطاقك الخاص فضعه هنا. ينتج عن هذا المتغيرات الأربعة التالية التي نستطيع تعريفها من أجل هذا التطبيق: Application variables name: laravel repository: https://github.com/do-community/do-ansible-adv-php.git branch: example domain: laravel.example.com نفتح الآن الـ playbook من أجل تحريرها: nano php.yml نستطيع في القسم العلوي vars إضافة تطبيقنا إلى قائمة التطبيقات الجديدة: Updated applications variables in php.yml --- - hosts: php sudo: yes vars: wwwuser: www-data applications: - name: laravel domain: laravel.example.com repository: https://github.com/do-community/do-ansible-adv-php.git branch: example ... إن قمنا الآن بتشغيل الـ playbook (باستخدام ansible-playbook php.yml --ask-sudo-pass) فلن يتغير شيء لأنّنا لم نقم بعد بإعداد مهامنا لكي تستخدم المتغير applications الجديد، إن ذهبنا إلى http://laravel.example.com/ في متصفحنا فينبغي أن يظهر تطبيقنا الأصلي. الخطوة الثالثة – المرور على المتغيرات عن طريقة حلقة loop في المهامسنتعلم في هذا القسم كيفيّة المرور على قوائم المتغيرات عبر حلقة loop في المهام. كما أشرنا سابقًا تحتاج قوائم المتغيرات المرور عليها عبر حلقة في كل مهمة نرغب في استخدامها فيها، وكما شاهدنا مع المهمّة install packages نحتاج إلى تعريف حلقة من العناصر ومن ثمّ تطبيق المهمّة لكل عنصر في القائمة. نفتح الـ playbook من أجل تحريرها: nano php.yml سنبدأ ببعض المهام السهلة، ينبغي أن نجد مهمتي env في منتصف الـ playbook تقريبًا: Existing env tasks in php.yml - name: set APP_DEBUG=false lineinfile: dest=/var/www/laravel/.env regexp='^APP_DEBUG=' line=APP_DEBUG=false - name: set APP_ENV=production lineinfile: dest=/var/www/laravel/.env regexp='^APP_ENV=' line=APP_ENV=production نلاحظ أنّها مكتوبة الآن بشكل حرفي مع الدليل laravel، نحتاج إلى تحديثها لكي تستخدم الخاصية name لكل تطبيق، ولفعل هذا نضيف الخيار with_items كي يمر على شكل حلقة خلال قائمة applications لدينا، وضمن المهمّة نفسها سنبدل المرجع laravel بالمتغير {{ item.name }}. ينبغي أن تبدو كما يلي: Updated .env tasks in php.yml - name: set APP_DEBUG=false lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^APP_DEBUG=' line=APP_DEBUG=false with_items: applications - name: set APP_ENV=production lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^APP_ENV=' line=APP_ENV=production with_items: applications ننتقل بعدها إلى الأسفل إلى مهمتي Laravel cron، يمكن تحديثهما كما فعلنا تمامًا مع مهام env، سنقوم بإضافة item.name إلى المُعامِل name من أجل مُدخلات لأنّ Ansible تستخدم هذا الحقل لتعرّف بشكل فريد كل مُدخل cron، إن تركناها كما هي فلن نكون قادرين على الحصول على مواقع متعددة على نفس الخادوم لأنّها ستكتب فوق بعضها بشكل ثابت وسيتم حفظ القيمة الأخيرة فقط. ينبغي أن تبدو المهمة كما يلي: Updated cron tasks in php.yml - name: Laravel Scheduler cron: > job="run-one php /var/www/{{ item.name }}/artisan schedule:run 1>> /dev/null 2>&1" state=present user={{ wwwuser }} name="{{ item.name }} php artisan schedule:run" with_items: applications - name: Laravel Queue Worker cron: > job="run-one php /var/www/{{ item.name }}/artisan queue:work --daemon --sleep=30 --delay=60 --tries=3 1>> /dev/null 2>&1" state=present user={{ wwwuser }} name="{{ item.name }} Laravel Queue Worker" with_items: applications إن قمنا بحفظ وتشغيل الـ playbook الآن (باستخدام ansible-playbook php.yml --ask-sudo-pass) فيجب أن نرى أنّه فقط تم تحديث مهمّتي cron، وهذا بسبب التغيير في المُعامِل name، ولا توجد أيّة تغييرات عدا عن ذلك، وهذا يعني أنّ قائمة تطبيقاتنا تعمل كما هو متوقع، ولم نقم بأيّة تغييرات إلى خادومنا كنتيجة لإعادة تصنيع الـ playbook لدينا. الخطوة الرابعة – تطبيق المتغيرات من الحلقة looped variables في قوالب templatesسنغطي في هذا القسم كيفيّة استخدام المتغيرات من الحلقة في القوالب. نستطيع استخدام هذه المتغيرات بنفس الطريقة تمامًا التي استخدمناها في المهام، كما هو الحال مع جميع المتغيرات الأخرى، تأتي الصعوبة عندما نأخذ بعين الاعتبار مسارات الملفات بالإضافة للمتغيرات، لأنّنا سنحتاج في بعض الأحيان إلى أخذ اسم الملف بعين الاعتبار وحتى تنفيذ أوامر أخرى بسبب الملف الجديد. نحتاج في حالة Nginx إلى إنشاء ملف إعدادات جديد لكل تطبيق وإخبار Nginx أنّه ينبغي تمكينها، نريد أيضًا إزالة ملف إعداداتنا الافتراضي: etc/nginx/sites-available/default/ خلال العمليّة. نفتح في البداية الـ playbook من أجل تحريرها: nano php.yml نقوم بإيجاد المهمة Configure Nginx (قرب منتصف الـ playbook) وتحديثها كما فعلنا مع المهام الأخرى: Updated nginx task in php.yml - name: Configure nginx template: src=nginx.conf dest=/etc/nginx/sites-available/{{ item.name }} with_items: applications notify: - restart php5-fpm - restart nginx وبينما نحن هنا نقوم بإضافة المهمتين الإضافيتين اللتين أشرنا لهما سابقًا، نخبر Nginx في البداية حول ملف إعدادات الموقع الجديد، يتم فعل هذا باستخدام بارتباط رمزي بين أدلة sites-available و sites-enabled في /var/nginx/. نضيف هذه المهمة بعد المهمة Configure nginx: New symlink task in php.yml - name: Configure nginx symlink file: src=/etc/nginx/sites-available/{{ item.name }} dest=/etc/nginx/sites-enabled/{{ item.name }} state=link with_items: applications notify: - restart php5-fpm - restart nginx نرغب بعدها في إزالة ملف إعدادات الموقع المُمكّن افتراضيًّا default كي لا يسبب مشاكل مع ملفّات إعدادات موقعنا الجديد، يتم عمل هذا بسهولة باستخدام الوحدة file: New file task php.yml - name: Remove default nginx site file: path=/etc/nginx/sites-enabled/default state=absent notify: - restart php5-fpm - restart nginx لاحظ أنّنا لم نحتاج إلى وضع applications في حلقة لأنّنا كنّا نبحث عن ملف واحد. يجب أن تبدو كتلة Nginx في الـ playbook كما يلي الآن: Updated nginx tasks in php.yml - name: Configure nginx template: src=nginx.conf dest=/etc/nginx/sites-available/{{ item.name }} with_items: applications notify: - restart php5-fpm - restart nginx - name: Configure nginx symlink file: src=/etc/nginx/sites-available/{{ item.name }} dest=/etc/nginx/sites-enabled/{{ item.name }} state=link with_items: applications notify: - restart php5-fpm - restart nginx - name: Remove default nginx site file: path=/etc/nginx/sites-enabled/default state=absent notify: - restart php5-fpm - restart nginx نحفظ الـ playbook ونفتح الملف nginx.conf من أجل تحريره: nano nginx.conf نقوم بتحديث ملف الإعدادات بحيث يستخدم متغيراتنا: Updated nginx.conf server { listen 80 default_server; listen [::]:80 default_server ipv6only=on; root /var/www/{{ item.name }}/public; index index.php index.html index.htm; server_name {{ item.domain }}; location / { try_files $uri $uri/ =404; } error_page 404 /404.html; error_page 500 502 503 504 /50x.html; location = /50x.html { root /var/www/{{ item.name }}/public; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } مع ذلك لم نقم بالانتهاء بعد، أتلاحظ default_server في الأعلى؟ نريد تضمينها فقط من أجل تطبيق laravel لجعله التطبيق الافتراضي، لعمل هذا نستطيع استخدام جملة IF بسيطة لنتحقّق إذا ما كان item.name يساوي laravel وإن كان كذلك نعرض default_server. ستبدو كما يلي: Updated nginx.conf with conditionals server { listen 80{% if item.name == "laravel" %} default_server{% endif %}; listen [::]:80{% if item.name == "laravel" %} default_server ipv6only=on{% endif %}; نحدّث nginx.conf وفقًا لذلك ونحفظه. حان الوقت الآن لتشغيل الـ playbook لدينا: ansible-playbook php.yml --ask-sudo-pass يجب أن تلاحظ أنّه تم تعليم مهام Nginx بأنّها تغيرت، عند الانتهاء من تشغيل الـ playbook نحدّث الموقع في متصفحنا ويجب أن يعرض ما يلي: http://laravel.example.com/ Queue: YES Cron: YES الخطوة الخامسة – وضع متغيرات متعددة في حلقة معاسنقوم في هذه الخطوة بوضع متغيّرات متعدّدة معًا في مهمّة. حان الوقت الآن لمعالجة مثال حلقات أكثر تعقيدًا، خصوصًا المتغيّرات المُسجّلَة، من أجل دعم حالات مختلفة ومنع تشغيل مهام غير ضرورية، تتذكر أنّنا استخدمنا register: cloned في مهمّة استنساخ مستودع git لتسجيل المتغير cloned مع حالة المهمّة، نستخدم بعدها when: cloned|changed في المهام التالية لتحفيز المهام بشكل شرطي، نحتاج الآن إلى تحديث هذه المراجع لتدعم حلقة التطبيقات. نفتح أوّلًا الـ playbook من أجل تحريرها: nano php.yml نبحث عن المهمّة Clone git repository: Existing git task in php.yml - name: Clone git repository git: > dest=/var/www/laravel repo=https://github.com/do-community/do-ansible-adv-php.git update=yes version=example sudo: yes sudo_user: "{{ wwwuser }}" register: cloned وبما أنّنا نقوم بتسجيل المتغيرات في هذه المهمة فلن نحتاج إلى فعل أي شيء لم نفعله سابقًا: Updated git task in php.yml - name: Clone git repository git: > dest=/var/www/{{ item.name }} repo={{ item.repository }} update=yes version={{ item.branch }} sudo: yes sudo_user: "{{ wwwuser }}" with_items: applications register: cloned نبحث الآن عن المهمة composer create-project: Original composer task in php.yml - name: composer create-project composer: command=create-project working_dir=/var/www/laravel optimize_autoloader=no sudo: yes sudo_user: "{{ wwwuser }}" when: cloned|changed نحتاج الآن إلى تحديثها للمرور عبر حلقة على applications و cloned، يتم فعل هذا باستخدام الخيار with_together وتمرير applications وcloned إليها، وبينما تقوم with_together بالمرور عبر حلقة على المتغيرين فيتم الصول إلى العناصر باستخدام item.#، حيث أنّ # هي فهرس المتغير، فعلى سبيل المثال: with_together: - list_one - list_two يشير item.0 إلى list_one ويشير item.1 إلى list_two. يعني هذا أنّنا نستطيع من أجل applications نستطيع الوصول إلى الخصائص عبر: item.0.name، نحتاج من أجل cloned إلى تمرير النتائج من المهام والتي يمكن الوصول إليها عبر cloned.results ومن ثمّ نستطيع التحقّق إن تم تغييرها من خلال item.1.changed. يعني هذا أنّ المهمة ستصبح: Updated composer task in php.yml - name: composer create-project composer: command=create-project working_dir=/var/www/{{ item.0.name }} optimize_autoloader=no sudo: yes sudo_user: "{{ wwwuser }}" when: item.1.changed with_together: - applications - cloned.results نقوم الآن بحفظ وتشغيل الـ playbook: ansible-playbook php.yml --ask-sudo-pass ينبغي ألّا تحدث أيّة تغييرات من هذا التشغيل، ومع ذلك نمتلك الآن متغيرًا مُسجّلًا يعمل بشكل رائع مع حلقة. الخطوة السادسة – المتغيرات المسجلة المعقدة والحلقاتسنتعلم في هذا القسم حول المزيد من المتغيرات المسجلة المعقدة والحلقات. الجزء الأكثر تعقيدًا من التحويل هو مُداولة handling المتغير المسجّل الذي نستخدمه من أجل توليد كلمة السر لقاعدة بيانات MySQL، ولا يوجد أكثر مما فعلناه في هذه الخطوة لم نقم بتغطيته، نحتاج فقط إلى تحديث عدد من المهام في وقت واحد. نفتح الـ playbook من أجل تحريرها: nano php.yml نبحث عن مهام MySQL ونقوم بإضافة المتغيرات البسيطة كما فعلنا في المهمة السابقة: Updated MySQL tasks in php.yml - name: Create MySQL DB mysql_db: name={{ item.name }} state=present with_items: applications - name: Generate DB password shell: makepasswd --chars=32 args: creates: /var/www/{{ item.name }}/.dbpw with_items: applications register: dbpwd - name: Create MySQL User mysql_user: name={{ item.name }} password={{ dbpwd.stdout }} priv={{ item.name }}.*:ALL state=present when: dbpwd.changed - name: set DB_DATABASE lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^DB_DATABASE=' line=DB_DATABASE={{ item.name }} with_items: applications - name: set DB_USERNAME lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^DB_USERNAME=' line=DB_USERNAME={{ item.name }} with_items: applications - name: set DB_PASSWORD lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^DB_PASSWORD=' line=DB_PASSWORD={{ dbpwd.stdout }} when: dbpwd.changed - name: Save dbpw file lineinfile: dest=/var/www/{{ item.name }}/.dbpw line="{{ dbpwd.stdout }}" create=yes state=present sudo: yes sudo_user: "{{ wwwuser }}" when: dbpwd.changed - name: Run artisan migrate shell: php /var/www/{{ item.name }}/artisan migrate --force sudo: yes sudo_user: "{{ wwwuser }}" when: dbpwd.changed نضيف بعدها with_together كي نستطيع استخدام كلمة سر قاعدة بياناتنا، ومن أجل توليد كلمة السر نحتاج إلى المرور بحلقة خلال dbpwd.results وسنكون قادرين على الوصول لكلمة السر من item.1.stdout بما أنّه سيتم الوصول لـ applications عبر item.0. نستطيع تحديث الـ playbook وفق ذلك: Updated MySQL tasks in php.yml - name: Create MySQL DB mysql_db: name={{ item.name }} state=present with_items: applications - name: Generate DB password shell: makepasswd --chars=32 args: creates: /var/www/{{ item.name }}/.dbpw with_items: applications register: dbpwd - name: Create MySQL User mysql_user: name={{ item.0.name }} password={{ item.1.stdout }} priv={{ item.0.name }}.*:ALL state=present when: item.1.changed with_together: - applications - dbpwd.results - name: set DB_DATABASE lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^DB_DATABASE=' line=DB_DATABASE={{ item.name }} with_items: applications - name: set DB_USERNAME lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^DB_USERNAME=' line=DB_USERNAME={{ item.name }} with_items: applications - name: set DB_PASSWORD lineinfile: dest=/var/www/{{ item.0.name }}/.env regexp='^DB_PASSWORD=' line=DB_PASSWORD={{ item.1.stdout }} when: item.1.changed with_together: - applications - dbpwd.results - name: Save dbpw file lineinfile: dest=/var/www/{{ item.0.name }}/.dbpw line="{{ item.1.stdout }}" create=yes state=present sudo: yes sudo_user: "{{ wwwuser }}" when: item.1.changed with_together: - applications - dbpwd.results - name: Run artisan migrate shell: php /var/www/{{ item.0.name }}/artisan migrate --force sudo: yes sudo_user: "{{ wwwuser }}" when: item.1.changed with_together: - applications - dbpwd.results بعد أن يتم تحديثها نقوم بحفظها وتشغيلها: ansible-playbook php.yml --ask-sudo-pass بالرغم من جميع التغييرات التي قمنا بها على الـ playbook فلا يجب أن يكون هنالك تغييرات في مهام قاعدة البيانات، ومع التغييرات في هذه الخطوة نكون قد انتهينا من التحويل من playbook تدعم تطبيق وحيد إلى playbook تدعم تطبيقات متعددة. الخاتمةتحدثنا في هذا الجزء عن إعداد المتغيرات، وسنكمل في الجزء اللاحق عن إضافة المزيد من التطبيقات ونشرها إلى خادوم آخر. ترجمة -وبتصرّف- لـ How To Deploy Multiple PHP Applications using Ansible on Ubuntu 14.04 لصاحبه Stephen Rees-Carter.
  4. هذا الدّرس هو جزء من سلسلة دروس حول نشر تطبيقات PHP باستخدام Ansible على Ubuntu، تحدّثنا في الأجزاء الأولى عن الخطوات الأساسيّة لنشر تطبيق، وفي بقيّة الأجزاء تكلمنا عن مواضيع أكثر تقدّمًا مثل قواعد البيانات، عفاريت الطابور queue daemons، وجدولة المهام (عبر cron). سنقوم في هذا الدّرس بالبناء على ما تعلمناه في الدروس السابقة عن طريق تحويل playbook في Ansible من دعمها لتطبيق واحد إلى دعمها لنشر تطبيقات PHP متعدّدة على خادوم أو عدّة خواديم. سنستخدم تطبيقات Lumen بسيطة كجزء أمثلتنا، ولكن يُمكِن تعديل هذه التعليمات بسهولة لتدعم أطر عمل وتطبيقات أخرى في حال كانت متواجدة لديك، من المفضّل أن تستخدم تطبيقات الأمثلة حتى تجد نفسك متآلفًا مع القيام بالتغييرات لِـ playbook. الخطوة الأولى – إضافة المزيد من التطبيقاتفي هذه الخطوة سنقوم بإعداد تطبيقين إضافيين في الـ playbook لدينا. الآن وقد أعدنا تصنيع الـ playbook سنستخدم متغيرات لتعريف التطبيقات، إنّ عملية إضافة تطبيقات جديدة لخادومنا هي عملية سهلة جدًّا، نقوم بإضافتها ببساطة إلى قائمة المتغيرات applications، وهنا تظهر قوة متغيرات Ansible. نفتح playbook من أجل تحريرها: nano php.yml نبحث في أعلى القسم vars عن الكتلة applications: Existing applications variable in php.yml applications: - name: laravel domain: laravel.example.com repository: https://github.com/do-community/do-ansible-adv-php.git branch: example نضيف تطبيقين اثنين: Updated applications variable in php.yml applications: - name: laravel domain: laravel.example.com repository: https://github.com/do-community/do-ansible-adv-php.git branch: example - name: one domain: one.example.com repository: https://github.com/do-community/do-ansible-php-example-one.git branch: master - name: two domain: two.example.com repository: https://github.com/do-community/do-ansible-php-example-two.git branch: master نحفظ الـ playbook ونقوم بتشغيلها: ansible-playbook php.yml --ask-sudo-pass قد تستغرق هذه الخطوة بعض الوقت بينما يقوم الـ composer بإعداد التطبيقات الجديدة، وعندما ينتهي سنلاحظ تغيير عدد من المهام، وإن دققنا أكثر سنلاحظ أنّه سيتم عرض كل عنصر ناتج عن الحلقة، يخبرنا الأول وهو تطبيقنا الأصل بعبارة ok أو skipped، بينما يخبرنا التطبيقان الجديدان بالحالة changed. والأهم من ذلك أنّه إذا زرنا النطاقات الثلاثة لمواقعنا التي أعددناها في متصفح الإنترنت فينبغي أن نلاحظ ثلاثة مواقع مختلفة. الأول يبدو مألوفًا لنا، أما الموقعان الآخران سيعرضان: http://one.example.com/ This is example app one! http://two.example.com/ This is example app two! وبذلك قمنا بنشر تطبيقي ويب جديدين عن طريق تحديث قائمة التطبيقات ببساطة. الخطوة الثانية – استخدام متغيرات المضيفين Host Variablesسنستخرج في هذه الخطوة متغيراتنا إلى متغيرات المضيفين. بالرجوع إلى الوراء نجد أنّ متغيرات الـ playbook جيدة، ولكن ماذا لو أردنا نشر تطبيقات مختلفة على خواديم مختلفة باستخدام نفس الـ playbook؟ نستطيع عمل تحقّق شرطي على كل مهمّة لإيجاد الخادوم الذي يقوم بتشغيل المهمة، أو نستطيع استخدام متغيرات المضيفين، وهي تمامًا كما تبدو عليه: متغيرات تُطبَّق على مضيف معيّن بدلًا من كافّة المضيفين عبر الـ playbook. يمكن تعريف متغيرات المضيف سطريًّا inline بداخل الملف hosts كما فعلنا مع المتغير ansible_ssh_user أو يمكن تعريفها في ملف مخصّص لكل مضيف داخل الدليل host_vars. في البداية نقوم بإنشاء دليل جديد إلى جانب الملف hosts والـ playbook، نقوم بتسمية الدليل بـ host_vars: mkdir host_vars نحتاج بعدها إلى إنشاء ملف من أجل المضيف، الاتفاقية التي تستخدمها Ansible هي من أجل أن يتوافق اسم الملف مع اسم المضيف في الملف hosts، لذلك على سبيل المثال إن كان يبدو الملف hosts لدينا كما يلي: Ansible hosts file your_first_server_ip ansible_ssh_user=sammy فينبغي أن نقوم بإنشاء ملف يُدعى host_vars/your_first_server_ip، فلنقم بإنشائه الآن: nano host_vars/your_first_server_ip تستخدم ملفّات المضيفين YAML من أجل تنسيقها تمامًا كما هو الحال مع الـ playbooks، ويعني هذا أنّنا نستطيع نسخ القائمة applications إلى ملف المضيفين الجديد لدينا بحيث يبدو كما يلي: New host_vars/your_first_server_ip file --- applications: - name: laravel domain: laravel.example.com repository: https://github.com/do-community/do-ansible-adv-php.git branch: example - name: one domain: one.example.com repository: https://github.com/do-community/do-ansible-php-example-one.git branch: master - name: two domain: two.example.com repository: https://github.com/do-community/do-ansible-php-example-two.git branch: master نقوم بحفظ ملف المضيفين الجديد ونفتح الـ playbook لتحريرها: nano php.yml نحدّث أعلى الملف لإزالة كامل القسم applications: Updated top of php.yml --- - hosts: php sudo: yes vars: wwwuser: www-data tasks: . . . نحفظ الـ playbook ونقوم بتشغيلها: ansible-playbook php.yml --ask-sudo-pass وعلى الرغم من أنّنا نقلنا متغيراتنا من الـ playbook إلى ملف المضيفين فيجب أن يبقى الخرج نفسه ولا يجب أن يتم تبليغنا عن تغييرات من قبل Ansible، وكما نرى يعمل host_vars بنفس الطريقة التي يعمل بها vars في الـ playbook، ولكنّه مُخصّص للمضيف. ستكون المتغيرات المُعرّفة في ملفّات host_vars قابلة للوصول عبر كامل الـ playbooks التي تدير الخادوم، وهو مفيد من أجل الخيارات والإعدادات الشائعة، ومع ذلك كن حذرًا من استخدام اسم شائع قد يعني أشياء مختلفة عبر الـ playbooks المختلفة. الخطوة الثالثة – نشر التطبيقات على خادوم آخرسنستخدم في هذه الخطوة ملفات المضيفين الجديدة وننشر تطبيقاتنا على خادوم آخر. نحتاج في البداية إلى تحديث ملف المضيفين hosts بمضيفنا الجديد، نفتحه من أجل تحريره: nano hosts ونقوم بإضافة المضيف الجديد: Ansible hosts file your_first_server_ip ansible_ssh_user=sammy your_second_server_ip ansible_ssh_user=sammy نحفظ الملف ونغلقه. نحتاج بعدها إلى إنشاء ملف مضيفين جديد، كما فعلنا مع أول ملف: nano host_vars/your_second_server_ip تستطيع انتقاء واحد أو أكثر من تطبيقات مثالنا وإضافتها إلى ملف المضيف لديك، فإذا أردت مثلًا نشر مثالنا الأصلي والمثال الثاني إلى خادوم جديد فيجب أن تستخدم: New host_vars/your_second_server_ip file --- applications: - name: laravel domain: laravel.example2.com repository: https://github.com/do-community/do-ansible-adv-php.git branch: example - name: two domain: two.example2.com repository: https://github.com/do-community/do-ansible-php-example-two.git branch: master نقوم بحفظ playbook. وأخيرًا نقوم بتشغيلها: ansible-playbook php.yml --ask-sudo-pass ستستغرق Ansible وقتًا ليتم تشغيلها لأنّها تقوم بإعداد كل شيء على خادومنا الثاني، وعندما تنتهي نفتح تطبيقاتنا التي اخترناها في المتصفح (استخدمنا في هذا المثال laravel.example2.com وtwo.example2.com) وللتأكد من أنّه تم إعدادها بشكل صحيح يجب أن نرى التطبيقات المحدّدة التي اخترناها من أجل ملف المضيفين، وينبغي ألّا تحدث أيّة تغييرات على خادومنا الأصلي. الخاتمةأخذنا في هذا الدرس playbook تطبيق وحيد تعمل بشكل كامل وقمنا بتحويلها لتدعم تطبيقات متعددة عبر عدّة خواديم، وبجمعها مع المواضيع التي تمت تغطيتها في الدروس السابقة يجب أن تمتلك كل ما تحتاجه لكتابة playbook كاملة لنشر تطبيقاتك، وكما هو الحال مع الدروس السابقة فلا زلنا لم نسجل الدخول بشكل مباشر باستخدام SSH. ومن المؤكد أنك لاحظت مدى بساطة إضافة المزيد من التطبيقات والمزيد من الخواديم بعد الانتهاء من تجهيز بنية الـ playbook، وهنا تكمن قوة Ansible وهو ما يجعلها مرنة جدًّا وسهلة الاستخدام. ترجمة -وبتصرّف- لـ How To Deploy Multiple PHP Applications using Ansible on Ubuntu 14.04 لصاحبه Stephen Rees-Carter.
  5. هذا الدّرس هو جزء من سلسلة دروس حول نشر تطبيقات PHP باستخدام Ansible على Ubuntu، تحدّثنا في أول أجزاء عن الخطوات الأساسيّة من أجل نشر تطبيق، وهي تشكل نقطة بداية من أجل الخطوات المذكورة في هذا الدّرس. سنغطّي في هذا الدّرس إعداد قاعدة البيانات (بما في ذلك كلمة السّر)، هدفنا في النهاية هو الحصول على خادوم يعمل عليه تطبيق PHP بشكل كامل مع الإعدادات المذكورة آنفًا. سنستخدم إطار عمل Laravel كمثال عن تطبيق PHP ولكن يُمكِن تعديل هذه التعليمات بسهولة لتدعم أطر عمل وتطبيقات أخرى في حال كانت متواجدة لديك. الخطوة الأولى – تثبيت حزم MySQLسنقوم في هذه الخطوة بإعداد قاعدة بيانات MySQL لكي يستخدمها تطبيقنا. إنّ الخطوة الأولى لضمان وجود MySQL مُثبّتة على خادومنا هي ببساطة إضافة الحِزَم المطلوبة إلى مهمّة تثبيت الحِزَم في أعلى الـ playbook لدينا، الحزم التي نحتاجها هي mysql-server، mysql-client، وphp5-mysql، سنحتاج أيضًا إلى python-mysqldb كي تستطيع Ansible التواصل مع MySQL. وبما أنّنا نضيف حِزَم فنحتاج إلى إعادة تشغيل nginx و php5-fpm لضمان قابلية استخدام الحِزَم الجديدة من قبل التطبيق، نحتاج في هذه الحالة أن تكون MySQL متوفرة من أجل PHP لكي تستطيع الاتصال إلى قاعدة البيانات. من الأشياء الرائعة حول Ansible هي أنّنا نستطيع تعديل أي مهمّة من المهام وإعادة تشغيل الـ playbook وسيتم حينها تطبيق التغييرات، يتضمّن هذا قوائم من الخيارات كما نملك مع مهمّة apt. نفتح الملف php.yml من أجل تحريره: nano php.yml نبحث عن المهمّة install packages ونحدّثها لتضم الحِزَم السابقة: Updated php.yml . . . - name: install packages apt: name={{ item }} update_cache=yes state=latest with_items: - git - mcrypt - nginx - php5-cli - php5-curl - php5-fpm - php5-intl - php5-json - php5-mcrypt - php5-sqlite - sqlite3 - mysql-server - mysql-client - php5-mysql - python-mysqldb notify: - restart php5-fpm - restart nginx . . . نقوم بحفظ وتشغيل الـ playbook: ansible-playbook php.yml --ask-sudo-pass الخطوة الثانية – إعداد قاعدة بيانات MySQLسنقوم في هذه الخطوة بإنشاء قاعدة بيانات MySQL من أجل تطبيقنا. تستطيع Ansible التخاطب مباشرة مع MySQL باستخدام الوحدات المسبوقة بـ mysql_ (مثل mysql_db، mysql_user)، تزودنا الوحدة mysql_db بطريقة لضمان وجود قاعدة بيانات ذات اسم مُحدّد بحيث نستطيع استخدام مهمّة مثل هذه لإنشاء قاعدة البيانات: New Ansible task - name: Create MySQL DB mysql_db: name=laravel state=present نحتاج أيضًا إلى حساب مستخدم صحيح مع كلمة سر معروفة للسماح لتطبيقنا بالاتصال إلى قاعدة البيانات، إحدى الوسائل لتحقيق هذا هي توليد كلمة السر محليًّا وحفظها في playbook الخاصّة بـ Ansible، ولكنّ هذه الطريقة غير آمنة وتوجد وسيلة أفضل منها. سنقوم بتوليد كلمة السّر باستخدام Ansible على الخادوم ذاته واستخدامها مباشرة عند الحاجة، ولتوليد كلمة سر سنستخدم أداة الأوامر السطرية makepasswd ونطلب منها كلمة سر مكوّنة من 32 حرف، ولأنّ makepasswd لا تأتي بشكل افتراضي مع Ubuntu سنحتاج إلى إضافتها إلى قائمة الحِزَم أيضًا. سنخبر أيضًا Ansible أن تتذكر خَرْج output هذا الأمر (أي تتذكر كلمة السّر) حتى نستطيع استخدامها لاحقًا في الـ playbook الخاصّة بنا، ومع ذلك ولأنّ Ansible لا تعلم إذا ما كان قد تم تنفيذ الأمر shell فسنقوم بإنشاء ملف عند تنفيذ هذا الأمر، ستتحقّق Ansible من وجود الملف وإن وجدته فستفترض أنّه تمّ تشغيل ذلك الأمر ولن يتم تشغيله مرّة أخرى. تبدو المهمّة كما يلي: New Ansible task - name: Generate DB password shell: makepasswd --chars=32 args: creates: /var/www/laravel/.dbpw register: dbpwd نحتاج بعدها لإنشاء مستخدم قاعدة بيانات MySQL الفعلي مع كلمة السّر التي حدّدناها، يتم عمل ذلك باستخدام الوحدة mysql_user ونستطيع استخدام الخيار stdout على المتغيّر الذي عرّفناه خلال مهمّة توليد كلمة السّر للحصول على الخَرْج الخام لأمر الصدفة shell، مثل هذا: dbpwd.stdout. يقبل الأمر mysql_user اسم المستخدم والصلاحيّات المطلوبة، نريد في حالتنا إنشاء مستخدم يُدعى laravel وإعطاء هذا المستخدم صلاحيّات كاملة على الجدول laravel، نحتاج أيضًا إلى إخبار المهمّة أن يتم تشغيلها فقط عندما يتم تغيير المتغيّر dbpwd، والذي سيحدث فقط عند تشغيل مهمّة توليد كلمة السّر. يجب أن تبدو المهمّة كما يلي: New Ansible task - name: Create MySQL User mysql_user: name=laravel password={{ dbpwd.stdout }} priv=laravel.*:ALL state=present when: dbpwd.changed وبوضع كل ذلك معًا نفتح الملف php.yml من أجل تحريره كي نستطيع إضافة المهمّة السابقة: nano php.yml نبحث في البداية عن المهمّة install packages ونقوم بتحديثها لتتضمّن الحزمة makepasswd: Updated php.yml . . . - name: install packages apt: name={{ item }} update_cache=yes state=latest with_items: - git - mcrypt - nginx - php5-cli - php5-curl - php5-fpm - php5-intl - php5-json - php5-mcrypt - php5-sqlite - sqlite3 - mysql-server - mysql-client - php5-mysql - python-mysqldb - makepasswd notify: - restart php5-fpm - restart nginx . . . نضيف بعدها مهام توليد كلمة السّر، إنشاء قاعدة بيانات MySQL، وإنشاء مستخدم في نهاية الملف: Updated php.yml . . . - name: UFW limit <abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">SSH</abbr> ufw: rule=limit port=<abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">ssh</abbr> - name: UFW open HTTP ufw: rule=allow port=http - name: Create MySQL DB mysql_db: name=laravel state=present - name: Generate DB password shell: makepasswd --chars=32 args: creates: /var/www/laravel/.dbpw register: dbpwd - name: Create MySQL User mysql_user: name=laravel password={{ dbpwd.stdout }} priv=laravel.*:ALL state=present when: dbpwd.changed handlers: . . . لا تقم بتشغيل الـ playbook الآن، ربّما تكون قد لاحظت أنّه بالرغم من أنّنا أنشأنا مستخدم وقاعدة بيانات MySQL فلم نفعل أي شيء مع كلمة السّر، سنغطّي هذا الموضوع في الخطوة القادمة، عند استخدام مهام shell ضمن Ansible فمن المهم دومًا أن نتذكّر متابعة سير العمل الذي يتعلّق بخَرْج ونتائج المهمّة بأكمله قبل تشغيلها لنتجنّب الاضطرار إلى تسجيل الدخول يدويًّا وإعادة تعيين الحالة. الخطوة الثالثة – إعداد تطبيق PHP من أجل قاعدة البياناتسنقوم في هذه الخطوة بحفظ كلمة سر قاعدة بيانات MySQL في الملف .env من أجل التطبيق. سنحدّث الملف .env ليتضمن اعتمادات (credentials) قاعدة بياناتنا التي أنشأناها حديثًا، يحتوي ملف .env الخاص بـ Laravel الأسطر التالية بشكل افتراضي: Laravel .env file DB_HOST=localhost DB_DATABASE=homestead DB_USERNAME=homestead DB_PASSWORD=secret نستطيع الإبقاء على السطر DB_HOST كما هو، ولكن سنحدّث الأسطر الثلاثة الأخرى باستخدام المهام التالية، وهي مشابهة جدًّا للمهام التي استخدمناها في الدّرس السابق من أجل تعيين APP_ENV و APP_DEBUG: New Ansible tasks - name: set DB_DATABASE lineinfile: dest=/var/www/laravel/.env regexp='^DB_DATABASE=' line=DB_DATABASE=laravel - name: set DB_USERNAME lineinfile: dest=/var/www/laravel/.env regexp='^DB_USERNAME=' line=DB_USERNAME=laravel - name: set DB_PASSWORD lineinfile: dest=/var/www/laravel/.env regexp='^DB_PASSWORD=' line=DB_PASSWORD={{ dbpwd.stdout }} when: dbpwd.changed وكما فعلنا مع مهمّة إنشاء مستخدم MySQL فقد استخدمنا متغيّر كلمة السر التي تمّ توليدها (dbpwd.stdout) لنشر الملف مع كلمة السّر، وأضفنا الخيار when لضمان أن يتم تشغيلها فقط عند تغيير dbpwd. وبما أنّ الملف .env موجود مسبقًا قبل إضافة مهمّة توليد كلمة السّر، فسنحتاج إلى حفظ كلمة السّر إلى ملف آخر، تبحث مهمّة توليد كلمة السّر عن وجود الملف (والذي أعددناه مسبقًا ضمن المهمّة)، سنستخدم أيضًا الخيارات sudo وsudo_user لإخبار Ansible أن يقوم بإنشاء الملف عن طريق المستخدم www-data: New Ansible task - name: Save dbpw file lineinfile: dest=/var/www/laravel/.dbpw line="{{ dbpwd.stdout }}" create=yes state=present sudo: yes sudo_user: www-data when: dbpwd.changed نفتح الملف php.yml من أجل تحريره: nano php.yml نضيف المهام السابقة إلى الـ playbook، يجب أن تتطابق نهاية الملف مع التالي: Updated php.yml . . . - name: Create MySQL User mysql_user: name=laravel password={{ dbpwd.stdout }} priv=laravel.*:ALL state=present when: dbpwd.changed - name: set DB_DATABASE lineinfile: dest=/var/www/laravel/.env regexp='^DB_DATABASE=' line=DB_DATABASE=laravel - name: set DB_USERNAME lineinfile: dest=/var/www/laravel/.env regexp='^DB_USERNAME=' line=DB_USERNAME=laravel - name: set DB_PASSWORD lineinfile: dest=/var/www/laravel/.env regexp='^DB_PASSWORD=' line=DB_PASSWORD={{ dbpwd.stdout }} when: dbpwd.changed - name: Save dbpw file lineinfile: dest=/var/www/laravel/.dbpw line="{{ dbpwd.stdout }}" create=yes state=present sudo: yes sudo_user: www-data when: dbpwd.changed handlers: . . . لا تقم بتشغيل الـ playbook الآن، فقد بقيت لدينا خطوة واحدة يجب إكمالها قبل أن نتمكّن من تشغيل الـ playbook. الخطوة الرابعة – تهجير قاعدة البيانات Migrating the Databaseسنقوم في هذه الخطوة بتنفيذ تهجير قاعدة البيانات database migrations من أجل إعداد جداول قاعدة البيانات. يتم فعل هذا في Laravel عن طريق تنفيذ الأمر migrate (على سبيل المثال php artisan migrate --force) بداخل دليل Laravel، لاحظ أنّنا أضفنا العَلَم force-- لأنّ بيئة production تحتاجه. تبدو مهمّة Ansible للقيام بهذا كما يلي: New Ansible task - name: Run artisan migrate shell: php /var/www/laravel/artisan migrate --force sudo: yes sudo_user: www-data when: dbpwd.changed حان الوقت الآن لتحديث playbook الخاصّة بنا، نفتح الملف php.yml لتحريره: nano php.yml نضيف المهام السابقة إلى الـ playbook، يجب أن تتطابق نهاية الملف مع التالي: Updated php.yml . . . - name: Save dbpw file lineinfile: dest=/var/www/laravel/.dbpw line="{{ dbpwd.stdout }}" create=yes state=present sudo: yes sudo_user: www-data when: dbpwd.changed - name: Run artisan migrate shell: php /var/www/laravel/artisan migrate --force sudo: yes sudo_user: www-data when: dbpwd.changed handlers: . . . بإمكاننا أخيرًا حفظ وتشغيل الـ playbook: ansible-playbook php.yml --ask-sudo-pass عند الانتهاء من تنفيذ هذا نقوم بتحديث الصفحة في متصفحنا ويجب أن نرى عندها رسالة تقول: your_server_ip/'>http://your_server_ip/ Queue: NO Cron: NO يعني هذا أنّ تم إعداد قاعدة البيانات بشكل صحيح وأنّها تعمل كما هو متوقع، ولكنّنا لم نقم حتى الآن بإعداد مهام cron أو عفريت الطابور queue daemon، والتي سنقوم بها في الدرس القادم. الخاتمةتحدّثنا في هذا الدّرس عن طريقة إعداد قاعدة بيانات MySQL وإعداد تطبيق PHP من أجلها ومن ثمّ تهجير قاعدة البيانات من أجل نشر تطبيق PHP متقدّم باستخدام Ansible. ترجمة -وبتصرّف- لـ How To Deploy an Advanced PHP Application Using Ansible on Ubuntu 14.04 لصاحبه Stephen Rees-Carter.
  6. هذا الدّرس هو جزء من سلسلة دروس حول نشر تطبيقات PHP باستخدام Ansible على Ubuntu، تحدّثنا في أول أجزاء عن الخطوات الأساسيّة من أجل نشر تطبيق، وهي تشكل نقطة بداية من أجل الخطوات المذكورة في هذا الدّرس. سنغطّي في هذا الدّرس إعداد جدولة المهام (crons) وعفاريت الطابور queue daemons، هدفنا في النهاية هو الحصول على خادوم يعمل عليه تطبيق PHP بشكل كامل مع الإعدادات المذكورة آنفًا. سنستخدم إطار عمل Laravel كمثال عن تطبيق PHP ولكن يُمكِن تعديل هذه التعليمات بسهولة لتدعم أطر عمل وتطبيقات أخرى في حال كانت متواجدة لديك. الخطوة الأولى – إعداد مهام cronسنقوم في هذه الخطوة بإعداد أي مهمّة cron نحتاج لإعدادها. إنّ مهام cron هي عبارة عن أوامر تعمل وفق جدول schedule مُحدَّد ويمكن استخدامها لإنجاز أي عدد من المهام من أجل تطبيقنا، كالقيام بمهام الصيانة أو إرسال تحديثات نشاط البريد الإلكتروني – بشكل أساسي أي شيء نحتاج عمله بشكل دوري بدون تدخل المستخدم يدويًّا، يمكن تشغيل مهام cron بتواتر كل دقيقة أو بشكل غير منتظم كما نريد. يأتي Laravel بشكل افتراضي مع أمر حرفي يُدعى schedule:run، وهو مُصمَّم ليعمل كل دقيقة وينفذ المهام المجدولة المُعرَّفة ضمن التطبيق، يعني هذا أنّنا نحتاج فقط لإضافة مهمّة cron واحدة إن كان تطبيقنا يستفيد من هذه الميّزة. تمتلك Ansible وحدة cron مع العديد من الخيارات المختلفة والتي تُترجَم مباشرة إلى خيارات مختلفة نستطيع إعدادها عبر cron: job: الأمر الذي نريد تنفيذه، مطلوب إن كانت state=present.minute، hour، day، weekday: الدقيقة، الساعة، اليوم، الشهر، أو اليوم من أيام الأسبوع الذي يجب فيه تشغيل الوظيفة، على الترتيب.special_time أوقات خاصّة (reboot، yearly، annually، monthly، weekly، daily، hourly): وقت خاص مُحدَّد بكنية nickname.سيقوم افتراضيًّا بإنشاء مهمّة تعمل كل دقيقة، وهو ما نريده، وهذا يعني أنّ المهمّة التي نريدها تبدو كما يلي: New Ansible task - name: Laravel Scheduler cron: > job="run-one php /var/www/laravel/artisan schedule:run 1>> /dev/null 2>&1" state=present user=www-data name="php artisan schedule:run" إنّ الأمر run-one هو مساعد صغير في Ubuntu يضمن أن يعمل الأمر فقط مرّة واحدة، وهذا يعني أنّه إن كان أمر schedule:run سابق لا يزال قيد التشغيل فلن يتم تشغيله مرّة أخرى، وهذا مفيد لتجنّب حالة تصبح فيها مهمّة cron مقفولة ضمن حلقة، ومع الوقت سيتم تشغيل المزيد من النُسَخ لنفس المهمّة حتى تنفذ موارد الخادوم. نفتح الملف php.yml لتحريره: nano php.yml نضيف المهمّة السابقة إلى الـ playbook، يجب أن تتطابق نهاية الملف مع التالي: Updated php.yml . . . - name: Run artisan migrate shell: php /var/www/laravel/artisan migrate --force sudo: yes sudo_user: www-data when: dbpwd.changed - name: Laravel Scheduler cron: > job="run-one php /var/www/laravel/artisan schedule:run 1>> /dev/null 2>&1" state=present user=www-data name="php artisan schedule:run" handlers: . . . نقوم بحفظ وتشغيل الـ playbook: ansible-playbook php.yml --ask-sudo-pass نحدّث الآن الصفحة في متصفحنا، وخلال دقيقة سيتم التحديث وستبدو كما يلي: your_server_ip/'>http://your_server_ip/ Queue: NO Cron: YES يعني هذا أنّ cron تعمل في الخلفية بشكل صحيح، وكجزء من تطبيق المثال هنالك وظيفة cron تعمل كل دقيقة وتقوم بتحديث مُدخَل الحالة في قاعدة البيانات كي يعلم التطبيق أنّها تعمل. الخطوة الثانية – إعداد عفريت الطابور Queue Daemonوكما في حالة الأمر الحرفي schedule:run من الخطوة السابقة، يأتي Laravel مع عامل للطابور يُمكِن تشغيله بالأمر الحرفي queue:work --daemon، سنقوم في هذه الخطوة بإعداد عامل عفريت (بالإنجليزية Daemon وهو برنامج يعمل في خلفيّة النظام) الطابور queue daemon worker من أجل Laravel. يتشابه عمّال الطابور مع وظائف cron في أنّها تقوم بتشغيل المهام في الخلفيّة، ويكمن الفرق في دفع التطبيق للوظائف إلى الطابور، إمّا عبر إجراءات يتم تنفيذها من قبل المستخدم أو من خلال مهام مُجدوَلة عبر وظائف cron، يتم تنفيذ مهام الطابور من قِبَل العامل في وقت واحد، ويتم معالجتها بحسب الطلب عندما يتم العثور عليها في الطابور، تُستخدَم مهام الطابور بشكل شائع من أجل العمل الذي يستغرق وقتًا لتنفيذه، كإرسال رسائل البريد الإلكتروني أو القيام باستدعاءات لواجهة API للخدمات الخارجيّة. وعلى عكس الأمر schedule:run فإنّ هذا الأمر لا يحتاج أن يتم تشغيله كل دقيقة، بل يحتاج بدلًا من ذلك أن يعمل كعفريت daemon في الخلفيّة بشكل ثابت، ومن الطرق الشائعة لفعل هذا هي استخدام حزمة طرف ثالث third-party تُدعى supervisord، ولكن تتطلّب هذه الطريقة فهم كيفيّة إعداد وإدارة النظام المذكور، وهنالك طريقة أسهل لتنفيذها باستخدام cron والأمر run-one. سنقوم بإنشاء مُدخَل cron لبدء عفريت عامل الطابور ونستخدم الأمر run-one لتشغيله، ويعني هذا أن يقوم cron بتشغيل العمليّة في أوّل مرة تعمل فيها، وسيتم تجاهل أي تشغيلات cron لاحقة للأمر عن طريق run-one أثناء تشغيل العامل، وحالما يتوقّف العامل سيسمح run-one للأمر بأن يعمل مرّة أخرى، وسيبدأ عامل الطابور عمله مرّة أخرى، وهي طريقة بسيطة وسهلة الاستخدام بشكل لا يصدّق توفّر علينا الحاجة لتعلّم كيفيّة إعداد واستخدام أداة أخرى. وبأخذ كل ذلك بعين الاعتبار سنقوم بإنشاء مهمّة cron أخرى لتشغيل عامل الطابور لدينا: New Ansible task - name: Laravel Queue Worker cron: > job="run-one php /var/www/laravel/artisan queue:work --daemon --sleep=30 --delay=60 --tries=3 1>> /dev/null 2>&1" state=present user=www-data name="Laravel Queue Worker" نفتح الملف php.yml من أجل تحريره: nano php.yml نضيف المهمّة السابقة إلى الـ playbook، يجب أن تتطابق نهاية الملف مع التالي: Updated php.yml . . . - name: Laravel Scheduler cron: > job="run-one php /var/www/laravel/artisan schedule:run 1>> /dev/null 2>&1" state=present user=www-data name="php artisan schedule:run" - name: Laravel Queue Worker cron: > job="run-one php /var/www/laravel/artisan queue:work --daemon --sleep=30 --delay=60 --tries=3 1>> /dev/null 2>&1" state=present user=www-data name="Laravel Queue Worker" handlers: . . . نقوم بحفظ وتشغيل الـ playbook: ansible-playbook php.yml --ask-sudo-pass نحدّث الصفحة في متصفحنا، وسيتم بعد دقيقة تحديثها لتبدو كما يلي: your_server_ip/'>http://your_server_ip/ Queue: YES Cron: YES يعني هذا أنّ عامل الطابور يعمل في الخلفيّة بشكل صحيح، تقوم وظيفة cron التي بدأنا بها في الخطوة السابقة بدفع الوظيفة إلى الطابور، تحدّث هذه الوظيفة قاعدة البيانات عند تشغيلها لتظهر بأنّها تعمل. نمتلك الآن مثال يعمل لتطبيق Laravel يتضمّن وظائف cron وعمّال طوابير. الخاتمةلقد قمنا في هذا الدّرس بتغطية بعض أكثر المواضيع تقدمًا عند استخدام Ansible من أجل نشر تطبيقات PHP، يمكن تعديل كافّة المهام المستخدمة بسهولة لتتلاءم مع معظم تطبيقات PHP (بحسب متطلباتها الخاصّة)، ويجب أن تشكّل لك نقطة انطلاق جيّدة لإعداد playbook الخاصّة بك من أجل تطبيقاتك. لم نستخدم أي أمر SSH كجزء من هذا الدّرس (باستثناء التحقّق من تسجيل دخول المستخدم www-data)، وتم إعداد كل شيء تلقائيًّا بما في ذلك كلمة سر مستخدم MySQL، بعد متابعتك لهذا الدّرس أصبح تطبيقك جاهزًا للانطلاق ودعم أدوات لدفع تحديثات الشيفرة. ترجمة -وبتصرّف- لـ How To Deploy an Advanced PHP Application Using Ansible on Ubuntu 14.04 لصاحبه Stephen Rees-Carter.
  7. سنواصل في هذا الدّرس حديثنا حول نشر تطبيق PHP باستخدام Ansible. هذا الدّرس هو الجزء الثّاني للسلسلة، إذا لم تقرأ الجزء الأول فمن الأفضل أن تشرع به أوّلا، حيث نُعالج فيه تثبيت Ansible وإعداده. إذا لم تكن لديك أيّة خلفية مُسبقة حول Ansible فمن الأفضل أن تبدأ مع مقال كيفيّة تثبيت وإعداد Ansible على Ubuntu. سنتحدث في هذا القسم من الدّرس عن كيفية الحصول على إطار عمل Laravel وإعداده وإعداد خادوم Nginx لتخديم تطبيق PHP. سنستخدم إطار عمل Laravel كمثال عن تطبيق PHP ولكن يُمكِن تعديل هذه التعليمات بسهولة لتدعم أطر عمل وتطبيقات أخرى في حال كانت متواجدة لديك. المتطلبات الأساسيةيبدأ هذا الدّرس مباشرة من حيث انتهى الجزء الأول من هذه السلسلة، ونحتاج كافّة الملفّات والإعدادات التي تم الحصول عليها في ذلك الجزء، إن لم تقم بإكمال أول درس من هذه السلسلة فنرجو أن تفعل ذلك قبل متابعة هذا الدّرس. الخطوة الأولى – استنساخ مستودع Gitفي هذا القسم سنقوم باستنساخ clone مستودع إطار عمل Laravel إلى الخادوم الخاص بنا باستخدام Git، سنشرح مثل الخطوة الثالثة كافّة الأقسام التي سنقوم بإضافتها إلى الـ playbook، ونضمّن بعدها كامل ملف php.yml من أجلك لتقوم بنسخه ولصقه. وقبل أن نستنسخ مستودع Git الخاص بنا نحتاج إلى التأكّد من وجود الدليل var/www/، نستطيع فعل هذا عن طريق إنشاء مهمّة مع وحدة الملف: - name: create /var/www/ directory file: dest=/var/www/ state=directory owner=www-data group=www-data mode=0700 نحتاج كما أشرنا سابقًا إلى استخدام الوحدة Git لاستنساخ المستودع إلى الخادوم الخاص بنا، وهي عمليّة بسيطة لأنّ كل ما نحتاجه بشكل طبيعي من أجل الأمر git clone هو مستودع المصدر source repository، في هذه الحالة سنعرّف أيضًا الوجهة destination ونخبر Ansible بعدم تحديث المستودع في حال وجوده مسبقًا عن طريق تعيين update=no، وبما أنّنا نستخدم Laravel سنستعمل رابط مستودع git التالي: https://github.com/laravel/laravel.git نحتاج مع ذلك إلى تشغيل المهمّة عن طريق المستخدم www-data للتأكّد من أنّ الصلاحيّات صحيحة، ولعمل هذا نستطيع إخبار Ansible أن ينفّذ الأمر كمستخدم محدّد باستخدام sudo، ستبدو المهمّة النهائية كما يلي: - name: Clone git repository git: > dest=/var/www/laravel repo=https://github.com/laravel/laravel.git update=no sudo: yes sudo_user: www-data ملاحظة: من أجل المستودعات المعتمدة على SSH نستطيع إضافة accept_hostkey=yes لمنع التحقّق من المضيف على SSH من تعليق المهمّة. نفتح الملف php.yml لتحريره: nano php.yml نضيف المهام السابقة إلى الـ playbook، يجب أن يبدو الملف النهائي كما يلي: ... - name: enable php5 mcrypt module shell: php5enmod mcrypt args: creates: /etc/php5/cli/conf.d/20-mcrypt.ini - name: create /var/www/ directory file: dest=/var/www/ state=directory owner=www-data group=www-data mode=0700 - name: Clone git repository git: > dest=/var/www/laravel repo=https://github.com/laravel/laravel.git update=no sudo: yes sudo_user: www-data handlers: - name: restart php5-fpm service: name=php5-fpm state=restarted - name: restart nginx service: name=nginx state=restarted نحفظ الـ playbook ونغلقها، ثمّ نقوم بتشغيلها: ansible-playbook php.yml --ask-sudo-pass الخطوة الثانية – إنشاء تطبيق باستخدام Composerسنستخدم في هذه الخطوة Composer لتثبيت تطبيق PHP واعتمادياته dependencies. يمتلك Composer الأمر create-project الذي يقوم بتثبيت كافّة الاعتماديات المطلوبة ومن ثمّ يُشغِّل خطوات إنشاء المشروع المُعرَّفة في القسم post-create-project-cmd من الملف composer.json، وهي الطريق المفضّلة للتأكّد من إعداد التطبيق بشكل صحيح لاستخدامه لأول مرّة. نستطيع استخدام مهمّة Ansible التالية لتنزيل وتثبيت Composer بشكل عمومي كـ usr/local/bin/composer/، سيكون بعدها قابلًا للنفاذ من قبل أي شخص يستخدم الخادوم بما فيهم Ansible: - name: install composer shell: curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer args: creates: /usr/local/bin/composer ومع وجود Composer مُثبّتًا لدينا فهنالك وحدة لـ Composer يُمكننا استخدامها، في حالتنا نريد إخبار Composer عن مكان مشروعنا (باستخدام المُعامِل working_dir)، ونريد أيضًا تنفيذ الأمر create-project، نحتاج أيضًا لإضافة المُعامِل optimize_autoloader=no لأنّ هذا العَلَم غير مدعوم من قبل الأمر create-project، وكما في حالة الأمر git يجب علينا تنفيذ هذا عن طريق المستخدم www-data للتأكّد من صلاحيّة الأذونات permissions، وبوضع كل ذلك معًا نحصل على هذه المهمّة: - name: composer create-project composer: command=create-project working_dir=/var/www/laravel optimize_autoloader=no sudo: yes sudo_user: www-data ملاحظة: قد تستغرق المهمّة create-project قدرًا كبيرًا من الوقت على خادوم جديد، حيث يمتلك الـ Composer ذاكرة تخزين مؤقّت فارغة ويحتاج إلى تنزيل كل شيء من جديد. نفتح الآن الملف php.yml لتحريره: nano php.yml نضيف المهام السابقة في نهاية القسم tasks فوق handlers بحيث تتوافق نهاية الـ playbook مع التالي: ... - name: Clone git repository git: > dest=/var/www/laravel repo=https://github.com/laravel/laravel.git update=no sudo: yes sudo_user: www-data - name: install composer shell: curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer args: creates: /usr/local/bin/composer - name: composer create-project composer: command=create-project working_dir=/var/www/laravel optimize_autoloader=no sudo: yes sudo_user: www-data handlers: - name: restart php5-fpm service: name=php5-fpm state=restarted - name: restart nginx service: name=nginx state=restarted نقوم أخيرًا بتشغيل الـ playbook: ansible-playbook php.yml --ask-sudo-pass ما الذي سيحدث إن قمنا بتشغيل Ansible مرّة أخرى الآن؟ سيتم تشغيل composer create-project مرّة أخرى، وفي حالة Laravel يعني هذا APP_KEY جديد، لذا نريد بدلًا من ذلك تعيين المهمّة لتعمل فقط بعد استنساخ clone جديد، نستطيع ضمان أنّها تعمل فقط مرّة واحدة عن طريق تسجيل متغيّر يحتوي نتائج المهمّة git clone ومن ثمّ التحقّق من هذه النتائج داخل المهمّة composer create-project، إن تمّ تغيير المهمّة git clone فسيتم تنفيذ composer create-project، أمّا إن لم يحدث ذلك فسيتم تخطّيها. ملاحظة: يبدو أنّه يوجد خطأ برمجي في بعض إصدارات وحدة composer في Ansible، وربّما تعيد الخَرْج OK بدلًا من Changed، حيث تتجاهل أنّه تمّ تنفيذ scripts على الرغم من أنّه لم يتم تثبيت اعتماديات. نفتح الملف php.yml من أجل تحريره: nano php.yml نبحث عن المهمّة git clone، نضيف الخيار register لحفظ نتائج المهمّة إلى المتغير cloned كما يلي: - name: Clone git repository git: > dest=/var/www/laravel repo=https://github.com/laravel/laravel.git update=no sudo: yes sudo_user: www-data register: cloned </code>نبحث بعدها عن المهمّة composer create-project، نضيف الخيار when للتحقّق من المتغيّر cloned لنرى إن تغيّرت قيمته أم لا: - name: composer create-project composer: command=create-project working_dir=/var/www/laravel optimize_autoloader=no sudo: yes sudo_user: www-data when: cloned|changed نقوم بحفظ الـ playbook وتشغيلها: ansible-playbook php.yml --ask-sudo-pass سيوقف الـ Composer الآن تغيير APP_KEY في كل مرّة يتم تشغيله فيها. الخطوة الثالثة – تحديث متغيرات البيئةفي هذه الخطوة سنقوم بتحديث متغيّرات البيئة Environment Variables من أجل تطبيقنا. يأتي Laravel مع ملف env. بشكل افتراضي والذي يقوم بتعيين قيمة APP_ENV إلى local وقيمة APP_DEBUG إلى true، نحتاج إلى تبديل هذه القيم إلى production و false على الترتيب، يُمكِن فعل هذا ببساطة باستخدام الوحدة lineinfile مع المهام التالية: - name: set APP_DEBUG=false lineinfile: dest=/var/www/laravel/.env regexp='^APP_DEBUG=' line=APP_DEBUG=false - name: set APP_ENV=production lineinfile: dest=/var/www/laravel/.env regexp='^APP_ENV=' line=APP_ENV=production نفتح الملف php.yml لتحريره: nano php.yml نضيف هذه المهمّة إلى الـ playbook، يجب أن تبدو نهاية الملف متطابقة مع التالي: ... - name: composer create-project composer: command=create-project working_dir=/var/www/laravel optimize_autoloader=no sudo: yes sudo_user: www-data when: cloned|changed - name: set APP_DEBUG=false lineinfile: dest=/var/www/laravel/.env regexp='^APP_DEBUG=' line=APP_DEBUG=false - name: set APP_ENV=production lineinfile: dest=/var/www/laravel/.env regexp='^APP_ENV=' line=APP_ENV=production handlers: - name: restart php5-fpm service: name=php5-fpm state=restarted - name: restart nginx service: name=nginx state=restarted نقوم بحفظ الـ playbook وتشغيلها: ansible-playbook php.yml --ask-sudo-pass إنّ الوحدة lineinfile مفيدة جدًا من أجل التطويعات tweaks السريعة لأي ملف نصّي، وهي رائعة للتأكّد من تعيين متغيّرات بيئة كهذه بشكل صحيح. الخطوة الرابعة – إعداد Nginxسنقوم في هذا القسم بإعداد Nginx لتخديم تطبيق PHP. إن زرت الآن الخادوم الخاص بك في متصفّح الإنترنت (على سبيل المثال http://your_server_ip )، فسترى صفحة Nginx الافتراضيّة بدلاً من صفحة المشروع الجديد في Laravel، حدث هذا لأنّنا لا زلنا نحتاج إلى إعداد خادوم ويب Nginx لدينا لتخديم التطبيق من الدليل var/www/laravel/public/، لفعل هذا نحتاج لتحديث إعدادات Nginx الافتراضيّة بهذا الدليل وإضافة دعم من أجل php-fpm بحيث يستطيع التعامل مع PHP scripts. نقوم بإنشاء ملف جديد يُدعى nginx.conf: nano nginx.conf نحفظ كتلة الخادوم التالية بداخل هذا الملف، تستطيع متابعة الخطوة الرابعة من هذا الدّرس من أجل المزيد من التفاصيل حول إعدادات Nginx، تُحدِّد التعديلات التالية مكان دليل Laravel العام وتتحقّق من استخدام Nginx لاسم المضيف الذي عرّفناه في الملف hosts كـ server_name مع المتغيّر inventory_hostname. nginx.conf server { listen 80 default_server; listen [::]:80 default_server ipv6only=on; root /var/www/laravel/public; index index.php index.html index.htm; server_name {{ inventory_hostname }}; location / { try_files $uri $uri/ =404; } error_page 404 /404.html; error_page 500 502 503 504 /50x.html; location = /50x.html { root /var/www/laravel/public; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } نحفظ الملف nginx.conf ونغلقه. بإمكاننا الآن استخدام وحدة القالب template module لدفع ملف الإعدادات الجديدة عبرها، تبدو وحدة template مشابهة جدًا للوحدة copy، ولكن يوجد فرق كبير بينهما، فالوحدة copy ستنسخ ملف أو عدّة ملفّات بدون القيام بأيّة تغييرات، بينما تنسخ الوحدة template ملفًّا واحدًا وتقوم بتحليل كافّة الملفّات الموجودة بداخله، ولأنّنا استخدمنا {{ inventory_hostname }} داخل ملف إعداداتنا سنستخدم الوحدة template بحيث يتم تحليلها بداخل عنوان IP الذي استخدمناه في الملف hosts، وبهذه الطريقة لا يتوجّب علينا كتابة شيفرة محدّدة لملفّات الإعدادات التي تستخدمها Ansible. ومع ذلك فكما هو معتاد عند كتابة المهام نحتاج إلى أن نأخذ بعين الاعتبار ما سيحدث على الخادوم، ولأنّنا نقوم بتغيير إعدادات Nginx نحتاج لإعادة تشغيل Nginx و php-fpm، يتم هذا باستخدام الخيار notify: - name: Configure nginx template: src=nginx.conf dest=/etc/nginx/sites-available/default notify: - restart php5-fpm - restart nginx نفتح ملف php.yml: nano php.yml نضيف مهمّة nginx هذه في نهاية قسم المهام، ينبغي أن يبدو الملف php.yml كما يلي: php.yml --- - hosts: php sudo: yes tasks: - name: install packages apt: name={{ item }} update_cache=yes state=latest with_items: - git - mcrypt - nginx - php5-cli - php5-curl - php5-fpm - php5-intl - php5-json - php5-mcrypt - php5-sqlite - sqlite3 - name: ensure php5-fpm cgi.fix_pathinfo=0 lineinfile: dest=/etc/php5/fpm/php.ini regexp='^(.*)cgi.fix_pathinfo=' line=cgi.fix_pathinfo=0 notify: - restart php5-fpm - restart nginx - name: enable php5 mcrypt module shell: php5enmod mcrypt args: creates: /etc/php5/cli/conf.d/20-mcrypt.ini - name: create /var/www/ directory file: dest=/var/www/ state=directory owner=www-data group=www-data mode=0700 - name: Clone git repository git: > dest=/var/www/laravel repo=https://github.com/laravel/laravel.git update=no sudo: yes sudo_user: www-data register: cloned - name: install composer shell: curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer args: creates: /usr/local/bin/composer - name: composer create-project composer: command=create-project working_dir=/var/www/laravel optimize_autoloader=no sudo: yes sudo_user: www-data when: cloned|changed - name: set APP_DEBUG=false lineinfile: dest=/var/www/laravel/.env regexp='^APP_DEBUG=' line=APP_DEBUG=false - name: set APP_ENV=production lineinfile: dest=/var/www/laravel/.env regexp='^APP_ENV=' line=APP_ENV=production - name: Configure nginx template: src=nginx.conf dest=/etc/nginx/sites-available/default notify: - restart php5-fpm - restart nginx handlers: - name: restart php5-fpm service: name=php5-fpm state=restarted - name: restart nginx service: name=nginx state=restarted نقوم بحفظ الـ playbook وتشغيلها مرّة أخرى: ansible-playbook php.yml --ask-sudo-pass حالما تكتمل نعود إلى متصفحنا ونقوم بتحديثه، ينبغي أن نرى الآن صفحة المشروع الجديد في Laravel. الخاتمةيُغطّي هذا الدرس نشر تطبيق PHP مع مستودع عام، وبينما يكون هذا مثاليًّا من أجل تعلّم كيفيّة عمل Ansible، فإنّك لن تعمل دائمًا على مشاريع مفتوحة المصدر بشكل كامل مع مستودعات مفتوحة، ويعني هذا أنّك ستحتاج إلى استيثاق git clone في الخطوة الثالثة مع مستودعك الخاص، يُمكِن فعل هذا بسهولة باستخدام مفاتيح SSH. على سبيل المثال بعدما تقوم بإنشاء وإعداد مفاتيح نشر SSH على مستودعك تستطيع استخدام Ansible لنسخها وإعدادها على خادومك قبل مهمّة git clone: - name: create /var/www/.<abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">ssh</abbr>/ directory file: dest=/var/www/.<abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">ssh</abbr>/ state=directory owner=www-data group=www-data mode=0700 - name: copy private <abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">ssh</abbr> key copy: src=deploykey_rsa dest=/var/www/.<abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">ssh</abbr>/id_rsa owner=www-data group=www-data mode=0600يجب أن يسمح هذا للخادوم بالاستيثاق بشكل صحيح ونشر تطبيقك. لقد قمنا للتو بنشر تطبيق PHP بسيط على خادوم ويب Nginx معتمد على Ubuntu باستخدام Composer لإدارة الاعتماديّات، وتمّ كل هذا بدون الحاجة للدخول مباشرة إلى الخادوم الخاصّ بنا وتنفيذ أي أمر بشكل يدوي. ترجمة -وبتصرّف- لـ How To Deploy a Basic PHP Application Using Ansible on Ubuntu 14.04 لصاحبه Stephen Rees-Carter.
  8. هذا الدّرس هو جزء من سلسلة دروس حول نشر تطبيقات PHP باستخدام Ansible على Ubuntu، تحدّثنا في الجزئين السّابقين عن تثبيت Ansible وإعداده ومن ثم عن إعداد Laravel وNginx. سنغطّي في هذا الدّرس إعداد مفاتيح SSH لتدعم أدوات نشر وتوزيع الشيفرة، وإعداد الجدار الناري للنظام، هدفنا في النهاية هو الحصول على خادوم يعمل عليه تطبيق PHP بشكل كامل مع الإعدادات المذكورة آنفًا. المتطلبات الأساسيةيبدأ هذا الدّرس مباشرة من حيث انتهى الجزء السّابق من هذه السلسلة، ونحتاج كافّة الملفّات والإعدادات التي تم الحصول عليها في ذلك الجزء، إن لم تقم بإكمال أول قسمين من هذه السلسلة فنرجو أن تفعل ذلك قبل متابعة هذا الدّرس. الخطوة الأولى – تبديل مستودع التطبيقسنقوم في هذه الخطوة بتحديث مستودع Git إلى مثال عن مستودع مُخصَّص قليلًا. بما أنّ تثبيت Laravel الافتراضي لا يتطلّب الميّزات المتقدمة التي سنقوم بإعدادها في هذا الدّرس فسنقوم بتبديل المستودع الموجود حاليًّا إلى مثال عن مستودع مع إضافة شيفرة للتنقيح debugging code فقط من أجل أن نظهر متى يعمل كل شيء، يُوجد المستودع الذي سنستخدمه على الرابط https://github.com/do-community/do-ansible-adv-php. نقوم بتغيير الدليل إلى ansible-php: cd ~/ansible-php/ نفتح playbook الموجودة حاليًّا من أجل تحريرها: nano php.yml نقوم بإيجاد وتحديث المهمّة “Clone git repository” بحيث تبدو كما يلي: Updated Ansible task - name: Clone git repository git: > dest=/var/www/laravel repo=https://github.com/do-community/do-ansible-adv-php update=yes version=example sudo: yes sudo_user: www-data register: cloned نحفظ ونشغل الـ playbook: ansible-playbook php.yml --ask-sudo-pass وبعد أن يتم تشغيلها نزور خادومنا في متصفح الويب لدينا (على الرابط http://your_server-ip بعد وضع عنوان خادومك)، ينبغي أن نشاهد رسالة تقول لم يتم العثور على التعريف "could not find driver". يعني هذا أنّنا نجحنا في استبدال المستودع الافتراضي بمثال مستودعنا، ولكن لا يستطيع التطبيق الاتصال بقاعدة البيانات، وهو ما نتوقع مشاهدته هنا، وسنقوم بتثبيت وإعداد قاعدة البيانات لاحقًا في هذا الدّرس. الخطوة الثانية – إعداد مفاتيح SSH من أجل النشرسنقوم في هذه الخطوة بإعداد مفاتيح SSH والتي يُمكن استخدامها من أجل نشر شيفرة التطبيق. ومع أنّ Ansible رائعة من أجل المحافظة على الإعدادات وإعداد الخواديم والتطبيقات، فيتم عادةً استخدام أدوات مثل Envoy و Rocketeer من أجل دفع تغييرات الشيفرة إلى الخادوم وتنفيذ أوامر التطبيق عن بُعد، تتطلّب أغلب هذه الأدوات اتصال SSH يتمكن من النفاذ إلى تثبيت التطبيق بشكل مباشر، يعني هذا في حالتنا أنّنا نحتاج إلى إعداد مفاتيح SSH من أجل المستخدم www-data. سنحتاج إلى ملف مفتاح عام من أجل المستخدم الذي نرغب بدفع الشيفرة منه، يُوجد هذا الملف بشكل نموذج في المسار ssh/id_rsa.pub./~، ننسخ هذا الملف إلى الدليل ansible-php: cp ~/.ssh/id_rsa.pub ~/ansible-php/deploykey.pubبإمكاننا استخدام الوحدة authorized_key لـ Ansible من أجل تثبيت مفتاحنا العام داخل var/www/.ssh/authorized_keys/ والذي سيسمح لأدوات النشر بالاتصال والنفاذ إلى تطبيقنا، تحتاج الإعدادات فقط إلى معرفة مكان المفتاح، باستخدام lookup، وإلى معرفة المستخدم الذي سيتم تثبيت المفتاح لأجله (www-data في حالتنا). New Ansible task - name: Copy public key into /var/www authorized_key: user=www-data key="{{ lookup('file', 'deploykey.pub') }}" نحتاج أيضًا لإعداد صدفة shell المستخدم www-data كي نستطيع فعليًّا تسجيل الدخول، وإلّا سيسمح SSH بالاتصال ولكن لن يتم عرض صدفة shell للمستخدم، يُمكن عمل هذا باستخدام الوحدة user وتعيين الصدفة إلى /bin/bash (أو الصدفة المفضلة لديك): New Ansible task - name: Set www-data user shell user: name=www-data shell=/bin/bash نفتح الآن الـ playbook لتحريرها من أجل إضافة المهام الجديدة: nano php.yml نضيف المهام السابقة إلى الـ playbook التي تُدعى php.yml، يجب أن تبدو نهاية الملف متطابقة مع التالي: Updated php.yml . . . - name: Configure nginx template: src=nginx.conf dest=/etc/nginx/sites-available/default notify: - restart php5-fpm - restart nginx - name: Copy public key into /var/www authorized_key: user=www-data key="{{ lookup('file', 'deploykey.pub') }}" - name: Set www-data user shell user: name=www-data shell=/bin/bash handlers: . . . نقوم بحفظ وتشغيل الـ playbook: ansible-playbook php.yml --ask-sudo-pass عندما تنتهي Ansible من ذلك ينبغي أن نكون قادرين على الدخول باستخدام SSH عن طريق المستخدم www-data: ssh www-data@your_server_ip إن استطعنا تسجيل الدخول بنجاح فهي تعمل بشكل صحيح، بإمكاننا الآن تسجيل الخروج عن طريق إدخال logout أو ضغط CTRL+D. لن نحتاج إلى استخدام هذا الاتصال في أي خطوات لاحقة، ولكن يبقى مفيدًا إن قمنا بإعداد أدوات أخرى، كما أشرنا سابقًا، أو من أجل التنقيح العام general debugging وصيانة التطبيق كما هو مطلوب. الخطوة الثالثة – إعداد الجدار الناريسنقوم في هذه الخطوة بإعداد الجدار الناري على الخادوم للسماح فقط بالاتصالات من أجل HTTP وSSH. يأتي Ubuntu مع جدار ناري يُدعى UFW (الجدار الناري غير المعقد Uncomplicated Firewall) مُثبَّت عليه بشكل افتراضي، وتدعمه Ansible بالوحدة ufw، يمتلك عدد من الميزات القوية وتمّ تصميمه ليكون بسيطًا قدر الإمكان وهو ملائم بشكل مثالي لخواديم الويب المحتواة ذاتيًّا والتي تحتاج فقط إلى عدة منافذ مفتوحة، نرغب في حالتنا بأن يكون المنفذ 80 (من أجل HTTP) والمنفذ 22 (من أجل SSH) مفتوحًا، وربّما قد تريد المنفذ 443 مفتوحًا من أجل HTTPS. تمتلك الوحدة ufw عددًا من الخيارات المختلفة تقوم بتنفيذ مهام مختلفة، وهذه المهام التي نريد تنفيذها هي: تمكين UFW ورفض كامل حركة مرور البيانات traffic القادمة افتراضيًّا.فتح منفذ SSH ولكن مع تحديده لمنع هجمات القوة القاسية brute force attacks.فتح منفذ HTTP.يُمكِن فعل هذا باستخدام المهام التالية على الترتيب: New Ansible tasks - name: Enable UFW ufw: direction=incoming policy=deny state=enabled - name: UFW limit SSH ufw: rule=limit port=ssh - name: UFW open HTTP ufw: rule=allow port=http </code>نفتح الملف php.yml من أجل تحريره: nano php.ymlنضيف المهام السابقة إلى الـ playbook، ينبغي أن تتطابق نهاية الملف مع التالي: Updated php.yml . . . - name: Copy public key into /var/www authorized_key: user=www-data key="{{ lookup('file', 'deploykey.pub') }}" - name: Set www-data user shell user: name=www-data shell=/bin/bash - name: Enable UFW ufw: direction=incoming policy=deny state=enabled - name: UFW limit SSH ufw: rule=limit port=ssh - name: UFW open HTTP ufw: rule=allow port=http handlers: . . . نقوم بحفظ وتشغيل الـ playbook: ansible-playbook php.yml --ask-sudo-pass بعد أن يتم هذا بنجاح يجب أن نكون قادرين على الاتصال عبر SSH (باستخدام Ansible) أو HTTP إلى خادومنا، ستكون المنافذ الأخرى مقفلة الآن. نستطيع التحقّق من حالة UFW في أي وقت عن طريق تنفيذ هذا الأمر: ansible php --sudo --ask-sudo-pass -m shell -a "ufw status verbose" وبتقسيم أمر Ansible السابق من أجل فهمه نجد: ansible: تقوم بتنفيذ مهمّة Ansible خام بدون playbook.php: تقوم بتنفيذ المهمّة على المضيفين في هذه المجموعة.--sudo: تنفّذ الأمر كـ sudo.--ask-sudo-pass: تقوم بالحث prompt من أجل كلمة سر sudo.-m shell: تقوم بتشغيل وحدة الصدفة shell.-a "ufw status verbose“: الخيارات التي يجب تمريرها إلى الوحدة، وبما أنّها أمر shell نقوم بتمرير الأمر الخام raw (أي ufw status verbose) مباشرة بدون أي خيارات key=value.يجب أن يُعيد شيئًا مشابهًا لهذا: UFW status output your_server_ip | success | rc=0 >> Status: active Logging: on (low) Default: deny (incoming), allow (outgoing), disabled (routed) New profiles: skip To Action From -- ------ ---- 22 LIMIT IN Anywhere 80 ALLOW IN Anywhere 22 (v6) LIMIT IN Anywhere (v6) 80 (v6) ALLOW IN Anywhere (v6) ترجمة -وبتصرّف- لـ How To Deploy an Advanced PHP Application Using Ansible on Ubuntu 14.04 لصاحبه Stephen Rees-Carter.
  9. ستغطّي هذه السّلسلة عمليّة نشر تطبيق PHP بسيط باستخدام Ansible، الهدف النّهائي سيكون الحصول على خادوم ويب جديد يُخدِّم تطبيق PHP بسيط بدون أي اتصال عبر SSH أو تشغيل يدوي للأوامر على الخادوم الهدف، سنغطي في هذا القسم من الدرس تثبيت Ansible وإعداد البيئة بشكل عام. سنستخدم إطار عمل Laravel كمثال عن تطبيق PHP ولكن يُمكِن تعديل هذه التعليمات بسهولة لتدعم أطر عمل وتطبيقات أخرى في حال كانت متواجدة لديك. المتطلبات الأساسيةسنستخدم Ansible لتثبيت وإعداد Nginx، PHP، وخدمات أخرى على خادوم Ubuntu 14.04 ، يعتمد هذا الدّرس على معرفتك الأساسية بـ Ansible لذا إن كنت جديدًا عليها فبإمكانك قراءة درس Ansible الأساسي أولًا. ستحتاج لمتابعة هذا الدّرس إلى: خادوم Ubuntu 14.04 بأي حجم والذي سنستخدمه لإعداد ونشر تطبيق PHP الخاص بنا عليه، ستتم الإشارة إلى عنوان IP هذا الجهاز بـ your_server_ip خلال هذا الدّرس.خادوم Ubuntu 14.04 والذي سنستخدمه من أجل Ansible، وهو الخادوم الذي سنبقى في وضعية تسجيل دخول عليه في كامل هذا الدّرس.إعداد مستخدم غير جذري مع صلاحيّات sudo لكل خادوم.مفاتيح SSH من أجل خادوم Ansible لتصريح تسجيل الدخول على خادوم نشر PHP، ويُمكِن إعدادها باتّباع هذه السلسلة وتطبيقها على خادوم Ansible الخاص بنا.الخطوة الأولى – تثبيت Ansibleيُمكِن إنجاز هذه الخطوة بسهولة عن طريق تثبيت PPA (أرشيف الحِزَم الشخصي Personal Package Archive) وتثبيت حزمة Ansible باستخدام apt. نُضيف أوّلًا PPA باستخدام الأمر apt-add-repository: sudo apt-add-repository ppa:ansible/ansibleوبعد انتهائه نقوم بتحديث ذاكرة التخزين المؤقّت cache لـ apt: sudo apt-get update نقوم بتثبيت Ansible أخيرًا: sudo apt-get install ansibleحالما يتم تثبيت Ansible نقوم بإنشاء دليل جديد للعمل بداخله وضبط الإعدادات الأساسيّة، تستخدم Ansible افتراضيًّا ملف مضيفين hosts موجود في المسار etc/ansible/hosts/، وهو يحتوي كافّة الخواديم التي يُديرها، وبينما يكون هذا الملف مناسبًا لبعض حالات الاستخدام فهو عام global، وهو ما لا نريده هنا. سنقوم من أجل هذا الدّرس بإنشاء ملف مضيفين محلّي local واستخدامه بدلًا من الملف السابق، نستطيع فعل هذا عن طريق إنشاء ملف إعدادات Ansible جديد بداخل دليل العمل لدينا، والذي بإمكاننا استخدامه لإخبار Ansible بأن تبحث عن ملف المضيفين داخل نفس الدليل. نُنشِئ مُجلّدًا جديدًا (سنستخدمه لبقيّة هذا الدّرس): mkdir ~/ansible-php ننتقل إلى داخل المُجلّد الجديد: cd ~/ansible-php/نُنشِئ ملفًّا جديدًا يُدعى ansible.cfg ونفتحه من أجل تحريره باستخدام nano أو أي مُحرِّر نصوص تفضله: nano ansible.cfgنضيف خيار الإعدادات hostfile مع القيمة hosts في المجموعة [defaults] عن طريق نسخ ما يلي إلى الملف ansible.cfg: ansible.cfg [defaults] hostfile = hostsنحفظ الملف ansible.cfg ونغلقه، نقوم بعدها بإنشاء الملف hosts والذي يحتوي على عنوان IP لخادوم PHP حيث سيتم نشر تطبيقنا. nano hostsننسخ ما يلي لإضافة قسم من أجل php مع وضع عنوان IP الخاص بخادومك بدلًا من your_server_ip ووضع اسم المستخدم غير الجذري الذي قمت بإنشائه في المتطلبات الأساسيّة على خادوم PHP بدلًا من sammy: hosts [php] your_server_ip ansible_ssh_user=sammy نحفظ ونغلق الملف hosts، فلنقم بإجراء تحقّق أبسط للتأكد من قدرة Ansible على الاتصال بالمضيف كما هو متوقّع عن طريق استدعاء الوحدة ping على المجموعة php الجديدة: ansible php -m pingربّما تحصل على تحقّق من استيثاق مُضيف SSH اعتمادًا على كونك قد سجلّت الدخول إلى هذا المُضيف من قبل، ينبغي أن تعود ping باستجابة ناجحة تبدو كما يلي: Output 111.111.111.111 | success >> { "changed": false, "ping": "pong" تمّ الآن تثبيت وإعداد Ansible بنجاح، نستطيع الانتقال إلى إعداد خادوم الويب لدينا. الخطوة الثانية – تثبيت الحزم المطلوبةسنقوم في هذه الخطوة بتثبيت بعض حِزَم النظام المطلوبة باستخدام Ansible و apt، سنثبت تحديدًا git، nginx، sqlite3، mcrypt، وبعض حِزَم php5-*. نحتاج قبل إضافة الوحدة apt لتثبيت الحِزَم التي نريدها إلى إنشاء playbook بسيط (وهو عبارة عن قواعد تُحدِّد إعدادات Ansible)، سنبني على هذا الـ playbook مع تقدّمنا في هذا الدّرس، نقوم بإنشاء playbook جديد يُدعى php.yml: nano php.yml نلصق الإعدادات التالية، يُحدِّد أول سطرين مجموعة المضيفين التي نرغب باستخدامها (php) وتتحقّق من أنّها تنفّذ الأوامر باستخدام sudo افتراضيًّا، تُضيف باقي الأسطر وحدة بالحِزَم التي نحتاجها، تستطيع تخصيصها من أجل تطبيقاتك الخاصّة أو استخدام الإعدادات التالية إن كنت تتبع مثال تطبيق Laravel: --- - hosts: php sudo: yes tasks: - name: install packages apt: name={{ item }} update_cache=yes state=latest with_items: - git - mcrypt - nginx - php5-cli - php5-curl - php5-fpm - php5-intl - php5-json - php5-mcrypt - php5-sqlite - sqlite3نحفظ الملف php.yml، ونقوم أخيرًا بتشغيل ansible-playbook لتثبيت الحِزَم على الخادوم، يجب ألّا ننسى استخدام الخيار --ask-sudo-pass إن كان يتطلّب مستخدم sudo على خادوم PHP كلمة سر: ansible-playbook php.yml --ask-sudo-passالخطوة الثالثة – تعديل ملفات إعدادات النظامسنقوم في هذا القسم بتعديل بعض ملفّات إعدادات النظام على خادوم PHP، أهم خيار إعدادات يُمكِن تغييره (بغض النظر عن ملفّات Nginx، والتي سيتم تغطيتها في خطوة لاحقة) هو الخيار cgi.fix_pathinfo في php5-fpm، لأنّ القيمة الافتراضيّة له تُشكِّل خطرًا أمنيًّا. سنوضّح أوّلًا جميع الأقسام التي سنضيفها إلى هذا الملف، ونضمّن بعدها كامل الملف php.yml من أجلك لكي تقوم بنسخه ولصقه. يُمكِن استخدام الوحدة lineinfile للتأكّد من أنّ قيمة الإعدادات ضمن الملف مطابقة تمامًا لما نتوقعه، يُمكِن عمل هذا باستخدام تعبير نمطي regular expression عام بحيث تتمكّن Ansible من فهم معظم الصيغ التي من المحتمل أن يكون فيها المُعامِل، سنحتاج أيضًا لإعادة تشغيل php5-fpm وnginx لضمان تطبيق التغييرات، لذا نحتاج إلى إضافة مُداوِلَين handlers اثنين أيضًا في قسم جديد للمداولات handlers، تكون المداولات مثاليّة لهذا لأنّه يتم إطلاقها فقط عند تغيير المهمّة، ويتم أيضًا تشغيلها في نهاية الـ playbook، لذا يُمكن لمهام متعدّدة استدعاء نفس المُداوِل وسيعمل فقط مرّة واحدة. يبدو القسم الذي يُنفِّذ ما سبق كما يلي: name: ensure php5-fpm cgi.fix_pathinfo=0 lineinfile: dest=/etc/php5/fpm/php.ini regexp='^(.*)cgi.fix_pathinfo=' line=cgi.fix_pathinfo=0 notify: - restart php5-fpm - restart nginx handlers: - name: restart php5-fpm service: name=php5-fpm state=restarted - name: restart nginx service: name=nginx state=restartedملاحظة: خطأ برمجي bug في إصدار Ansible 1.9.1 يوجد خطا برمجي في إصدار Ansible 1.9.1 يمنع php5-fpm من إعادة تشغيلها مع الوحدة service، وقد استخدمنا هذا في مُداولاتنا. وحتى يتم إصدار إصلاح له نستطيع الالتفاف على هذه المشكلة عن طريق تغيير المُداوِل restart php5-fpm من استخدام الأمر service إلى استخدام الأمر shell كما يلي: - name: restart php5-fpm shell: service php5-fpm restartسيتجاوز هذا المشكلة ويعيد تشغيل php5-fpm بشكل صحيح. نحتاج بعد ذلك أيضًا إلى التأكّد من تمكين الوحدة php5-mcrypt، يُمكن فعل هذا عن طريق تنفيذ script يُدعى php5enmod باستخدام صدفة المهام shell task والتحقّق من وجود الملف 20-mcrypt.ini في مكانه عند تمكينه، لاحظ أنّنا نخبر Ansible أنّ المهمّة تقوم بإنشاء ملف مُحدَّد، فإن كان هذا الملف موجودًا فلن يتم تشغيل المهمّة: name: enable php5 mcrypt module shell: php5enmod mcrypt args: creates: /etc/php5/cli/conf.d/20-mcrypt.iniنفتح الآن الملف php.yml لتحريره مرّة أخرى: nano php.ymlنضيف المهام والمداولات السابقة بحيث يتطابق الملف مع التالي: --- - hosts: php sudo: yes tasks: - name: install packages apt: name={{ item }} update_cache=yes state=latest with_items: - git - mcrypt - nginx - php5-cli - php5-curl - php5-fpm - php5-intl - php5-json - php5-mcrypt - php5-sqlite - sqlite3 - name: ensure php5-fpm cgi.fix_pathinfo=0 lineinfile: dest=/etc/php5/fpm/php.ini regexp='^(.*)cgi.fix_pathinfo=' line=cgi.fix_pathinfo=0 notify: - restart php5-fpm - restart nginx - name: enable php5 mcrypt module shell: php5enmod mcrypt args: creates: /etc/php5/cli/conf.d/20-mcrypt.ini handlers: - name: restart php5-fpm service: name=php5-fpm state=restarted - name: restart nginx service: name=nginx state=restarted نقوم أخيرًا بتشغيل playbook: ansible-playbook php.yml --ask-sudo-pass يمتلك الآن الخادوم كافّة الحِزَم المطلوبة مُثبّتة عليه ومجموعة الإعدادات الأساسيّة جاهزة للانطلاق. الخاتمةتحدثنا في القسم الأول من هذا الدّرس عن طريقة تثبيت Ansible وإعداد البيئة بشكل عام من أجل التحضير لعمليّة نشر تطبيق PHP بسيط باستخدام Ansible، وسنكمل في القسم الثاني الحصول على Laravel وإعداده وإعداد خادوم Nginx لتخديم تطبيق PHP. ترجمة -وبتصرّف- لـ How To Deploy a Basic PHP Application Using Ansible on Ubuntu 14.04 لصاحبه Stephen Rees-Carter.