إدارة الإعدادات مع Ansible

Ansible على نطاق واسع

18 دقيقة الدرس 9 من 30

Ansible على نطاق واسع

تشغيل playbook على عشرة خوادم أمر سهل. أما تشغيل نفس الـ playbook على عشرة آلاف خادم — عبر مراكز بيانات متعددة وحسابات سحابية وقطاعات شبكة مختلفة، ضمن قيود نوافذ التغيير الصارمة — فهي مشكلة هندسية مختلفة جوهريًا. يتناول هذا الدرس الاستراتيجيات ومعاملات الضبط والأدوات التي تميّز إعداد Ansible الهاوي عن منصة أتمتة أسطول احترافية في بيئة الإنتاج.

فهم Forks: التوازي في Ansible

بشكل افتراضي، يعالج Ansible 5 خوادم فقط بالتوازي (إعداد forks). هذا الإعداد الافتراضي متحفظ عمدًا وغير مناسب لمعظم الأساطيل في بيئة الإنتاج. تتحكم الـ forks في عدد اتصالات SSH التي يفتحها عقدة التحكم في وقت واحد.

# ansible.cfg — ضبط عقدة التحكم وفق قدرتها [defaults] forks = 50 # اتصالات SSH متوازية؛ ارفعه إلى 100-500 على عقد تحكم قوية host_key_checking = False pipelining = True # يلغي جولة إضافية لكل مهمة؛ يتطلب requiretty=False على الأهداف gathering = smart # تخزين مؤقت للحقائق؛ لا إعادة جمع للخوادم غير المتغيرة fact_caching = redis fact_caching_connection = localhost:6379:0 fact_caching_timeout = 86400 [ssh_connection] ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o ServerAliveInterval=10 retries = 3

ثلاثة إعدادات تحقق أكبر تأثير على نطاق واسع:

  • forks — ارفعه إلى 50-200 لأساطيل السحابة. السقف العملي هو حد الملفات المفتوحة (ulimit -n) والذاكرة المتاحة (~10 MB لكل fork).
  • pipelining = True — يجمع رفع الوحدة وتنفيذها في استدعاء SSH واحد بدلًا من ثلاثة. على playbook بـ 500 خادم يمكن أن يوفر 30-40% من وقت التشغيل.
  • fact_caching — يتجنب إعادة تشغيل مهمة gather_facts في كل تشغيل. مع Redis، تبقى الحقائق محتفظة بها بين التشغيلات لمدة fact_caching_timeout ثانية.

استراتيجيات التنفيذ

يأتي Ansible بثلاث استراتيجيات تنفيذ مدمجة تغيّر كيفية توزيع المهام عبر الخوادم.

Ansible execution strategies comparison linear (default) Task 1 → all hosts Task 2 → all hosts Task 3 → all hosts Waits for ALL hosts before next task. Safe, predictable. free Host A: T1,2,3 Host B: T1 Host A: done Host B: T2,3 Each host races independently. Maximum speed, no ordering guarantees. serial (rolling) Batch 1 (10%) → T1,2,3 Batch 2 (10%) → T1,2,3 Batch 3 (10%) → T1,2,3 Rolling deploy: capacity stays up, blast radius limited.
مقارنة استراتيجيات تنفيذ Ansible الثلاث: linear (الافتراضي الآمن)، free (أقصى إنتاجية)، وserial/rolling (نشر إنتاج متحكَّم فيه مع تحديد نطاق التأثير).
# نشر متدحرج — تحديث 10% من الأسطول في كل مرة - name: Rolling application deploy hosts: app_servers serial: - "10%" # الدفعة الأولى: 10% من الخوادم - "25%" # الدفعة الثانية: 25% - "100%" # الخوادم المتبقية max_fail_percentage: 5 # إيقاف إذا فشل أكثر من 5% من الدفعة strategy: free # داخل كل دفعة، الخوادم تعمل باستقلالية pre_tasks: - name: Remove host from load balancer uri: url: "http://lb.internal/api/drain/{{ inventory_hostname }}" method: POST delegate_to: localhost tasks: - name: Deploy new application artifact ansible.builtin.unarchive: src: "s3://artifacts/app-{{ version }}.tar.gz" dest: /opt/app remote_src: yes - name: Restart service ansible.builtin.systemd: name: app state: restarted post_tasks: - name: Re-add host to load balancer uri: url: "http://lb.internal/api/enable/{{ inventory_hostname }}" method: POST delegate_to: localhost
اضبط max_fail_percentage: 0 للنشر الذي لا يتسامح مع أي فشل. استخدم قائمة serial متدرجة لاختبار دفعة صغيرة أولًا قبل التطبيق على بقية الأسطول.

