Ansible Check Mode: اكشف Drift السيرفر قبل التنفيذ
مستوى القارئ: متوسط
هتكسب مراجعة واضحة لتغييرات السيرفر قبل ما تلمس الإنتاج، بدل ما تعرف الخطأ بعد ما NGINX يرفض يعمل reload.
المشكلة باختصار
الطريقة الشائعة بتفشل لما تعدل ملف config يدويًا على VM، ثم تعدل نفس الملف بعد أسبوع من Ansible. اللي بيحصل فعلاً إن السيرفر يبقى فيه drift: الواقع على الماكينة مش مطابق للكود الموجود في Git.
افترض إن عندك 12 VM لتطبيق Node.js وملفات NGINX وsystemd. تغيير صغير في gzip أو proxy timeout ممكن يعدي على 11 سيرفر ويفشل على واحد. لو بتعمل apply مباشر، أنت بتكتشف المشكلة بعد التنفيذ. أفضل طريقة هنا هي تشغيل dry run منظم قبل التغيير.
الفكرة بمثال بسيط
ركز في المثال ده. عندك ملف NGINX template في Git، وعلى السيرفر حد غيّر قيمة client_max_body_size يدويًا من 20m إلى 100m عشان يمرر upload كبير. بعد شهر، playbook قديم هيرجعها إلى 20m بدون ما حد ينتبه.
--check بيقول لك: “كنت هغير الملف ده”. و--diff بيوريك قبل وبعد. بالظبط زي مراجعة pull request، لكن للواقع الموجود على السيرفر. علميًا، check mode في Ansible يحاول محاكاة التغيير بدون تطبيقه، والـ diff mode يعرض الفروق في الملفات أو القيم لما الـ module يدعم ذلك.
إعداد عملي قابل للنسخ
ابدأ بمخزون بسيط. المثال مبني على VM واحدة أولًا، لأن Ansible نفسه ينصح باستخدام diff بحذر مع host محدود بسبب كثرة المخرجات واحتمال ظهور بيانات حساسة.
# inventory.ini
[web]
web-01 ansible_host=203.0.113.10 ansible_user=ubuntu
بعدها اعمل playbook صغير يدير NGINX ويمنع عرض diff للملفات الحساسة. هنا هنراجع config عام فقط.
# nginx.yml
- name: Manage nginx config safely
hosts: web
become: true
tasks:
- name: Install nginx
ansible.builtin.apt:
name: nginx
state: present
update_cache: true
- name: Render site config
ansible.builtin.template:
src: templates/app.conf.j2
dest: /etc/nginx/sites-available/app.conf
owner: root
group: root
mode: '0644'
notify: reload nginx
- name: Enable site
ansible.builtin.file:
src: /etc/nginx/sites-available/app.conf
dest: /etc/nginx/sites-enabled/app.conf
state: link
handlers:
- name: reload nginx
ansible.builtin.service:
name: nginx
state: reloaded
شغّل المراجعة قبل التنفيذ الفعلي:
ansible-playbook -i inventory.ini nginx.yml --check --diff --limit web-01
لو النتيجة مثلًا changed=3 failed=0، يبقى عندك 3 تغييرات متوقعة. في فريق صغير، الرقم العملي المقبول قبل أول rollout ممكن يكون من 1 إلى 5 تغييرات مفهومة. لو طلع changed=24 على VM واحدة، وقف. ده غالبًا drift كبير أو playbook أوسع من اللازم.
ازاي تستخدمه في CI بدون كسر الإنتاج
بدل ما تخلي أول تشغيل على الإنتاج هو التنفيذ، خليه مراجعة. في GitHub Actions أو GitLab CI، شغّل check على host واحدة أو staging inventory. لو خرج failed، امنع merge. لو خرج changed عالي جدًا، اطلب review يدوي.
# .github/workflows/ansible-check.yml
name: ansible-check
on:
pull_request:
paths:
- 'ansible/**'
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Ansible
run: python -m pip install ansible-core
- name: Dry run one host
working-directory: ansible
run: |
ansible-playbook -i inventory.ini nginx.yml \
--check --diff --limit web-01
الـ trade-off هنا واضح. بتكسب تقليل مفاجآت الإنتاج ومراجعة قبل التنفيذ. بتخسر 5 إلى 15 دقيقة في كل PR، وممكن تحتاج masking للمخرجات لو عندك templates فيها secrets. لو عندك 50 VM، لا تبدأ بهم كلهم. ابدأ بـ --limit على host واحدة، ثم وسّع الدائرة.
أرقام واقعية قبل وبعد
في setup صغير من 12 VM، تطبيق check mode قبل apply ممكن يقلل حوادث config الشهرية من 7 إلى 2 تقريبًا، لو كان سبب الحوادث الأساسي هو التعديل اليدوي وغياب المراجعة. الرقم تقديري، لكنه مفيد كهدف قياس: عدّ عدد rollbacks أو reload failures قبل وبعد 4 أسابيع.
قياسك الأساسي مش “Ansible اشتغل ولا لأ”. القياس المفيد هو: كم تغيير ظهر في --check --diff، وكم تغيير منهم كان غير متوقع. لو كل PR بيطلع 10 تغييرات غير مفهومة، عندك مشكلة ownership للكود أو drift متراكم على السيرفرات.
متى لا تستخدم هذه الطريقة
لا تعتمد على check mode وحده لو الـ playbook فيه أوامر shell مع side effects، أو tasks تعتمد على registered variables من خطوات سابقة قد لا تعمل في المحاكاة. بعض modules لا تدعم check mode بالكامل، وساعتها ممكن لا تعرض التغيير المتوقع. كذلك لا تشغّل --diff على templates تحتوي passwords أو tokens إلا لو استخدمت diff: false أو أخفيت المخرجات من CI.
لو بتدير Kubernetes manifests عبر GitOps، غالبًا أدوات مثل Argo CD diff أو Helm diff أنسب. Ansible check mode أقوى لما تدير VM، packages، services، وملفات config مباشرة.
مصادر
- Ansible: Validating tasks with check mode and diff mode
- Ansible: INI inventory plugin
- Ansible: YAML inventory plugin
الخطوة التالية
افتح آخر playbook عندك وشغّله على host واحدة فقط بالأمر: ansible-playbook -i inventory.ini site.yml --check --diff --limit اسم_السيرفر. لو ظهر أكثر من 5 تغييرات غير متوقعة، لا تعمل apply. ابدأ بتنظيف drift الأول.