Ansible --check ও --diff dry run কী সত্যিই দেখায়
Ansible-এর --check ও --diff কী প্রমাণ করে দেখুন: কোন module check mode সমর্থন না করায় dry run ভুল ফল দেয়, এবং বাস্তব প্রয়োগে কী বদলাতে পারে।
Ansible check mode কী করে
Ansible check mode হলো একটি dry run: ansible-playbook --check play-এর প্রতিটি host-এ সংযোগ করে, প্রতিটি module-কে জিজ্ঞেস করে বর্তমান state আপনার নির্ধারিত state-এর সঙ্গে মিলে কি না, এবং কোনো কিছু write না করেই কী পরিবর্তন হতে পারে তা জানায়। --diff যোগ করলে যে file-গুলোতে পরিবর্তন করা হতো, সেগুলোর আগের ও পরের content-ও দেখায়। এই দুটির সাহায্যে প্রতিটি বাস্তব run-এর আগে গুরুত্বপূর্ণ প্রশ্নটির উত্তর পাওয়া যায়: এই server-গুলোতে এখন কী পরিবর্তন হতে যাচ্ছে?
Check mode আপনার playbook-এর simulation নয়। কোথাও server-এর কোনো model তৈরি হয় না। প্রতিটি module-কে শুধু write করার পরিবর্তে দেখার নির্দেশ দেওয়া হয়। যে module read-only অবস্থায় উত্তর দিতে পারে, সেটি changed জানিয়ে পরবর্তী কাজে যায়। যে module উত্তর দিতে পারে না, সেটি কিছু করে না এবং কিছু জানায়ও না। Ansible documentation-এ বিষয়টি এক লাইনে বলা হয়েছে: "যে module check mode সমর্থন করে না, সেটি কিছু জানায় না এবং কিছু করে না।" এই সীমাবদ্ধতার কারণেই dry run ভুল উত্তর দিতে পারে; তাই এই guide-এর অধিকাংশ অংশ এই সীমাবদ্ধতা নিয়ে।
Dry run চালান: --check এবং --diff
ansible-playbook -i inventory.ini site.yml --check --diff --limit web1-C এবং -D দুটি flag-এর সংক্ষিপ্ত রূপ। --limit ইচ্ছাকৃত। একটি host-এর diff পড়া যায়। 20টি host-এর diff সাধারণত স্ক্রল করে পার হয়ে যেতে হয়।
চারটি result word পুরো report-এর অর্থ প্রকাশ করে।
ok: [web1]অর্থ module পরীক্ষা করে দেখেছে এবং বর্তমান state ইতিমধ্যে মিলে গেছে। কোনো পরিবর্তন হবে না।changed: [web1]অর্থ module কোনো কিছু লিখত।--diffথাকলে, তার উপরের line-গুলোতে কী পরিবর্তন হতো তা দেখা যায়।skipping: [web1]অর্থ task মূল্যায়ন করা হয়নি। হয়whenfalse ছিল, অথবা module check mode-এ চলতে পারে না।fatal: [web1]অর্থ check করার সময় task ব্যর্থ হয়েছে। Playbook নষ্ট হয়েছে ধরে নেওয়ার আগে message পড়ুন।
File module-এর ক্ষেত্রে --diff unified diff দেখায়। বাদ দেওয়া line-এ - এবং যোগ করা line-এ + চিহ্ন থাকে। Header-এর line --- before এবং +++ after দিয়ে শুরু হয় এবং destination path-এর নাম দেখায়। যে module file লেখে না, সেটি নিজের before ও after অবস্থা দেখায়। তাই ansible.builtin.user file content নয়, যে attribute-গুলো পরিবর্তন করা হতো সেগুলো দেখায়।
ansible.cfg-এ diff স্থায়ীভাবে চালু করুন, যাতে flag-টি ভুলে না যান:
[diff]
always = true
context = 5Check mode-এর আগে দুটি কম খরচের check চালানো উচিত। ansible-playbook site.yml --syntax-check কোনো host-এর সঙ্গে যোগাযোগ না করেই YAML এবং play structure parse করে। ansible-playbook site.yml --list-tasks যে task-গুলো চলত সেগুলো দেখায়। এভাবেই বোঝা যায়, আপনি যে role-টিকে tag করা আছে ভেবেছিলেন সেটি আসলে tag করা নেই। কোনোটিই connection তৈরি করে না, তাই দুটিই তাৎক্ষণিকভাবে শেষ হয়।
Check mode নিজে connection তৈরি করে। এটি pattern-এর প্রতিটি host-এ SSH খোলে এবং facts সংগ্রহ করে। তাই কোনো host down থাকলে dry run ব্যর্থ হয়। এটি নিজেই একটি কার্যকর signal। Dry run-কে CI-তে যুক্ত করার আগে unreachable host সম্পর্কে playbook-এর করণীয় নির্ধারণ করা গুরুত্বপূর্ণ হওয়ার এটিও একটি কারণ।
নতুন সার্ভারে check mode কেন ব্যর্থ হয়
এই play সঠিক। --check ব্যবহার করে এমন একটি সার্ভারে এটি চালান, যেখানে এখনো nginx নেই। দেখবেন, এর বেশির ভাগ অংশ ব্যর্থ হচ্ছে।
- name: Install nginx
ansible.builtin.apt:
name: nginx
state: present
- name: Write the site config
ansible.builtin.template:
src: site.conf.j2
dest: /etc/nginx/conf.d/site.conf
- name: Start and enable nginx
ansible.builtin.service:
name: nginx
state: started
enabled: trueapt task-এ changed দেখায়, এবং এটি সঠিক: package-টি অনুপস্থিত, তাই বাস্তব run-এ এটি install হবে। Check mode এটি install করেনি। এরপর template task ব্যর্থ হয়, কারণ এই host-এ /etc/nginx/conf.d/ নেই এবং এটি তৈরি করার মতো কিছুই চালানো হয়নি। service task-ও ব্যর্থ হয়, কারণ query করার জন্য কোনো nginx unit নেই। এই দুই ব্যর্থতার কোনোটিই playbook-এর bug নয়। Dry run-এর জন্য প্রয়োজনীয় state তৈরি হয়নি। আগের কোনো task-এর পরিবর্তনের ওপর input নির্ভর করলে check mode সেই task-এর জন্য কার্যকর output দিতে পারে না—documentation-এর সতর্কবার্তার অর্থ এটাই।
তাই নিয়মটির সঠিক ব্যাখ্যা হলো: playbook যে host-এ ইতিমধ্যে প্রয়োজনীয় state তৈরি করেছে, সেই host-এর ক্ষেত্রে check mode নির্ভুল। নতুন host-এর ক্ষেত্রে এটি অনেক অপ্রয়োজনীয় error দেখাতে পারে। একটি --check run-এ প্রতিটি task ok জানালে, converged host সম্পর্কে এটি বাস্তব তথ্য। এর অর্থ কোনো পরিবর্তন করা হবে না। একেবারে নতুন host-এ --check বেশির ভাগ সময় শুধু জানায় যে host-টি নতুন। VPS-এর জন্য আপনার প্রথম Ansible playbook লিখলে প্রথম dry run-এ অনেক error দেখাবে—এটাই স্বাভাবিক। Playbook বিচার করুন দ্বিতীয় dry run-এর ফল দেখে।
চেক মোডে command এবং shell task কেন এড়িয়ে যাওয়া হয়
ansible.builtin.command এবং ansible.builtin.shell আপনার command কী করে তা জানে না। যেকোনো নির্বিচারে binary চালানোর read-only পদ্ধতি নেই। তাই check mode-এ module এটি চালাতে অস্বীকৃতি জানায়। task result-এ skipped: true থাকে এবং Command would have run if not in check mode message দেখা যায়। আপনার output-এ skipping: [web1] প্রদর্শিত হয়।
module documentation-এ check mode support-কে "partial" বলা হয়েছে। সেখানে workaround হিসেবে creates এবং removes উল্লেখ করা হয়েছে। task-এ একটি creates path দিলে check mode অন্তত file test মূল্যায়ন করতে পারে:
- name: Extract the release bundle
ansible.builtin.command: /usr/bin/tar xf /tmp/app.tar.gz -C /opt/app
args:
creates: /opt/app/bin/app/opt/app/bin/app ইতিমধ্যে থাকলে check mode Would not run command since '/opt/app/bin/app' exists জানায়। এটি একটি প্রকৃত ফলাফল। path না থাকলে Command would have run if not in check mode পাওয়া যায়। এটিও একটি প্রকৃত ফলাফল। creates ছাড়া dry run-এ task-টি কোনো ফলাফল দেয় না।
এর পরবর্তী প্রভাব এই শূন্য ফলাফলের চেয়েও গুরুতর। এড়িয়ে যাওয়া task-ও একটি result নিবন্ধন করে। তবে সেটি skip result এবং এতে stdout key থাকে না। পরের task-এর condition মূল্যায়নের সময় ব্যর্থ হয়। তখন 'dict object' has no attribute 'stdout'-এর কাছাকাছি একটি error দেখা যায়। বাস্তব run-এ playbook কাজ করে, কিন্তু dry run-এ ব্যর্থ হয়। এই feature-এর সবচেয়ে বিভ্রান্তিকর ব্যর্থতা এটিই।
check_mode: false, এটি কোথায় ব্যবহার করা উচিত
কোনো task-এ check_mode: false থাকলে সেটি --check-এর অধীনেও বাস্তবে চালানো হয়। skipped-command সমস্যার সমাধান হিসেবে এটি ব্যবহার করা যায়। তবে এটি শুধু এমন task-এ নিরাপদ, যা কেবল পড়ে।
- name: Read the installed app version
ansible.builtin.command: /usr/local/bin/app --version
register: app_version
check_mode: false
changed_when: falseউভয় mode-এই task-টি নির্ভরযোগ্যভাবে কাজ করে। এটি একটি version পড়ে এবং কখনো কিছু লেখে না। changed_when: false task-টিকে এমন পরিবর্তন দেখানো থেকে বিরত রাখে, যা এটি করেনি। check_mode: false dry run-এর সময় app_version.stdout-কে বিদ্যমান রাখে, ফলে এর ওপর নির্ভর করা শর্তগুলোও evaluate হয়।
অন্য কোথাও paste করার আগে keyword-টির অর্থ আক্ষরিকভাবে বুঝে নিন। check_mode: false-সহ কোনো task ansible-playbook --check চলাকালে আপনার server-এ লিখবে। কোনো apt task বা template task-এ এটি ব্যবহার করলে dry run দেখতে পরিষ্কার মনে হতে পারে, কিন্তু তখন সেটি আর dry run থাকে না। কোনো লেখার task-কে নিরাপদ করা না গেলে সেটিকে guard করুন:
- name: Apply the database migration
ansible.builtin.command: /usr/local/bin/app migrate --apply
when: not ansible_check_modeansible_check_mode একটি magic variable, যা Ansible check run চলাকালে true সেট করে। এর বিপরীত keyword-ও আছে। check_mode: true task-কে সব সময় check mode-এ চালায়, এমনকি real run-এর সময়ও। এতে task-টি drift probe হিসেবে কাজ করে। ফলাফল register করুন। changed report-এর অর্থ হলো host-টি task-এ নির্ধারিত অবস্থার সঙ্গে আর মেলে না।
প্রতিটি run-এ কোনো task changed রিপোর্ট করার কারণ
মাঝখানে কিছু না রেখে playbook-টি পরপর দুবার চালান। দ্বিতীয় run-এ প্রতিটি task-এর ok রিপোর্ট করা উচিত। কোনো task এখনও changed রিপোর্ট করলে, তার দুটি কারণের একটি রয়েছে: module যে state পরিচালনা করে তা দেখতে পারছে না, অথবা আপনি যে input দিচ্ছেন তা স্থিতিশীল নয়। দুটিই ঠিক করা যায়। এগুলোকে নীরব করার মতো অপ্রয়োজনীয় noise ভাববেন না।
commandএবংshell-এ কোনোcreates,removesবাchanged_whenনা থাকলে প্রতিবারইchangedরিপোর্ট হবে, কারণ কিছু ঘটেছে কি না তা জানার কোনো উপায় module-এর নেই।createsযোগ করুন, অথবা output-এর কোনো string-এর বিপরীতেchanged_whenসেট করুন।ansible.builtin.file-এর সঙ্গেstate: touchব্যবহার করলে নকশা অনুযায়ী প্রতিবারchangedরিপোর্ট হবে, কারণ কোনো file-এ touch করলে তার timestamp আপডেট হয়। আপনার উদ্দেশ্য শুধু owner বা mode নির্ধারণ করা হলেstate: fileব্যবহার করুন।- কোনো
template-এর rendered output পরিবর্তিত হলে প্রতিবার file-টি নতুন করে লেখা হয়।ansible_date_timeথেকে পাওয়া timestamp,now()-এ করা একটি call বা প্রতিবার নতুন করে তৈরি করা password—সবই আলাদা byte তৈরি করে। তাই module সঠিকভাবেই change রিপোর্ট করে। পরিবর্তনশীল value-টি template-এর বাইরে রাখুন। ansible.builtin.user-এpassword: "{{ pw | password_hash('sha512') }}"ব্যবহার করলে প্রতিবার পরিবর্তন হয়, কারণpassword_hashপ্রতিবার call করার সময় একটি random salt বেছে নেয়। ফলে তৈরি হওয়া hash কখনও/etc/shadow-এ থাকা hash-এর সঙ্গে মেলে না। স্থিতিশীল কোনো value থেকে তৈরি করা explicit salt দিন।- কোনো package module-এ
state: latestব্যবহার করলে upgrade উপলভ্য থাকলেইchangedরিপোর্ট হয়। এটি সঠিক রিপোর্ট। এ কারণেইstate: latestএমন playbook তৈরি করে যার ফলাফল আগে থেকে নির্ধারণ করা যায় না।state: presentব্যবহার করুন এবং ইচ্ছাকৃতভাবে upgrade করুন। - কোনো URL-এ নির্দেশ করা
ansible.builtin.unarchive-এcreatesনা থাকলে সেটি আবার download ও extract করে। একটিcreatespath দিন।
--diff ব্যবহার করাই এই কারণগুলো দ্রুত আলাদা করার উপায়। কোনো task changed বলছে এবং diff-এ ভিন্ন byte দেখা যাচ্ছে, তাহলে আপনার input স্থিতিশীল নয়। যদি এটি changed বলে কিন্তু diff-এ কিছুই না দেখা যায়, তাহলে module তার করা পরিবর্তন প্রকাশ করতে পারছে না। সাধারণত এর অর্থ একটি command task বা timestamp-এর মতো metadata-only write।
কোনো noisy task নীরব করতে changed_when: false ব্যবহার করবেন না। এটি report চাপা দেয়। ফলে notify কখনও চালু হয় না এবং service restart করা handler-ও চলবে না। পরিবর্তে task-টি ঠিক করুন।
পরিবর্তনের প্রভাব সীমিত রাখুন: --limit, --tags এবং --step
Check mode কী পরিবর্তন হতে পারে তা দেখায়। এই flag-গুলো একসঙ্গে কতগুলো মেশিনে পরিবর্তন প্রয়োগ হবে, তা নির্ধারণ করে।
--limit inventory-এর একটি subset-এ play-এর পরিধি সীমিত করে। এটি hosts:-এর মতো একই pattern গ্রহণ করে, তাই --limit web1 এবং --limit 'webservers:!web3' দুটিই কাজ করে। Pattern-টি quote করুন। Interactive bash session-এ quote না করা ! exclamation mark-এ history expansion চালু করে, ফলে Ansible কমান্ডটি দেখার আগেই shell সেটি পরিবর্তন করে ফেলে।
Pattern-টির ওপর নির্ভর করার আগে এটি যাচাই করুন। ansible-playbook site.yml --limit 'webservers:!web3' --list-hosts মিলে যাওয়া host-গুলো দেখায় এবং কোনো host-এ সংযোগ না করেই শেষ হয়। কোনো pattern-এর সঙ্গে কিছু না মিললেও এটি নিরাপদ, কারণ Ansible পুরো inventory-তে fallback করে না। এটি একটি warning দেখায় যে host pattern-এর সঙ্গে কোনো host মেলেনি, তারপর hosts এবং --limit কোনো host-এর সঙ্গে মেলে না—এমন error দেখিয়ে শেষ হয়। inventory file-এ ওই group-গুলো কীভাবে সংজ্ঞায়িত করা আছে তা জানা থাকলেই pattern-এর আচরণ শুরু থেকেই নির্ভরযোগ্যভাবে অনুমান করা যায়।
--tags deploy শুধু tag করা task চালায়, আর --skip-tags packages বাকি সব task চালায়। --list-tags উপলভ্য tag-গুলো দেখায়। একটি play এত বড় হয়ে গেলে যে পুরো play চালাতে আর ইচ্ছুক নন, তখন tag ব্যবহার করা কার্যকর হয়। এই কারণেই দীর্ঘ playbook-কে role-এ ভাগ করা উপকারী।
--start-at-task "Write the site config" নির্দিষ্ট নামের task থেকে ব্যর্থ run পুনরায় শুরু করে। এটি recovery-এর জন্য ব্যবহার করুন, তবে এর সীমাবদ্ধতা বুঝে নিন: ওই task-এর আগের সব task এড়িয়ে যাওয়া হয়। এর মধ্যে এমন task-ও থাকে যেগুলো facts সেট করে বা পরবর্তী task-গুলো যে variable পড়ে, সেগুলো register করে।
--step প্রতিটি task-এর আগে prompt দেখায় এবং আপনার yes, no বা continue উত্তর দেওয়ার জন্য অপেক্ষা করে। এটি ধীর, তবে ধ্বংসাত্মক কোনো কাজ প্রথমবার চালানোর সময় এটিই সঠিক tool। কারণ বিশটি task শেষ হওয়ার পরে নয়, দুটি task-এর মাঝেই আপনি কাজ থামাতে পারবেন।
ক্রমিকভাবে পরিবর্তন চালু করুন
ডিফল্টভাবে Ansible পরবর্তী task শুরু করার আগে play-এর প্রতিটি host-এ একটি task চালায়। এটি দ্রুত, তবে এর অর্থ হলো কোনো ভুল task একই সেকেন্ডে পুরো fleet-এ পৌঁছে যায়। আপনি error পড়ে Ctrl-C চাপার আগেই পরিবর্তনটি সর্বত্র প্রয়োগ হয়ে যায়।
serial play-কে batch-এ ভাগ করে। পুরো play প্রথম batch-এর বিরুদ্ধে চলে, তারপর পরবর্তী batch-এর বিরুদ্ধে চলে।
- name: Roll out the web tier
hosts: webservers
serial: [1, 5, "30%"]
max_fail_percentage: 0
tasks:
- name: Deploy the release
ansible.builtin.include_role:
name: webappপ্রথম batch-এ একটি host থাকে। সেটি সফল হলে দ্বিতীয় batch-এ পাঁচটি host থাকে, এবং এরপরের প্রতিটি batch-এ play-এর host-গুলোর 30 percent থাকে। max_fail_percentage: 0 কোনো batch-এর যেকোনো host ব্যর্থ হলেই play শেষ করে, ফলে ত্রুটিপূর্ণ release একটি machine-এই থেমে যায়। any_errors_fatal: true হলো আরও সরাসরি সংস্করণ; প্রথম host ব্যর্থ হলেই এটি সবার জন্য play শেষ করে।
প্রথমে একটি host-এর বিরুদ্ধে চালানো অযৌক্তিক সতর্কতা নয়। এর নির্দিষ্ট কারণ আছে। Inventory group-গুলোর মধ্যে সময়ের সঙ্গে পার্থক্য তৈরি হয়। অন্যদের ছয় মাস পরে যোগ করা কোনো server-এ ভিন্ন distribution release থাকতে পারে, কেউ হাতে করে ইনস্টল করা কোনো service থাকতে পারে, অথবা তার disk layout ভিন্ন হতে পারে। Playbook-টি group-এর জন্য সঠিক হলেও ওই একটি host-এর জন্য ভুল হতে পারে। একই configuration-এ থাকা কোনো host-এর বিরুদ্ধে dry run চালালে এই সমস্যা ধরা পড়বে না। Linux server fleet পরিচালনা মূলত পরিবর্তনটি প্রয়োগ করার আগেই ব্যতিক্রমী host শনাক্ত করার কাজ।
যেভাবে ধাপগুলো চালাবেন
ansible-playbook site.yml --syntax-checkকোনো network ছাড়াই YAML এবং structure-এর ভুল শনাক্ত করে।ansible-playbook site.yml --limit web1 --list-hostsনিশ্চিত করে যে আপনার pattern প্রত্যাশামতোই match করছে।ansible-playbook site.yml --limit web1 --check --diffdry run চালায়। diff পড়ুন।ansible-playbook site.yml --limit web1 --diffএটি ওই একটি host-এ প্রয়োগ করে।- ধাপ 4 আবার চালান। সবকিছুর ফলাফল
okহওয়া উচিত। কোনো কিছু এখনওchangedথাকলে, বাকি fleet-এ প্রয়োগের আগে সেটি ঠিক করতে হবে। - এখন পুরো inventory-তে
ansible-playbook site.yml --check --diffচালালে অর্থবহ ফলাফল পাওয়া যাবে, কারণ সঠিক অবস্থায় আনা host-গুলো নীরব থাকবে এবং অবশিষ্ট ফলাফলই প্রকৃত delta দেখাবে।
ধাপ 3 সম্পর্কে একটি সতর্কতা আছে। --diff file-এর content আপনার terminal এবং CI job log-এ output করে। তাই কোনো template-এ database password থাকলে সেই password-ও log-এ চলে যাবে। Output বন্ধ করতে ওই task-এ diff: false সেট করুন, অথবা পুরো result আড়াল করতে no_log: true ব্যবহার করুন। প্রকৃত value repository-তে না রেখে একটি encrypted Ansible Vault file-এ রাখুন।
FAQ
ansible-playbook --check কি সার্ভারে কোনো পরিবর্তন করে?
না, তবে একটি ব্যতিক্রম আছে এবং সেটি আপনি নিয়ন্ত্রণ করেন। check mode-এ প্রতিটি module-কে পরিবর্তন না করে অবস্থা জানাতে বলা হয়। যে module তা করতে পারে না, সেটি কিছু জানায় না এবং কোনো কাজও করে না। ব্যতিক্রমটি হলো check_mode: false task keyword। এটি --check run চলাকালীনও ওই নির্দিষ্ট task বাস্তবে চালায়। dry run-এর ওপর নির্ভর করার আগে আপনার playbook ও role-এ check_mode: false খুঁজুন। প্রতিটি মিল শুধু state পড়ে—এমন task কি না নিশ্চিত করুন।
--check এবং --diff-এর মধ্যে পার্থক্য কী?
--check নির্ধারণ করে কোনো কাজ বাস্তবে চলবে কি না। --diff নির্ধারণ করে আপনি কতটা বিস্তারিত দেখতে পাবেন। একা --check ব্যবহার করলে শুধু জানা যায় যে একটি file পরিবর্তিত হবে। একা --diff ব্যবহার করলে পরিবর্তনটি প্রয়োগ হয় এবং কোন line পরিবর্তিত হয়েছে তা দেখায়। পড়া যায় এমন dry run-এর জন্য দুটিই একসঙ্গে ব্যবহার করুন। বাস্তব run-এর সময়ও --diff চালু রাখুন। এর জন্য [diff]-এর অধীনে ansible.cfg-এ always = true সেট করুন।
আমার Ansible task কেন প্রতিটি run-এ changed দেখায়?
কারণ module যে state পরিচালনা করে তা দেখতে পারছে না, অথবা আপনি যে value দিচ্ছেন তা প্রতিবার আলাদা। command এবং shell সব সময় changed report করে, যদি না আপনি creates বা changed_when যোগ করেন। file-এর সঙ্গে state: touch ব্যবহার করলে ইচ্ছাকৃতভাবেই পরিবর্তন হয়। Timestamp বা নতুন করে তৈরি করা password render করা template প্রতিবার আলাদা byte তৈরি করে। তাই file-টি সত্যিই প্রতিবার rewrite হয়। Playbook পরপর দুবার চালান। দ্বিতীয় pass-এও যা changed থাকে, সেটিই সংশোধন করার task।
dry run-এর সময় আমার command এবং shell task কেন বাদ পড়ে?
কারণ নির্বিচারে চালানো কোনো command-এর read-only পদ্ধতি নেই। check mode-এ command module skipped: true সেট করে এবং Command would have run if not in check mode message দেখায়। পরিবর্তে file test মূল্যায়ন করার জন্য creates বা removes যোগ করুন। যে task শুধু state পড়ে, সেখানে check_mode: false এবং changed_when: false একসঙ্গে সেট করুন। এতে dry run-এর সময়ও registered result থাকে এবং তার ওপর নির্ভরশীল condition-গুলো কাজ করতে পারে।
নতুন server-এ check mode ব্যর্থ হয়, কিন্তু বিদ্যমান server-এ সফল হয় কেন?
কারণ পরবর্তী task যে state-এর ওপর নির্ভর করে, check mode সেই state তৈরি করে না। nginx ছাড়া কোনো host-এ dry run চালালে installation-টি changed হিসেবে report হয়। এরপর /etc/nginx/conf.d/-এ লেখার task ব্যর্থ হয়, কারণ ওই directory কখনো তৈরি করা হয়নি। এটি প্রত্যাশিত আচরণ। Check mode হলো এমন host-এর drift detector, যেগুলোতে playbook আগে থেকেই সম্পূর্ণভাবে প্রয়োগ হয়েছে। এটি প্রথম run যাচাই করতে পারে না। নতুন host-এ একটি machine-এ playbook প্রয়োগ করুন এবং দ্বিতীয় run-এর ফলাফল পরীক্ষা করুন।