آموزش کار با check mode و --diff در Ansible
در این راهنما بررسی میکنیم که چگونه با استفاده از --check و --diff تغییرات را قبل از اجرا شبیهسازی کنید. همچنین محدودیتهای ماژولها در گزارشدهی را بررسی میکنیم.
عملکرد حالت check mode در Ansible
حالت check mode در Ansible یک اجرای آزمایشی (dry run) است: ansible-playbook --check به تمام میزبانهای موجود در play متصل میشود، از هر ماژول میپرسد که آیا وضعیت فعلی با وضعیت مورد نظر شما مطابقت دارد یا خیر، و بدون نوشتن هیچ تغییری، گزارش میدهد که چه چیزی تغییر خواهد کرد. با افزودن --diff، این ابزار محتوای فایلهایی که قرار است تغییر کنند را نیز قبل و بعد از اعمال تغییرات نمایش میدهد. این دو در کنار هم به پرسشی پاسخ میدهند که پیش از هر اجرای واقعی باید مطرح شود: چه چیزی قرار است روی این سرورها تغییر کند؟
حالت check mode شبیهسازی playbook شما نیست. هیچ مدلی از سرور در هیچجایی وجود ندارد. از هر ماژول صرفاً خواسته میشود که به جای نوشتن، فقط وضعیت را بررسی کند. ماژولی که بتواند به صورت فقطخواندنی پاسخ دهد، changed را گزارش کرده و به کار خود ادامه میدهد. ماژولی که نتواند پاسخ دهد، هیچ کاری انجام نمیدهد و چیزی گزارش نمیکند. مستندات Ansible این موضوع را در یک جمله خلاصه کرده است: «ماژولهایی که از حالت check mode پشتیبانی نمیکنند، هیچ چیزی گزارش نمیدهند و هیچ کاری انجام نمیدهند.» این شکاف همان جایی است که اجرای آزمایشی ممکن است پاسخ اشتباهی به شما بدهد، بنابراین بخش عمدهای از این راهنما به بررسی همین شکاف اختصاص دارد.
اجرای تست آزمایشی: --check و --diff
ansible-playbook -i inventory.ini site.yml --check --diff --limit web1-C و -D صورتهای کوتاه این دو فلگ هستند. استفاده از --limit آگاهانه است. تفاوت (diff) یک میزبان چیزی است که میتوانید آن را بخوانید. تفاوت بیست میزبان چیزی است که فقط از روی آن رد میشوید.
چهار کلمه نتیجه، کل گزارش را تشکیل میدهند.
ok: [web1]یعنی ماژول وضعیت را بررسی کرده و وضعیت فعلی با وضعیت مطلوب مطابقت دارد. هیچ تغییری اعمال نخواهد شد.changed: [web1]یعنی ماژول چیزی را تغییر میداد. با استفاده از--diff، خطوط بالای آن نشان میدهند که چه تغییری رخ میداد.skipping: [web1]یعنی تسک ارزیابی نشده است. یا یکwhenنادرست بوده، یا ماژول قابلیت اجرا در حالت check mode را ندارد.fatal: [web1]یعنی تسک در حین بررسی با خطا مواجه شده است. پیش از آنکه فرض کنید پلیبوک خراب است، پیام خطا را بخوانید.
--diff یک unified diff برای ماژولهای فایل چاپ میکند، که در آن خطوط حذفشده با - و خطوط اضافه شده با + مشخص میشوند؛ این خروجی زیر سرتیتری قرار میگیرد که خطوط آن با --- before و +++ after شروع شده و مسیر مقصد را نام میبرند. ماژولهایی که فایل نمینویسند، وضعیت قبل و بعد خود را چاپ میکنند، بنابراین ansible.builtin.user به جای محتوای فایل، ویژگیهایی را که تغییر میداد نشان میدهد.
برای اینکه هرگز استفاده از این فلگ را فراموش نکنید، diff را بهطور دائمی در ansible.cfg فعال کنید:
[diff]
always = true
context = 5دو بررسی کمهزینهتر وجود دارند که باید پیش از check mode انجام شوند. ansible-playbook site.yml --syntax-check فایل YAML و ساختار پلیبوک را بدون تماس با هیچ میزبانی پارس میکند. ansible-playbook site.yml --list-tasks تسکهایی را که قرار است اجرا شوند چاپ میکند؛ این همان روشی است که متوجه میشوید نقشی (role) که فکر میکردید دارای تگ است، در واقع نیست. هیچکدام از این دو دستور به میزبان متصل نمیشوند، بنابراین هر دو آنی هستند.
خودِ check mode به میزبان متصل میشود. این حالت یک اتصال SSH به تمام میزبانهای موجود در الگو برقرار کرده و فکتها را جمعآوری میکند، بنابراین میزبانی که در دسترس نباشد باعث شکست تست آزمایشی میشود. این خود یک سیگنال مفید است و به همین دلیل است که تصمیمگیری درباره نحوه برخورد پلیبوک با میزبانهای غیرقابلدسترس پیش از قرار دادن تست آزمایشی در CI اهمیت دارد.
چرا حالت check در یک سرور تازه نصبشده با شکست مواجه میشود
این پلیبوک صحیح است. اگر آن را با --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: trueتسک apt وضعیت changed را گزارش میدهد و این درست است: بسته مورد نظر وجود ندارد، بنابراین اجرای واقعی آن را نصب خواهد کرد. حالت check آن را نصب نکرده است. سپس تسک template شکست میخورد، زیرا /etc/nginx/conf.d/ روی این میزبان وجود ندارد و هیچ چیزی آن را ایجاد نکرده است. تسک service نیز شکست میخورد، زیرا واحد nginx برای پرسوجو وجود ندارد. هیچکدام از این خطاها باگ پلیبوک نیستند. اجرای آزمایشی (dry run) به دلیل نبود وضعیت مورد نیاز متوقف شد؛ این همان چیزی است که مستندات هنگام هشدار درباره عدم تولید خروجی مفید در حالت check برای تسکهایی که ورودی آنها به تغییرات تسک قبلی وابسته است، بیان میکنند.
بنابراین نسخه صادقانه این قانون چنین است: حالت check در برابر میزبانی که پلیبوک قبلاً روی آن همگرا (converged) شده دقیق است، و در برابر یک میزبان تازه، پر از خطا (noisy) است. اجرای --check که در آن همه تسکها ok را گزارش میدهند، یک اظهارنظر واقعی درباره یک میزبان همگرا است، زیرا به این معنی است که هیچ تغییری رخ نخواهد داد. روی یک میزبان کاملاً جدید، --check عمدتاً به شما میگوید که میزبان جدید است. هنگامی که در حال نوشتن اولین پلیبوک Ansible خود برای یک VPS هستید، انتظار داشته باشید که اولین اجرای آزمایشی با انبوهی از خطاها (رنگ قرمز) مواجه شود و پلیبوک را بر اساس اجرای دوم قضاوت کنید.
چرا وظایف مربوط به command و shell در حالت check mode نادیده گرفته میشوند
ansible.builtin.command و ansible.builtin.shell نمیدانند که دستور شما چه کاری انجام میدهد. هیچ روشی برای اجرای یک فایل باینری دلخواه به صورت read-only وجود ندارد، بنابراین در حالت check mode، ماژول از اجرای آن خودداری میکند. نتیجهٔ وظیفه شامل skipped: true و پیام Command would have run if not in check mode است و خروجی شما skipping: [web1] را نشان میدهد.
مستندات ماژول، پشتیبانی آن از حالت check mode را «جزئی» مینامد و راهکار پیشنهادی آن creates و removes است. اگر یک مسیر creates به وظیفه بدهید، حالت check mode حداقل میتواند تست فایل را ارزیابی کند:
- 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 را گزارش میدهد که یک پاسخ واقعی است. اگر مسیر وجود نداشته باشد، شما Command would have run if not in check mode را دریافت میکنید که آن هم یک پاسخ واقعی است. بدون creates، آن وظیفه در اجرای آزمایشی (dry run) شما یک فضای خالی باقی میماند.
اثر جانبی این موضوع بدتر از یک فضای خالی است. وظیفهای که نادیده گرفته شده (skipped) همچنان یک نتیجه ثبت میکند، اما آن نتیجه یک نتیجهٔ skip است و فاقد کلید stdout میباشد. در نتیجه، شرط وظیفهٔ بعدی هنگام ارزیابی با خطا مواجه میشود؛ خطایی که به 'dict object' has no attribute 'stdout' شباهت دارد. پلیبوک شما در اجرای واقعی کار میکند اما در اجرای آزمایشی دچار شکست میشود، که گیجکنندهترین نوع خطا در کل این قابلیت است.
check_mode: false و تنها جایی که به آن تعلق دارد
check_mode: false روی یک task به این معناست که «این دستور را واقعاً اجرا کن، حتی در حالت --check». این راهکار مشکل دستورات نادیده گرفته شده (skipped) است و تنها برای taskهایی که عملیات خواندن انجام میدهند، ایمن است.
- name: Read the installed app version
ansible.builtin.command: /usr/local/bin/app --version
register: app_version
check_mode: false
changed_when: falseآن task در هر دو حالت صادق است. این task یک نسخه را میخواند و هرگز چیزی نمینویسد؛ changed_when: false مانع از گزارش تغییراتی میشود که انجام نشدهاند و check_mode: false باعث میشود app_version.stdout در طول یک اجرای آزمایشی (dry run) وجود داشته باشد تا شرایطی که بر اساس آن بنا شدهاند، همچنان ارزیابی شوند.
پیش از آنکه این کلمه کلیدی را در جای دیگری کپی کنید، معنای آن را به دقت درک کنید. یک task با check_mode: false در طول ansible-playbook --check روی سرورهای شما تغییراتی اعمال میکند. اگر آن را روی یک task از نوع apt یا template قرار دهید، اجرای آزمایشی شما مرتبتر به نظر میرسد، اما دیگر یک اجرای آزمایشی واقعی نخواهد بود. زمانی که نمیتوان یک task نوشتاری را ایمن کرد، به جای آن از یک محافظ استفاده کنید:
- name: Apply the database migration
ansible.builtin.command: /usr/local/bin/app migrate --apply
when: not ansible_check_modeansible_check_mode یک متغیر جادویی است که Ansible در طول اجرای آزمایشی آن را روی true تنظیم میکند. کلمه کلیدی معکوس آن نیز وجود دارد. check_mode: true یک task را همیشه در حالت check mode قفل میکند، حتی در طول یک اجرای واقعی؛ این کار آن را به یک ابزار تشخیص انحراف (drift probe) تبدیل میکند: نتیجه را ثبت کنید، و یک گزارش changed به این معناست که وضعیت میزبان دیگر با آنچه task درخواست میکند، مطابقت ندارد.
چرا یک تسک در هر اجرا وضعیت changed را گزارش میدهد
پلیبوک را دو بار پشت سر هم و بدون هیچ تغییری در محیط اجرا کنید. در اجرای دوم، هر تسک باید وضعیت ok را گزارش دهد. هر تسکی که همچنان changed را گزارش میکند، یکی از دو مورد زیر را نشان میدهد: یا ماژول نمیتواند وضعیت فعلی منبعی که مدیریت میکند را تشخیص دهد، یا ورودیهایی که به آن میدهید پایدار نیستند. هر دو مورد قابلرفع هستند و هیچکدام نویز محسوب نمیشوند که نیاز به نادیده گرفتن داشته باشند.
- دستورات
commandوshellبدون استفاده ازcreates،removesیاchanged_when، هر بار وضعیتchangedرا گزارش میدهند، زیرا ماژول راهی برای تشخیص اینکه آیا تغییری رخ داده است یا خیر ندارد. ازcreatesاستفاده کنید یاchanged_whenرا بر اساس یک رشته (string) در خروجی تنظیم کنید. - ماژول
ansible.builtin.fileهمراه باstate: touch، طبق طراحی در هر اجرا وضعیتchangedرا گزارش میدهد، زیرا لمس کردن (touch) یک فایل، مُهر زمانی (timestamp) آن را بهروز میکند. اگر تنها قصد شما تنظیم مالک (owner) یا دسترسیها (mode) است، ازstate: fileاستفاده کنید. - یک
templateکه خروجی رندر شدهاش تغییر میکند، فایل را در هر اجرا بازنویسی میکند. یک مُهر زمانی ازansible_date_time، فراخوانیnow()، یا رمز عبوری که هر بار بهصورت تازه تولید میشود، همگی بایتهای متفاوتی ایجاد میکنند؛ بنابراین ماژول بهدرستی تغییر را گزارش میدهد. مقدار متغیر را از قالب (template) حذف کنید. - ماژول
ansible.builtin.userباpassword: "{{ pw | password_hash('sha512') }}"در هر اجرا تغییر میکند، زیراpassword_hashهر بار که فراخوانی میشود یک salt تصادفی انتخاب میکند؛ بنابراین هش حاصل هرگز با هش موجود در/etc/shadowمطابقت ندارد. یک salt صریح که از یک منبع پایدار مشتق شده است را ارسال کنید. state: latestدر یک ماژول پکیج، هر زمان که ارتقایی در دسترس باشد، وضعیتchangedرا گزارش میدهد. این گزارش صادقانه است. به همین دلیل است کهstate: latestپلیبوکی به شما میدهد که نتیجهاش قابل پیشبینی نیست. ازstate: presentاستفاده کنید و ارتقا را بهصورت آگاهانه انجام دهید.ansible.builtin.unarchiveکه به یک URL بدونcreatesاشاره دارد، هر بار فایل را مجدداً دانلود و استخراج میکند. یک مسیرcreatesبه آن بدهید.
استفاده از --diff سریعترین راه برای تشخیص این موارد است. اگر تسکی وضعیت changed را نشان میدهد و diff بایتهای متفاوتی را نمایش میدهد، ورودی شما ناپایدار است. اگر وضعیت changed را نشان میدهد و diff هیچ چیزی را نمایش نمیدهد، ماژول نمیتواند تغییرات خود را بیان کند که معمولاً به معنای یک تسک command یا نوشتنِ صرفِ متادیتا مانند مُهر زمانی است.
برای ساکت کردن یک تسک پرصدا، به سراغ changed_when: false نروید. این کار گزارش را سرکوب میکند، بنابراین notify هرگز فعال نمیشود و هندلری که سرویس را ریاستارت میکند، اجرا نخواهد شد. بهجای این کار، تسک را اصلاح کنید.
کاهش دامنهٔ آسیب: --limit، --tags و --step
حالت Check mode به شما میگوید چه تغییراتی اعمال خواهد شد. این فلگها تعیین میکنند که همزمان چند ماشین تحت تأثیر قرار بگیرند.
فلگ --limit اجرا را به زیرمجموعهای از inventory محدود میکند. این فلگ همان الگوهایی را میپذیرد که hosts: میپذیرد، بنابراین هر دو دستور --limit web1 و --limit 'webservers:!web3' کار میکنند. الگو را داخل کوتیشن قرار دهید. یک ! بدون کوتیشن در یک نشست تعاملی bash باعث فعالشدن history expansion روی علامت تعجب میشود و shell شما پیش از آنکه Ansible دستور را ببیند، آن را بازنویسی میکند.
پیش از اعتماد به الگو، آن را تأیید کنید. دستور ansible-playbook site.yml --limit 'webservers:!web3' --list-hosts میزبانهای منطبق را چاپ کرده و بدون اتصال به هیچکدام از آنها خارج میشود. الگویی که با هیچچیز منطبق نباشد ایمن است، زیرا Ansible به کل inventory بازنمیگردد. این ابزار هشداری مبنی بر عدم انطباق با الگوی میزبان چاپ کرده و سپس با خطایی مبنی بر اینکه میزبانها و --limit با هیچ میزبانی منطبق نیستند، خارج میشود. دانستن نحوه تعریف آن گروهها در فایل inventory همان چیزی است که باعث میشود یک الگو از ابتدا قابل پیشبینی باشد.
فلگ --tags deploy فقط تسکهای دارای تگ مشخص را اجرا میکند و --skip-tags packages همه چیزهای دیگر را اجرا میکند. دستور --list-tags تگهای موجود را چاپ میکند. تگها زمانی مفید واقع میشوند که یک play از حدی بزرگتر شود که بخواهید کل آن را اجرا کنید؛ این موضوع همچنین یکی از دلایل تقسیم یک playbook طولانی به roleها است.
فلگ --start-at-task "Write the site config" اجرای ناموفق را از یک تسک مشخص از سر میگیرد. از آن برای بازیابی استفاده کنید و هزینه آن را درک کنید: همه چیز پیش از آن تسک نادیده گرفته میشود، از جمله تسکهایی که فکتها را تنظیم میکنند یا متغیرهایی را ثبت میکنند که تسکهای بعدی به آنها نیاز دارند.
فلگ --step پیش از هر تسک از شما پرسش میکند و منتظر میماند تا پاسخ yes، no یا continue بدهید. این کار کند است، اما برای اولین باری که یک عملیات مخرب را اجرا میکنید ابزار مناسبی است، زیرا میتوانید به جای توقف پس از بیست تسک، بین دو تسک متوقف شوید.
اعمال تغییرات با استفاده از serial
بهصورت پیشفرض، Ansible پیش از شروع تسک بعدی، هر تسک را روی تمام میزبانهای موجود در play اجرا میکند. این روش سریع است، اما باعث میشود یک تسک معیوب در همان ثانیه به کل ناوگان سرایت کند. تا زمانی که شما خطا را بخوانید و Ctrl-C را فشار دهید، تغییرات در همه جا اعمال شده است.
serial اجرای play را به دستههای کوچکتر تقسیم میکند. کل play ابتدا روی دسته اول اجرا میشود و سپس به سراغ دسته بعدی میرود.
- 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دسته اول شامل یک میزبان است. اگر آن میزبان با موفقیت عملیات را پشت سر بگذارد، دسته دوم شامل 5 میزبان خواهد بود و تمام دستههای بعدی شامل 30 درصد از کل میزبانهای play خواهند بود. max_fail_percentage: 0 بهمحض شکست خوردن هر میزبان در یک دسته، اجرای play را متوقف میکند؛ بنابراین یک release معیوب تنها روی یک ماشین متوقف میشود. any_errors_fatal: true نسخه سختگیرانهتری است که با اولین شکست در هر میزبانی، اجرای play را برای همه متوقف میکند.
اجرا روی یک میزبان در ابتدا، پارانویا نیست و دلیل مشخصی دارد. گروههای موجود در inventory دچار تغییرات تدریجی (drift) میشوند. سروری که 6 ماه پس از بقیه اضافه شده است، ممکن است نسخه توزیع متفاوتی داشته باشد، سرویسی داشته باشد که شخصی بهصورت دستی نصب کرده است، یا چیدمان دیسکهایش متفاوت باشد. playbook ممکن است برای کل گروه درست باشد اما برای آن یک میزبان خاص اشتباه باشد، و هیچ اجرای آزمایشی (dry run) روی یک میزبان همگامسازیشده، این موضوع را نشان نخواهد داد. مدیریت ناوگانی از سرورهای Linux تا حد زیادی تمرین یافتن آن میزبان متفاوت پیش از اعمال تغییرات است.
ترتیب اجرای عملیات
- دستور
ansible-playbook site.yml --syntax-checkخطاهای ساختاری و YAML را بدون نیاز به شبکه شناسایی میکند. - دستور
ansible-playbook site.yml --limit web1 --list-hostsتأیید میکند که الگوی شما دقیقاً با آنچه مد نظر دارید مطابقت دارد. - دستور
ansible-playbook site.yml --limit web1 --check --diffاجرای آزمایشی (dry run) است. خروجی diff را بررسی کنید. - دستور
ansible-playbook site.yml --limit web1 --diffتغییرات را روی همان یک میزبان اعمال میکند. - مرحله 4 را دوباره اجرا کنید. همه چیز باید وضعیت
okرا گزارش دهد. هر موردی که همچنانchangedباشد، وظیفهای است که باید پیش از اعمال تغییرات روی کل ناوگان، اصلاح شود. - دستور
ansible-playbook site.yml --check --diffاکنون در کل inventory پاسخ معناداری ارائه میدهد، زیرا میزبانهای همگراشده (converged) ساکت هستند و آنچه باقی میماند، دلتای واقعی است.
یک هشدار درباره مرحله 3: دستور --diff محتوای فایلها را در ترمینال و لاگ CI شما چاپ میکند؛ بنابراین قالبی که رمز عبور دیتابیس را رندر میکند، آن رمز را در لاگ نیز نمایش میدهد. برای جلوگیری از این خروجی، گزینه diff: false را روی آن task تنظیم کنید یا از no_log: true برای مخفیسازی کامل نتیجه استفاده نمایید. همچنین مقدار اصلی را به جای مخزن کد، در یک فایل رمزنگاریشده Ansible Vault نگهداری کنید.
FAQ
آیا دستور ansible-playbook --check تغییری در سرور ایجاد میکند؟
خیر، با یک استثنا که کنترل آن در دست شماست. در حالت check mode، از هر ماژول خواسته میشود بهجای نوشتن، فقط گزارش دهد؛ ماژولهایی که قادر به انجام این کار نیستند، هیچ گزارش یا تغییری ایجاد نمیکنند. استثنا، کلمه کلیدی check_mode: false در تسک است که باعث میشود آن تسک خاص حتی در حین اجرای --check بهصورت واقعی اجرا شود. پیش از اعتماد به یک اجرای آزمایشی (dry run)، پلیبوکها و نقشهای خود را برای یافتن check_mode: false جستجو کنید و مطمئن شوید هر مورد یافتشده، تسکی است که فقط وضعیت را میخواند.
تفاوت بین --check و --diff چیست؟
--check تعیین میکند که آیا چیزی بهصورت واقعی اجرا میشود یا خیر. --diff تعیین میکند که چه میزان جزئیات را مشاهده کنید. استفاده از --check بهتنهایی به شما میگوید که یک فایل تغییر خواهد کرد. استفاده از --diff بهتنهایی تغییر را اعمال کرده و خطوط تغییریافته را به شما نشان میدهد. برای یک اجرای آزمایشی که واقعاً قابل خواندن باشد، این دو را با هم استفاده کنید و برای اجراهای واقعی نیز با تنظیم always = true در بخش [diff] در فایل ansible.cfg، گزینه --diff را فعال نگه دارید.
چرا تسک Ansible من در هر اجرا وضعیت changed را گزارش میدهد؟
زیرا ماژول نمیتواند وضعیتی که مدیریت میکند را تشخیص دهد، یا مقداری که به آن میدهید هر بار متفاوت است. command و shell همیشه وضعیت changed را گزارش میدهند، مگر اینکه creates یا changed_when را اضافه کنید. file به همراه state: touch ذاتاً تغییر ایجاد میکند. قالبی (template) که یک timestamp یا یک رمز عبور تازه تولیدشده را رندر میکند، در هر اجرا بایتهای متفاوتی تولید میکند، بنابراین فایل واقعاً بازنویسی میشود. پلیبوک را دو بار پشت سر هم اجرا کنید: هر تسکی که در اجرای دوم همچنان changed گزارش میشود، همان تسکی است که نیاز به اصلاح دارد.
چرا تسکهای command و shell من در طول اجرای آزمایشی (dry run) نادیده گرفته میشوند؟
زیرا هیچ روش فقطخواندنی (read-only) برای اجرای یک دستور دلخواه وجود ندارد. در حالت check mode، ماژول command وضعیت skipped: true را با پیام Command would have run if not in check mode تنظیم میکند. از creates یا removes استفاده کنید تا حالت check mode بتواند تست فایل را ارزیابی کند. برای تسکی که فقط وضعیت را میخواند، check_mode: false را به همراه changed_when: false تنظیم کنید تا نتیجه ثبتشده (registered result) در طول اجرای آزمایشی همچنان موجود باشد و شرطهای مبتنی بر آن به کار خود ادامه دهند.
چرا حالت check mode روی سرور جدید با خطا مواجه میشود اما روی سرور موجود موفق است؟
زیرا حالت check mode وضعیتی که تسکهای بعدی به آن وابستهاند را ایجاد نمیکند. اجرای آزمایشی روی میزبانی که nginx ندارد، نصب را changed گزارش میدهد و سپس در تسکی که در /etc/nginx/conf.d/ مینویسد با خطا مواجه میشود، زیرا آن دایرکتوری هرگز ایجاد نشده است. این رفتار مورد انتظار است. حالت check mode ابزاری برای تشخیص انحراف (drift) در میزبانهایی است که پلیبوک قبلاً روی آنها همگرا (converge) شده است. این حالت نمیتواند اولین اجرا را اعتبارسنجی کند. روی یک میزبان جدید، پلیبوک را روی یک ماشین اعمال کنید و نتیجه را در اجرای دوم بررسی کنید.