Ansible playbook বনাম role: কোনটি কখন ব্যবহার করবেন
Ansible playbook কখন যথেষ্ট এবং কখন role ব্যবহার করবেন তা জানুন। role layout, ansible-galaxy init, role call ও variable precedence-এর বাস্তব নির্দেশিকা এখানে।
Ansible playbook বনাম role: পার্থক্য কী
Ansible playbook হলো সেই ফাইল, যা আপনি ansible-playbook দিয়ে চালান। এটি একদল host-কে তাদের জন্য নির্ধারিত কাজের সঙ্গে যুক্ত করে। Ansible role হলো নির্দিষ্ট কাঠামোর একটি directory, যেখানে tasks, templates, handlers এবং default variables থাকে; playbook নাম ধরে এটিকে কল করে। উভয়ের ভিতরের task syntax একই। তাই কোনটি দিয়ে কী প্রকাশ করা যায়, এটি সেই প্রশ্ন নয়। আসল বিষয় হলো পুনঃব্যবহার।
একটি সরল playbook দিয়ে শুরু করুন। একটি site.yml-এ একটি tasks: list রাখা আপনার প্রথম automation-এর জন্য উপযুক্ত কাঠামো। অধিকাংশ মানুষ যতটা ভাবেন, তার চেয়ে অনেক বেশি সময় এটি উপযুক্ত থাকে। একই tasks-এর block দ্বিতীয় কোনো host group-এ চালাতে হলে role-এ রূপান্তর করুন। অথবা file প্রায় 100 lines ছাড়িয়ে গেলে role ব্যবহার করুন, যখন scroll করে কোনো task খুঁজে পাওয়া কঠিন হয়ে যায়।
আপনি এখনো কোনো playbook না লিখে থাকলে, একটি single VPS-এর জন্য প্রথম playbook দিয়ে শুরু করুন। এটি বড় হতে শুরু করলে এখানে ফিরে আসুন।
যখন একটি flat playbook-ই সঠিক সমাধান
কাজটি একবারই হলে, একটি host-এ চললে, অথবা অন্য কেউ playbook-টি পড়বে না হলে flat playbook ব্যবহার করাই সঠিক। একটি application server provision করা বা maintenance window-এর আগে একটি box patch করা—কোনোটির জন্যই directory tree তৈরি করার প্রয়োজন নেই। একটি role সাতটি directory এবং একটি অতিরিক্ত indirection layer যোগ করে। একমাত্র caller যদি তার পাশের playbook-টি হয়, তাহলে এই indirection কোনো সুবিধা দেয় না; বরং কী চলবে তা পড়তে গেলেই আপনাকে অতিরিক্ত একটি ধাপ পেরোতে হয়।
একটি নির্দিষ্ট সময়ে flat playbook আর সঠিক পছন্দ থাকে না, এবং সেই সময়টি সহজেই বোঝা যায়। আপনি যখন একটি tasks block দ্বিতীয় playbook-এ copy করেন, তখনই সংকেতটি স্পষ্ট। এরপর থেকে প্রতিটি fix দুই জায়গায় করতে হবে, এবং একদিন তা শুধু এক জায়গাতেই করা হবে।
একটি role directory-তে আসলে কী থাকে
roles/common/
defaults/main.yml
vars/main.yml
tasks/main.yml
handlers/main.yml
templates/99-hardening.conf.j2
files/
meta/main.ymltasks/main.ymlহলো entry point। role call করা হলে Ansible এই file চালায়, এবং অন্য সব directory optional।defaults/main.yml-এ caller যে variables override করবে বলে প্রত্যাশা করা হয়, সেগুলো থাকে। Ansible-এ এটি সর্বনিম্ন priority-এর source, তাই প্রায় অন্য যেকোনো source এর চেয়ে এগিয়ে থাকে।vars/main.yml-এ এমন variables থাকে, যেগুলো caller override করবে বলে প্রত্যাশা করা হয় না। priority-তে এটি inventory-এর ওপরে থাকে, যা একটি গুরুত্বপূর্ণ অঙ্গীকার। এটি খুব কম ব্যবহার করুন।handlers/main.yml-এnotifyদ্বারা trigger হওয়া tasks থাকে। একটি handler play-এর শেষে একবার চলে, যত task-ই তাকে notify করুক না কেন।files/-এcopymodule verbatim কপি করে এমন files থাকে, আরtemplates/-এtemplatemodule render করে এমন Jinja2 templates থাকে। role-এর ভিতরে উভয়কেই path ছাড়া bare filename দিয়ে reference করবেন, কারণ Ansible প্রথমে role-এর নিজস্ব directory-গুলোতে খোঁজে।meta/main.ymlrole dependencies এবং Ansible Galaxy যে metadata পড়ে, সেগুলো declare করে।
এই layout কোনো style preference নয়। Ansible নির্দিষ্ট এই path-গুলোতেই খোঁজে। তাই roles/common/template/-এ রাখা একটি template (singular) কখনোই পাওয়া যাবে না।
ansible-galaxy init দিয়ে common role তৈরি করুন
mkdir -p ~/infra/roles
cd ~/infra
ansible-galaxy init --init-path roles commonএটি roles/common-এর অধীনে পুরো skeleton তৈরি করে। এর মধ্যে এমন directory-ও থাকে যেগুলো আপনি ব্যবহার করবেন না। main.yml-এর কিছু stub-এ শুধু --- থাকে। যেগুলো খালি রাখবেন, সেগুলো মুছে দিন। খালি vars/main.yml Ansible-এর জন্য ক্ষতিকর নয়, তবে role-এ আসলে কোন file গুরুত্বপূর্ণ তা বোঝা কঠিন করে।
এখন কাজ সম্পাদনকারী file-গুলো পূরণ করুন। প্রথমে defaults দিন, কারণ এগুলো role-এর public interface।
# roles/common/defaults/main.yml
---
common_packages:
- ufw
- fail2ban
- unattended-upgrades
common_admin_group: admins
common_permit_root_login: "no"
common_password_authentication: "no""no" এবং "yes" quote করুন। Ansible PyYAML দিয়ে YAML parse করে। PyYAML কোনো bare no-কে boolean false হিসেবে পড়ে। ফলে rendered config line PermitRootLogin False হয়ে যায় এবং sshd সেটি প্রত্যাখ্যান করে। Quote ব্যবহার করলে value-টি string হিসেবে থাকে।
# roles/common/tasks/main.yml
---
- name: Install the base packages
ansible.builtin.apt:
name: "{{ common_packages }}"
state: present
update_cache: true
cache_valid_time: 3600
- name: Create the admin group
ansible.builtin.group:
name: "{{ common_admin_group }}"
state: present
- name: Install the sshd hardening drop-in
ansible.builtin.template:
src: 99-hardening.conf.j2
dest: /etc/ssh/sshd_config.d/99-hardening.conf
owner: root
group: root
mode: "0644"
validate: /usr/sbin/sshd -t -f %s
notify: Restart sshd# roles/common/handlers/main.yml
---
- name: Restart sshd
ansible.builtin.service:
name: ssh
state: restarted# roles/common/templates/99-hardening.conf.j2
# Managed by Ansible. Local edits are overwritten on the next run.
PermitRootLogin {{ common_permit_root_login }}
PasswordAuthentication {{ common_password_authentication }}Debian এবং Ubuntu-তে systemd unit-এর নাম ssh। RHEL family system-এ নাম sshd। কোনো কিছু template পরিবর্তন করলেই শুধু handler কার্যকর হয়। তাই ভুল unit-এর নাম দেওয়া handler-এর সমস্যা সাধারণত কয়েক সপ্তাহ পরে প্রকাশ পায়।
এই task-এর সবচেয়ে গুরুত্বপূর্ণ অংশ হলো validate line। Ansible template-টি একটি temporary file-এ render করে। এরপর %s-এর জায়গায় ওই file-এর path বসিয়ে command চালায়। Command 0 exit code দিলে তবেই destination প্রতিস্থাপিত হয়। Template-এ একটি ভুল directive রেখে আবার চালান। Task failed to validate-সহ ব্যর্থ হবে, প্রকৃত /etc/ssh/sshd_config.d/99-hardening.conf অপরিবর্তিত থাকবে, এবং আপনি এখনও server-এ login করতে পারবেন। মনে রাখবেন, এই check শুধু syntax পরীক্ষা করে না। sshd -t host keys পড়তে না পারলে sshd: no hostkeys available -- exiting. exit code দেয়। তখন Ansible একই failed to validate জানায়। তাই template-কে দোষারোপ করার আগে module-এর msg পড়ুন।
একটি playbook কীভাবে role কল করে
# site.yml
---
- name: Base configuration for every server
hosts: all
become: true
roles:
- common# inventory.ini
[local]
localhost ansible_connection=localansible-playbook -i inventory.ini site.ymlRecap-এ play-এর শেষে failed=0 থাকা উচিত। Call site-এ expanded form ব্যবহার করে parameter পাঠান। এভাবেই একটি role দুইটি host group-এ ব্যবহার করা যায়:
roles:
- role: common
common_admin_group: ops
common_permit_root_login: prohibit-passwordএখানে একটি ordering rule আছে, যা প্রায় সবাইকে অবাক করে। একটি play-তে pre_tasks, roles, tasks এবং post_tasks থাকতে পারে। ফাইলে এগুলো যে ক্রমেই লিখুন না কেন, Ansible সব সময় ওই ক্রমেই চালায়। tasks:-কে roles:-এর উপরে রাখলেও role আগে চলবে। তাই কোনো কাজ role-এর আগে করাতে হলে সেটি pre_tasks:-এ রাখতে হবে, tasks:-এর শুরুতে নয়।
- name: Ordering demonstration
hosts: local
gather_facts: false
pre_tasks:
- name: Runs first
ansible.builtin.debug:
msg: pre
roles:
- common
tasks:
- name: Runs after the role
ansible.builtin.debug:
msg: task
post_tasks:
- name: Runs last
ansible.builtin.debug:
msg: postroles: key-এর পরিবর্তে task list-এর ভেতর থেকে role কল করতে import_role অথবা include_role ব্যবহার করুন।
tasks:
- name: Static, read when the playbook is parsed
ansible.builtin.import_role:
name: common
- name: Dynamic, resolved when the task runs
ansible.builtin.include_role:
name: postgres
when: "'db' in group_names"import_role static। Ansible parse time-এ role পড়ে এবং তার task-গুলো play-এর অংশ হয়ে যায়। তাই ansible-playbook --list-tasks site.yml সেগুলো তালিকাভুক্ত করে এবং import-এর একটি tag ভেতরের প্রতিটি task-এ প্রযোজ্য হয়। include_role dynamic। Task চালু না হওয়া পর্যন্ত কিছু পড়া হয় না। এর ফলে variable বা loop থেকে role name নির্ধারণ করা যায়। এর অসুবিধা হলো, ওই task-গুলো --list-tasks এবং --start-at-task-এ দেখা যায় না।
এখানে একটি সাধারণ ভুলের সুযোগ আছে। include_role task-এ থাকা when: মূল্যায়ন করা হয় included role-এর defaults/main.yml scope-এ আসার আগে। Include-এর ওপর when: common_packages | length > 0 লিখলে run 'common_packages' is undefined দিয়ে থেমে যায়, যদিও ওই variable যে role include করছেন তার মধ্যেই সংজ্ঞায়িত। সমাধান হলো toggle-টি role-এর বাইরে সরিয়ে নেওয়া। এটি group_vars/all.yml-এ রাখুন, যাতে সব জায়গা থেকে scope-এ থাকে। Role-এর defaults-এ শুধু role নিজে ব্যবহার করে এমন value রাখুন।
কোন variable কার্যকর হয়: defaults, group_vars, vars, extra vars
Ansible variable precedence-এর 20টির বেশি স্তর নথিবদ্ধ করে। বাস্তবের প্রায় সব বিরোধ চারটি স্তরেই মেটে। দুর্বল থেকে শক্তিশালী ক্রমে সেগুলো হলো।
roles/<name>/defaults/main.ymlনিচের দিকের একটি স্তর। অন্য যেকোনো জায়গায় সেট করা প্রায় সবকিছুই এটিকে অতিক্রম করে। তাই role-এর পরিবর্তনযোগ্য parameter রাখার জন্য এটি উপযুক্ত।group_vars/এবংhost_vars/মাঝামাঝি স্তরে থাকে। আপনার site-এর নিজস্ব মান এখানে রাখুন। এগুলো role default-কে পরিষ্কারভাবে override করে।roles/<name>/vars/main.yml,host_vars-এর উপরে থাকে। এখানে সেট করা কোনো মান inventory থেকে override করা যায় না। Role-এর অভ্যন্তরীণ সামঞ্জস্য বজায় রাখতে যেসব মান অপরিবর্তিত থাকা দরকার, সেগুলোর জন্য এটি রাখুন। যেমন, service name-এর সঙ্গে মিল থাকা package name।- Call site-এ পাঠানো role parameter
vars/main.yml-কে অতিক্রম করে। Command line-এ দেওয়া-erole parameter-সহ নিচের সবকিছুকে অতিক্রম করে।
প্রায় এক মিনিটে এই precedence কীভাবে নির্ধারিত হয় তা দেখা যায়। একটি ছোট role-এ একটি default এবং একটি role var দিন। তারপর host_vars-এ একই নামগুলো সেট করুন।
# roles/prec/defaults/main.yml
---
prec_tunable: from-defaults
prec_internal: from-defaults# roles/prec/vars/main.yml
---
prec_internal: from-rolevars# host_vars/localhost.yml
---
prec_tunable: from-hostvars
prec_internal: from-hostvars# roles/prec/tasks/main.yml
---
- name: Show which value survived
ansible.builtin.debug:
msg: "tunable={{ prec_tunable }} internal={{ prec_internal }}"ansible-playbook -i inventory.ini prec.yml
ansible-playbook -i inventory.ini prec.yml -e prec_internal=from-cliপ্রথম run-এ tunable=from-hostvars internal=from-rolevars প্রদর্শিত হয়। Inventory role default-কে অতিক্রম করে, কিন্তু role var-এর কাছে হেরে যায়। দ্বিতীয় run-এ internal=from-cli প্রদর্শিত হয়, কারণ extra vars সর্বোচ্চ স্তরে থাকে এবং নিচের কোনো স্তরই সেগুলোকে override করতে পারে না। এই কারণেই একবারের run-এর জন্য -e ব্যবহার করা ঠিক আছে, কিন্তু দীর্ঘমেয়াদে রাখা script-এ এটি ব্যবহার করা ভুল। এটি repository-র বিবেচিত প্রতিটি সিদ্ধান্তকে নীরবে অতিক্রম করে।
কার্যকর নিয়ম হলো: কোনো মান পরিবর্তনযোগ্য রাখতে চাইলে সেটি defaults/-এ রাখুন। vars/-এ রাখলে role-এর ভবিষ্যৎ প্রতিটি ব্যবহারকারীকে জানানো হয় যে inventory এই মান পরিবর্তন করতে পারবে না। কখনও এটি আপনার উদ্দেশ্য হতে পারে। বেশিরভাগ সময় এটি অনিচ্ছাকৃত ভুল।
রোলটি idempotent প্রমাণ করুন: এটি দুইবার চালান
বিশ্বস্ত Ansible run দ্বিতীয়বার একই ফল দেয় এবং কোনো পরিবর্তন হয়নি বলে জানায়। Playbook দুইবার চালান এবং recap দেখুন।
ansible-playbook -i inventory.ini site.yml
ansible-playbook -i inventory.ini site.ymlদ্বিতীয় recap এমন হওয়া উচিত:
PLAY RECAP *********************************************************************
localhost : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0changed=0 মানে প্রতিটি module বর্তমান অবস্থা পরীক্ষা করে দেখেছে যে কাজটি আগেই সম্পন্ন হয়েছে। দ্বিতীয় run-এ changed=2 মানে দুটি task পার্থক্য শনাক্ত করতে পারছে না। তাই সেগুলো বারবার file rewrite করবে এবং service restart করবে। সাধারণত এর কারণ command বা shell, কারণ কোনো নির্বিচার command কী করেছে তা Ansible জানার উপায় নেই।
# traps.yml
---
- name: Command modules do not know what they changed
hosts: local
gather_facts: false
tasks:
- name: This appends a line on every run
ansible.builtin.shell: "echo run >> /tmp/grow.txt"
- name: This appends a line only once
ansible.builtin.shell: "echo run >> /tmp/guarded.txt"
args:
creates: /tmp/guarded.txtPlaybook-টি দুইবার চালান। এরপর wc -l /tmp/grow.txt /tmp/guarded.txt থাকা line গুনুন। /tmp/grow.txt-এ দুটি line এবং /tmp/guarded.txt-এ একটি line থাকার কথা। দ্বিতীয় run-এ guarded task একেবারেই চালানো হয়নি। তার result-এ skipped, since /tmp/guarded.txt exists message রয়েছে, কারণ creates module-কে আগে খোঁজার মতো দৃশ্যমান ফলাফল দেয়। কোনো command এমন ফলাফল না রাখলে তার output changed_when দিয়ে register করুন এবং নিজেই সিদ্ধান্ত নিন।
ansible-playbook --check --diff site.yml কোনো পরিবর্তন না করে সম্ভাব্য পরিবর্তন দেখায়। --diff template যে নির্দিষ্ট line-গুলো rewrite করত, সেগুলো দেখায়। একটি বিষয় মনে রেখে output পড়ুন: check mode-এ shell এবং command task skip হয়। তাই পরিষ্কার দেখানো plan-এর মধ্যেও কাজ বাকি থাকতে পারে।
Recap-এর আরও একটি column একইভাবে সতর্কতার সঙ্গে দেখুন: যে host-এ Ansible connect করতে পারেনি, সেটি failed-এর বদলে unreachable-এর অধীনে গণনা হয়। ওই host-এর কোনো task-ই চালানো হয় না। তাই এই role কয়েকটির বেশি machine-এ প্রয়োগ করার আগে একটি unreachable host পুরো run থামাবে কি না আগে সিদ্ধান্ত নিন।
Ansible কেন বলে যে role পাওয়া যায়নি
Ansible প্রথমে playbook ফাইলের পাশে থাকা roles/ directory-তে, তারপর roles_path-এ role খোঁজে। এই অনুসন্ধান আপনার shell নয়, playbook অনুসরণ করে।
ERROR! the role 'common' was not found in /home/deploy/lonely/roles:/home/deploy/lonelyএই বার্তার অর্থ হলো site.yml এবং roles/-এর মধ্যে সামঞ্জস্য নেই। Ansible যে path-গুলো পরীক্ষা করেছে, সেগুলোও বার্তায় দেখায়। দুটি একই directory-তে রাখুন। Parent directory থেকে চালানো সমস্যা নয়, কারণ playbook-এর path-ই বিবেচ্য:
ansible-playbook -i infra/inventory.ini infra/site.ymlএকই সমস্যার আরেকটি কম দৃশ্যমান রূপ আছে। বর্তমান directory world writable হলে Ansible সেখানে থাকা ansible.cfg উপেক্ষা করে। কারণ সিস্টেমের যেকোনো user সেখানে configuration রেখে আপনার run-এর আচরণ পরিবর্তন করতে পারে।
[WARNING]: Ansible is being run in a world writable directory (/tmp/infra), ignoring it as an ansible.cfg source.ফলে আপনার roles_path এবং inventory setting নীরবে অনুপস্থিত থাকে, এবং role lookup ব্যর্থ হয় এমন একটি কারণে যার সঙ্গে role-এর সরাসরি সম্পর্ক নেই। ansible --version Ansible বাস্তবে যে config file load করেছে তা দেখায়, আর ansible-config dump --only-changed built-in default থেকে ভিন্ন প্রতিটি setting দেখায়। কোনো run-এ আপনার configuration কার্যকর হচ্ছে না বলে মনে হলে দুটিই পরীক্ষা করুন।
Sharing roles: requirements.yml এবং একটি নির্দিষ্ট সংস্করণ
অন্য কেউ লিখেছে এমন একটি role ইনস্টল করা হয়, কপি করা হয় না। এটি একবার ঘোষণা করুন:
# requirements.yml
---
roles:
- name: postgres
src: https://github.com/example/ansible-role-postgres
scm: git
version: v1.4.0ansible-galaxy install -r requirements.yml -p galaxy_rolesসবসময় version সেট করুন। এটি না থাকলে কমান্ড চালানোর দিনের default branch-এ যা থাকে, সেটিই পাওয়া যায়। ফলে গত মাসে কাজ করা deployment আপনার নিজের repository-তে কোনো পরিবর্তন না থাকলেও ব্যর্থ হতে পারে। roles_path-এ download directory নির্ধারণ করুন এবং ওই directory-টি git-এর বাইরে রাখুন:
# ansible.cfg
[defaults]
inventory = inventory.ini
roles_path = ./galaxy_rolesPlaybook-এর পাশে roles/-এ থাকা role-গুলোও পাওয়া যায়, কারণ roles_path-এর পাশাপাশি ওই path-ও সবসময় অনুসন্ধান করা হয়। তাই আপনার নিজস্ব role-গুলো committed এবং reviewed থাকে, আর third-party role-গুলো tag-এ pinned reproducible download হিসেবে ব্যবহৃত হয়।
যেখানে role আর উপযুক্ত সমাধান নয়
একটি Ansible run-এর মধ্যে role হলো পুনর্ব্যবহারের একটি একক। এটি আপনার provider-এ server বা DNS record তৈরি করে না। role-কে দিয়ে এসব করানোর চেষ্টা করলেই playbook এমন অবস্থায় যায়, যা কেউ আর রক্ষণাবেক্ষণ করতে চায় না। শুরু করার আগে Ansible এবং Terraform-এর মধ্যে কাজের বিভাজন পড়ে নেওয়া উপযোগী। role inventory design-এরও বিকল্প নয়। কয়েকটি মেশিনের বেশি হলে কীভাবে সেই server-গুলোকে group করবেন এবং সেগুলোতে সংযোগ করবেন—তা task কীভাবে সাজানো হয়েছে তার চেয়ে বেশি গুরুত্বপূর্ণ হয়ে ওঠে।
এই common role যে hardening প্রয়োগ করে, তার জন্যও আলাদা সিদ্ধান্ত প্রয়োজন। উপরের drop-in-এ মাত্র দুটি directive সেট করা হয়েছে। তাই আপনার পরিচালিত প্রতিটি host-এর role-এ কী রাখা উচিত তা নির্ধারণের আগে কোন SSH setting সত্যিই পরিবর্তন করা উপযোগী এবং Ubuntu-কে কীভাবে স্বয়ংক্রিয়ভাবে security update প্রয়োগ করাবেন পড়ুন।
FAQ
কখন একটি Ansible playbook-কে role-এ রূপান্তর করা উচিত?
যখন একই task block দ্বিতীয় কোনো play-তে বা দ্বিতীয় কোনো host group-এর বিরুদ্ধে চালাতে হয়। Playbook-এর মধ্যে task কপি করা এর স্পষ্ট সংকেত। কারণ তখন থেকে প্রতিটি সংশোধন দুই জায়গায় প্রয়োগ করতে হবে, এবং কোনো এক সময় তা কেবল এক জায়গায় প্রয়োগ হবে। প্রায় 100 লাইনের কম একটি playbook, যা সব সময় শুধু একটি group-কে target করে, role ব্যবহার করে কোনো সুবিধা পায় না। অতিরিক্ত directory বরং এটি পড়া কঠিন করে।
একই play-তে থাকা task-এর আগে কি role চলে?
হ্যাঁ। Ansible প্রথমে pre_tasks চালায়, এরপর roles:-এর অধীনে তালিকাভুক্ত সবকিছু, তারপর tasks:, এবং শেষে post_tasks:। আপনার file-এ এই key-গুলো যে ক্রমেই থাকুক, Ansible তা উপেক্ষা করে। tasks:-কে roles:-এর উপরে লিখলে ওই task আগে চলে না। কোনো কিছু role-এর আগে চালানো আবশ্যক হলে সেটি pre_tasks:-এ রাখুন।
আমার group_vars-এর মান role-কে override করছে না কেন?
ভেরিয়েবলটি defaults/main.yml-এর বদলে role-এর vars/main.yml-এ সেট করা আছে কি না পরীক্ষা করুন। Ansible-এর precedence order-এ vars/, group_vars এবং host_vars-এর উপরে থাকে। তাই inventory এটিকে override করতে পারে না। ভেরিয়েবলটি defaults/main.yml-এ সরান। এটি precedence order-এর নিচের দিকে থাকে এবং caller-এর পরিবর্তন করতে পারা উচিত এমন ভেরিয়েবলের জন্য এটিই সঠিক স্থান। precedence সমস্যাটিই কারণ, typo নয়, তা নিশ্চিত করতে একবার -e name=value দিয়ে চালান। এটি অন্য সব source-এর চেয়ে বেশি precedence পায়।
Ansible বলছে role পাওয়া যায়নি কেন?
অনুসন্ধান playbook file-এর পাশের directory থেকে শুরু হয়। তাই site.yml এবং roles/ একই directory-তে থাকতে হবে। Error message-এ Ansible যে path-গুলো পরীক্ষা করেছে, সেগুলো the role 'common' was not found in /home/deploy/lonely/roles:/home/deploy/lonely-এর মতো দেখানো হয়। Parent directory থেকে playbook চালানো সমস্যা নয়, কারণ অনুসন্ধান আপনার shell-এর working directory নয়, playbook path অনুসরণ করে। আপনি যদি ansible.cfg থেকে roles_path-এর ওপর নির্ভর করেন, তাহলে ansible --version দিয়ে নিশ্চিত করুন যে file-টি load করা হয়েছে। World-writable working directory থাকলে Ansible এটি উপেক্ষা করে।
Role তৈরি করতে কি ansible-galaxy init প্রয়োজন?
না। Role হলো প্রত্যাশিত নামের directory-গুলোর একটি কাঠামো। তাই mkdir -p roles/common/tasks এবং একটি tasks/main.yml থাকলেই একটি কার্যকর role তৈরি হয়। ansible-galaxy init --init-path roles common-এর সাহায্যে typing কমে এবং meta/main.yml ও একটি README stub-সহ সম্পূর্ণ skeleton তৈরি হয়। যে directory-গুলো খালি রেখে দেন, সেগুলো মুছে ফেলুন। কারণ খালি vars/main.yml role-এ আসলে কোন file কার্যকর তা বোঝা কঠিন করে।