AWX وAnsible Automation Platform (Controller)

سير عمل ansible-playbook من سطر الأوامر لا يتوسع تنظيميًا. من شغّل آخر playbook؟ على أي خوادم؟ بأي متغيرات؟ هل نجح؟ هل يمكن لمهندس غير متخصص تشغيله بأمان؟ هذه الأسئلة بلا إجابات دون مستوى تحكم. هذا المستوى هو AWX (المصدر المفتوح) أو Red Hat Ansible Automation Platform / Automation Controller (المنتج المؤسسي).

الإمكانات الرئيسية التي يضيفها AWX على سطر الأوامر:

  • RBAC — الفرق تحصل على صلاحيات لـ job templates محددة، لا وصول Shell لعقدة التحكم.
  • إدارة بيانات الاعتماد — مفاتيح SSH وكلمات مرور Vault وبيانات السحابة مخزنة مشفرة في قاعدة بيانات AWX؛ لا تُكشف للمشغلين.
  • Job templates — مجموعة مسمّاة وموثّقة من: playbook + inventory + credentials + متغيرات. أي شخص يملك الصلاحية يمكنه تشغيلها دون معرفة CLI.
  • Surveys — نماذج ويب تطلب من المشغل إدخال متغيرات (مثل البيئة المستهدفة أو الإصدار) قبل تشغيل job. حقن متغيرات آمن وقابل للتدقيق.
  • Workflow job templates — رسوم بيانية موجّهة (DAGs) من job templates: "شغّل التصلب، ثم النشر، ثم اختبارات الدخان؛ إذا فشلت الاختبارات، شغّل الاسترداد."
  • سجل التدقيق — كل job يحفظ stdout الكامل والمستخدم الذي أطلقه والطوابع الزمنية والنتيجة. ضروري للامتثال (SOC 2، PCI-DSS).
  • الجدولة — تنفيذ مدفوع بـ cron لتطبيق الامتثال الليلي.
في الواقع العملي، تتعامل فرق التقنية الكبيرة مع job templates في AWX باعتبارها الطريقة الوحيدة المعتمدة لتشغيل Ansible في الإنتاج. المهندسون الذين يحتاجون تشغيلًا استثنائيًا يفتحون تذكرة تُطلق job template ذات معاملات — لا SSH إلى عقدة التحكم. هذا يلغي مشكلة "يعمل على جهازي" ويوفر سجل كامل للتغييرات.

الـ Inventory الديناميكي على نطاق واسع

ملفات inventory/hosts.ini الثابتة لا يمكن صيانتها بعد عشرات الخوادم. على نطاق واسع، يجب سحب الـ inventory ديناميكيًا من مصدر الحقيقة — مزود السحابة أو CMDB أو سجل الخدمات.

# inventory/aws_ec2.yml — إضافة AWS dynamic inventory plugin: amazon.aws.aws_ec2 regions: - us-east-1 - eu-west-1 filters: tag:Env: production instance-state-name: running keyed_groups: - key: tags.Role prefix: role - key: placement.availability_zone prefix: az compose: ansible_host: public_ip_address # أو private_ip_address لأساطيل متصلة عبر VPN ansible_user: "'ec2-user'" # تشغيل: ansible-inventory -i inventory/aws_ec2.yml --graph # role_webserver # |--10.0.1.5 # |--10.0.1.6 # az_us_east_1a # |--10.0.1.5

متى يكون Ansible الأداة الخاطئة: البنية التحتية الثابتة

يتميز Ansible في تهيئة الخوادم القابلة للتعديل — الأجهزة التي تعيش طويلًا بما يكفي لتستحق إدارة مستمرة. لكن الاتجاه الحديث في السحابة هو البنية التحتية الثابتة (Immutable Infrastructure): بناء صورة جهاز مرة واحدة ونشرها، ثم استبدالها بدلًا من تعديلها عند الحاجة للتغيير.

استخدم Ansible لإدارة الإعدادات عندما:

  • تدير VMs طويلة العمر (خوادم قواعد البيانات، العقد القديمة، الخوادم المادية).
  • وقت التشغيل مهم وبناء AMI جديدة لكل تغيير بطيء جدًا.
  • لا يمكن استبدال النظام دون ترحيل بيانات (الخدمات ذات الحالة).

فضّل الصور الثابتة (Packer + Ansible، Docker، AMI-based ASG) عندما:

  • تشغّل طبقات تطبيق بلا حالة — خوادم ويب، عقد API، workers.
  • تريد سلوكًا متطابقًا في بيئة التطوير والاختبار والإنتاج (الصورة هي القطعة الفنية).
  • نموذج تهديدك يتطلب خوادم إنتاج بلا وصول SSH كليًا.
  • تستخدم بالفعل Kubernetes أو ECS — الحاويات هي الوحدة الثابتة؛ إعداد المضيف ضئيل.
أفضل الممارسات هو النهج الهجين: استخدم Packer + Ansible لبناء AMIs ذهبية. يهيّئ Ansible تصلب نظام التشغيل الأساسي والعوامل المشتركة (CloudWatch، SSM) والاعتمادات مرة واحدة أثناء بناء الصورة. الأسطول المشغّل لا يتلقى أي pushes من Ansible — يُستبدل. يواصل Ansible إدارة الخوادم الطويلة العمر ذات الحالة التي لا يمكنها اتباع النمط الثابت.
لا تشغّل ansible-playbook دون بوابة إدارة تغيير في الإنتاج. يمكن لـ playbook غير مختبر أن يُطلق على آلاف الخوادم في ثوانٍ. اختبر دومًا على مجموعة inventory للاختبار أولًا، استخدم --check (تشغيل جاف) و--diff لمعاينة التغييرات، وقيّد صلاحيات إطلاق job templates الإنتاجية لكبار المهندسين أو اشترط موافقة ثانية في AWX.

تحليل الأداء

عندما يكون playbook كبير بطيئًا، قِسه قبل الضبط العشوائي. إضافتا profile_tasks وprofile_roles callback تُشحن مع Ansible ولا تُضيف أي تكلفة في التشغيل العادي.

# ansible.cfg — تفعيل callbacks التوقيت [defaults] callbacks_enabled = profile_tasks, profile_roles, timer # بعد التشغيل ستظهر مخرجات مثل: # ============================================================ # gather_facts ----------------------------------- 48.23s # apt: install packages -------------------------- 32.11s # template: nginx.conf --------------------------- 4.87s # ============================================================ # Total time: 85.21s # مكاسب سريعة بمجرد معرفة المهام البطيئة: # 1. تخزين الحقائق مؤقتًا (fact_caching = redis) # 2. استخدام async + poll للمهام طويلة التشغيل # 3. رفع قيمة forks # 4. استخدام Mitogen strategy plugin (تسريع 3-7x، يستبدل SSH بـ Python RPC) # pip install mitogen ansible-mitogen # ansible.cfg: # [defaults] # strategy_plugins = /path/to/ansible_mitogen/plugins/strategy # strategy = mitogen_linear

على نطاق التقنية الكبيرة، يُعتمد إضافة Mitogen على نطاق واسع لتحسينها الجذري في السرعة. تستبدل SSH ثم Shell ثم تشغيل Python bootstrap بقناة Python مستمرة داخل العملية، مما يخفض تكلفة كل مهمة لكل خادم من ~200 ملّيثانية إلى ~5 ملّيثانية. المقايضة هي اعتمادية إضافية وتعارضات عرضية مع وحدات المجتمع التي تستخدم Python غير اعتيادية — دائمًا اختبر في بيئة الاختبار أولًا.