Ansible playbook बनाम role: कब किसका उपयोग करें?
Ansible playbook और role के बीच का अंतर समझें। जानें कि कब एक साधारण playbook पर्याप्त है और कब आपको ansible-galaxy init के साथ role का उपयोग करना चाहिए।
Ansible playbook बनाम role: क्या अंतर है
Ansible playbook वह फ़ाइल है जिसे आप ansible-playbook के साथ चलाते हैं। यह hosts के एक समूह को उनके द्वारा किए जाने वाले कार्यों से जोड़ती है। Ansible role एक निश्चित लेआउट वाली डायरेक्टरी है जिसमें tasks, templates, handlers और default variables होते हैं, और एक playbook इसे नाम से कॉल करती है। दोनों के भीतर task सिंटैक्स समान है, इसलिए यह इस बारे में नहीं है कि आप क्या व्यक्त कर सकते हैं। यह पुन: उपयोग (reuse) का प्रश्न है।
एक साधारण playbook से शुरुआत करें। एक site.yml जिसमें tasks: की सूची हो, आपके पहले ऑटोमेशन के लिए सही स्वरूप है, और यह अधिकांश लोगों की अपेक्षा से अधिक समय तक सही बना रहता है। जब कार्यों के उसी ब्लॉक को hosts के दूसरे समूह के लिए चलाना हो, या जब फ़ाइल लगभग 100 लाइनों से अधिक बढ़ जाए और आप स्क्रॉल करके task न ढूंढ पा रहे हों, तब इसे role में बदलें।
यदि आपने अभी तक एक भी नहीं लिखा है, तो एक single VPS के लिए पहली playbook से शुरुआत करें और जब यह बढ़ने लगे तब वापस आएं।
जब एक flat playbook सही विकल्प हो
एक flat playbook तब सही होती है जब काम केवल एक बार करना हो, किसी एक host पर करना हो, या जब इसे किसी और के द्वारा नहीं पढ़ा जाना हो। किसी एक application server को provision करना, या maintenance window से पहले किसी box को patch करना: इनमें से किसी भी काम के लिए directory tree की आवश्यकता नहीं होती। एक role सात directories और indirection की एक परत जोड़ देता है। यदि इसे केवल बगल में रखी playbook ही call करती है, तो वह indirection कोई लाभ नहीं देता और हर बार जब आप यह पढ़ना चाहते हैं कि वास्तव में क्या run हो रहा है, तो आपको एक अतिरिक्त jump लगानी पड़ती है।
एक flat playbook सही विकल्प तब नहीं रह जाती जब एक विशिष्ट स्थिति आती है, और उस स्थिति को पहचानना आसान है। जब आप tasks के एक block को दूसरी playbook में copy करते हैं। वह copy ही संकेत है। उसके बाद से हर सुधार को दो बार करना पड़ता है, और एक दिन ऐसा आएगा जब वह केवल एक ही बार किया जाएगा।
एक 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.ymlentry point है। जब role को call किया जाता है, तो Ansible इस file को चलाता है, और बाकी सभी directories वैकल्पिक हैं।defaults/main.ymlमें वे variables होते हैं जिन्हें caller द्वारा override किए जाने की अपेक्षा होती है। यह Ansible में सबसे कम प्राथमिकता वाला स्रोत है, इसलिए लगभग बाकी सब कुछ इससे ऊपर रहता है।vars/main.ymlमें वे variables होते हैं जिन्हें caller द्वारा override करने की अपेक्षा नहीं होती है। यह प्राथमिकता में inventory से ऊपर रहता है, जो कि एक बहुत ही सख्त नियम है। इसका उपयोग कम ही करें।handlers/main.ymlमें वे tasks होते हैं जोnotifyद्वारा trigger किए जाते हैं। एक handler play के अंत में एक बार चलता है, चाहे उसे कितनी भी बार notify किया गया हो।files/में वे files होती हैं जिन्हेंcopymodule द्वारा ज्यों का त्यों copy किया जाता है, औरtemplates/में Jinja2 templates होते हैं जिन्हेंtemplatemodule द्वारा render किया जाता है। एक role के अंदर आप दोनों को बिना किसी path के केवल filename से reference करते हैं, क्योंकि Ansible सबसे पहले role की अपनी directories में खोजता है।meta/main.ymlrole dependencies और उस metadata को घोषित करता है जिसे Ansible Galaxy पढ़ता है।
यह layout केवल पसंद की बात नहीं है। Ansible इन्हीं सटीक paths में देखता है, इसलिए यदि आप कोई template roles/common/template/ (एकवचन) में रखते हैं, तो वह कभी नहीं मिलेगा।
ansible-galaxy init के साथ common role बनाएं
mkdir -p ~/infra/roles
cd ~/infra
ansible-galaxy init --init-path roles commonयह roles/common के अंतर्गत पूरा ढांचा तैयार कर देता है, जिसमें ऐसी directories भी शामिल होती हैं जिनका आप उपयोग नहीं करेंगे और main.yml स्टब्स होते हैं जिनमें केवल --- होता है। जिन्हें आप खाली छोड़ते हैं, उन्हें हटा दें। एक खाली vars/main.yml Ansible के लिए हानिकारक नहीं है, लेकिन यह छिपा देता है कि role में वास्तव में कौन सी फाइलें मायने रखती हैं।
अब उन फाइलों को भरें जो काम करती हैं। सबसे पहले 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, YAML को PyYAML के साथ पार्स करता है, जो एक खाली no को boolean false के रूप में पढ़ता है, इसलिए रेंडर की गई config लाइन PermitRootLogin False बन जाती है और sshd इसे अस्वीकार कर देता है। कोट्स (quotes) मान को एक 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 परिवार के सिस्टम पर यह sshd है। जो handler गलत नाम का उपयोग करता है, वह केवल तभी विफल होता है जब template में वास्तव में कुछ बदलता है, यही कारण है कि यह समस्या आमतौर पर हफ्तों बाद सामने आती है।
validate लाइन उस task में सबसे उपयोगी चीज है। Ansible template को एक अस्थायी फाइल में रेंडर करता है, उस फाइल के पथ को %s के लिए प्रतिस्थापित करता है, और कमांड चलाता है। destination केवल तभी बदला जाता है जब कमांड 0 exit code के साथ समाप्त हो। template में एक निरर्थक directive डालें और फिर से चलाएं: task failed to validate के साथ विफल हो जाता है, वास्तविक /etc/ssh/sshd_config.d/99-hardening.conf अप्रभावित रहता है, और आपके पास अभी भी एक ऐसा सर्वर है जिसमें आप लॉग इन कर सकते हैं। ध्यान रखें कि यह चेक केवल आपके सिंटैक्स से अधिक का परीक्षण करता है। यदि sshd -t होस्ट कीज़ (host keys) को नहीं पढ़ सकता है, तो यह sshd: no hostkeys available -- exiting. के साथ समाप्त होता है और 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.ymlPlay का अंत recap में failed=0 के साथ होना चाहिए। कॉल साइट पर expanded form का उपयोग करके parameters पास करें, इसी तरह एक role दो host groups की सेवा करता है:
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: के ऊपर रखें, फिर भी roles सबसे पहले ही चलेंगे। इसलिए यदि किसी 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 को पढ़ता है और इसके tasks play का हिस्सा बन जाते हैं, इसलिए ansible-playbook --list-tasks site.yml उन्हें list करता है और import पर लगा tag अंदर के हर task पर लागू होता है। include_role dynamic है। जब तक task run नहीं होता, तब तक कुछ भी नहीं पढ़ा जाता है, जो आपको variable या loop से role का नाम तय करने की सुविधा देता है। इसकी कीमत यह है कि वे tasks --list-tasks और --start-at-task के लिए अदृश्य होते हैं।
यहाँ एक trap है। include_role task पर लगा when:, शामिल किए गए role के defaults/main.yml के scope में आने से पहले evaluate हो जाता है। include पर when: common_packages | length > 0 लिखें और run 'common_packages' is undefined के साथ रुक जाएगा, भले ही वह variable उसी role में परिभाषित हो जिसे आप include कर रहे हैं। इसका समाधान यह है कि toggle को role से बाहर निकालें: इसे group_vars/all.yml में रखें, जहाँ यह हर जगह scope में होता है, और role के defaults को उन values के लिए छोड़ दें जिनका उपयोग role स्वयं करता है।
कौन सा वेरिएबल प्रभावी होता है: defaults, group_vars, vars, extra vars
Ansible में वेरिएबल प्राथमिकता (variable precedence) के बीस से अधिक स्तर होते हैं। इनमें से चार स्तर लगभग हर वास्तविक विवाद को सुलझा देते हैं, और यहाँ वे सबसे कमजोर से सबसे मजबूत के क्रम में दिए गए हैं।
roles/<name>/defaults/main.ymlसबसे नीचे के स्तर पर होता है। आप कहीं और जो भी सेट करते हैं, वह लगभग हमेशा इसे ओवरराइड कर देता है, और यही कारण है कि यह किसी role के ट्यूनेबल पैरामीटर्स के लिए सही स्थान है।group_vars/औरhost_vars/बीच में आते हैं। यहाँ आपके साइट के अपने उत्तर होने चाहिए, और ये role defaults को स्पष्ट रूप से ओवरराइड करते हैं।roles/<name>/vars/main.ymlका स्थानhost_varsसे ऊपर है। यहाँ रखा गया मान inventory से ओवरराइड नहीं किया जा सकता। इसे उन चीजों के लिए सुरक्षित रखें जिन्हें role के भीतर सुसंगत रहने की आवश्यकता है, जैसे कि कोई package name जिसे service name से मेल खाना चाहिए।- कॉल साइट पर पास किया गया role parameter
vars/main.ymlको हरा देता है, और कमांड लाइन पर दिया गया-eबाकी सब कुछ, यहाँ तक कि role parameters को भी ओवरराइड कर देता है।
आप लगभग एक मिनट में इसे हल होते हुए देख सकते हैं। एक छोटे 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पहला रन tunable=from-hostvars internal=from-rolevars प्रिंट करता है। Inventory ने role default को हरा दिया लेकिन role var से हार गई। दूसरा रन internal=from-cli प्रिंट करता है, क्योंकि extra vars सबसे ऊपर होते हैं और नीचे का कोई भी मान इसे बदल नहीं सकता। यही कारण है कि -e एक बार के रन के लिए तो ठीक है, लेकिन आपके द्वारा रखे गए स्क्रिप्ट में यह गलत है: यह चुपचाप आपके रिपॉजिटरी में लिए गए हर सोच-समझकर किए गए निर्णय को ओवरराइड कर देता है।
कार्य करने का नियम: यदि आप चाहते हैं कि कोई मान सेट किया जा सके, तो उसे defaults/ में रखें। इसे vars/ में रखने का अर्थ है कि role का उपयोग करने वाले हर भविष्य के उपयोगकर्ता को यह बताना कि inventory इसे बदल नहीं सकती। कभी-कभी आपका यही उद्देश्य होता है, लेकिन आमतौर पर यह एक गलती होती है।
सिद्ध करें कि role 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 ने वर्तमान स्थिति की जांच की और पाया कि काम पहले ही पूरा हो चुका है। दूसरी बार चलाने पर changed=2 का मतलब है कि दो tasks यह नहीं बता पा रहे हैं कि क्या बदलाव हुआ है, इसलिए वे हमेशा फाइलें फिर से लिखते रहेंगे और services को restart करते रहेंगे। इसका सामान्य कारण command या shell होता है, क्योंकि Ansible के पास यह जानने का कोई तरीका नहीं है कि किसी arbitrary command ने क्या किया है।
# 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.txtउस playbook को दो बार चलाएं, फिर wc -l /tmp/grow.txt /tmp/guarded.txt वाली पंक्तियों को गिनें। /tmp/grow.txt में दो पंक्तियाँ होती हैं और /tmp/guarded.txt में एक। दूसरी बार चलाने पर guarded task बिल्कुल भी execute नहीं हुआ, और इसके परिणाम में skipped, since /tmp/guarded.txt exists संदेश होता है, क्योंकि creates module को पहले खोजने के लिए एक दृश्य उत्पाद (visible product) देता है। जब कोई command ऐसा कोई उत्पाद नहीं छोड़ती है, तो उसके output को register करें और changed_when के साथ स्वयं निर्णय लें।
ansible-playbook --check --diff site.yml बिना बदलाव किए परिवर्तनों का पूर्वानुमान लगाता है, और --diff उन सटीक पंक्तियों को print करता है जिन्हें एक template फिर से लिखेगा। output को पढ़ते समय एक सावधानी बरतें: shell और command tasks check mode में छोड़ दिए जाते हैं, इसलिए जो plan साफ दिखता है, उसमें भी काम छिपा हो सकता है।
उस recap में एक और column समान सावधानी का हकदार है: जिस host से Ansible connect नहीं हो सका, उसे failed के बजाय unreachable के अंतर्गत गिना जाता है और उसका कोई भी task run नहीं हुआ, इसलिए यह पहले ही तय कर लें कि क्या एक unreachable host को पूरी run रोक देनी चाहिए इससे पहले कि आप इस role को कुछ से अधिक मशीनों पर point करें।
Ansible यह क्यों कहता है कि role नहीं मिली
Ansible, playbook फ़ाइल के बगल में roles/ डायरेक्टरी को खोजता है, और उसके बाद roles_path में देखता है। यह खोज आपके शेल (shell) के स्थान के बजाय playbook के स्थान का अनुसरण करती है।
ERROR! the role 'common' was not found in /home/deploy/lonely/roles:/home/deploy/lonelyइस संदेश का अर्थ है कि site.yml और roles/ के बीच तालमेल नहीं है, और यह उन पाथ्स (paths) को प्रिंट करता है जिन्हें इसने आज़माया था। इन दोनों को एक ही डायरेक्टरी में रखें। किसी पैरेंट डायरेक्टरी से रन करना ठीक है, क्योंकि playbook का पाथ ही मायने रखता है:
ansible-playbook -i infra/inventory.ini infra/site.ymlइसी समस्या का एक शांत संस्करण भी है। जब वर्तमान डायरेक्टरी world writable होती है, तो Ansible वहां मौजूद ansible.cfg को अनदेखा कर देता है, क्योंकि सिस्टम का कोई भी उपयोगकर्ता वहां कॉन्फ़िगरेशन फ़ाइल डाल सकता है और आपके रन के व्यवहार को बदल सकता है।
[WARNING]: Ansible is being run in a world writable directory (/tmp/infra), ignoring it as an ansible.cfg source.ऐसी स्थिति में आपकी roles_path और inventory सेटिंग्स चुपचाप गायब हो जाती हैं, और role lookup किसी ऐसे कारण से विफल हो जाता है जिसका roles से कोई लेना-देना नहीं है। ansible --version उस config file को प्रिंट करता है जिसे उसने वास्तव में लोड किया है, और ansible-config dump --only-changed उन सभी सेटिंग्स को प्रिंट करता है जो इन-बिल्ट डिफ़ॉल्ट्स से अलग हैं। जब भी रन ऐसा व्यवहार करे जैसे कि आपका कॉन्फ़िगरेशन मौजूद ही नहीं है, तो इन दोनों की जाँच करें।
भूमिकाओं (roles) को साझा करना: requirements.yml और एक पिन की गई version
किसी और द्वारा लिखी गई भूमिका को कॉपी करने के बजाय इंस्टॉल किया जाता है। इसे एक बार घोषित करें:
# 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 को डाउनलोड डायरेक्टरी पर पॉइंट करें और उस डायरेक्टरी को git से बाहर रखें:
# ansible.cfg
[defaults]
inventory = inventory.ini
roles_path = ./galaxy_rolesplaybook के बगल में roles/ में मौजूद भूमिकाएं अभी भी मिल जाती हैं, क्योंकि roles_path के अलावा उस पाथ को हमेशा खोजा जाता है। इस प्रकार, आपकी अपनी भूमिकाएं कमिट और रिव्यु की जाती हैं, जबकि थर्ड-पार्टी भूमिकाएं एक टैग पर पिन की गई पुनरुत्पादनीय (reproducible) डाउनलोड होती हैं।
जहाँ roles का उपयोग सीमित हो जाता है
एक role एक Ansible run के भीतर पुन: उपयोग की एक इकाई है। यह आपके provider पर सर्वर या DNS record नहीं बनाता है, और ऐसा करने का प्रयास करने से playbooks ऐसी बन जाती हैं जिन्हें कोई भी maintain नहीं करना चाहता। शुरू करने से पहले Ansible और Terraform के बीच कार्य का विभाजन पढ़ना उपयोगी है। एक role inventory design का विकल्प भी नहीं है: एक बार जब आप कुछ मशीनों से आगे बढ़ जाते हैं, तो आप उन सर्वरों को कैसे group करते हैं और उन तक कैसे पहुँचते हैं यह इस बात से अधिक मायने रखता है कि tasks को कैसे file किया गया है।
यह common role जो hardening install करता है, उसके लिए भी अलग से निर्णय लेने की आवश्यकता है। ऊपर दिया गया drop-in केवल दो directives सेट करता है और कुछ नहीं, इसलिए यह तय करने से पहले कि आपके हर host के लिए role में क्या होना चाहिए, किन SSH settings को बदलना वास्तव में सार्थक है और Ubuntu को अपने आप security updates लागू करने के लिए कैसे सेट करें इसे पढ़ें।
FAQ
मुझे Ansible playbook को role में कब बदलना चाहिए?
जब कार्यों (tasks) के एक ही ब्लॉक को दूसरी play में या hosts के दूसरे समूह पर चलाना हो। जब आप playbooks के बीच tasks को कॉपी करने लगते हैं, तो यह संकेत है कि आपको role का उपयोग करना चाहिए, क्योंकि ऐसा करने पर हर सुधार को दो बार लागू करना पड़ेगा और किसी न किसी दिन आप एक जगह सुधार करना भूल जाएंगे। लगभग 100 लाइनों से छोटी एक अकेली playbook जो केवल एक समूह को target करती है, उसे role में बदलने से कोई लाभ नहीं होता और अतिरिक्त directories के कारण उसे पढ़ना कठिन हो जाता है।
क्या roles उसी play में मौजूद tasks से पहले चलते हैं?
हाँ। Ansible पहले pre_tasks चलाता है, फिर roles: के अंतर्गत सूचीबद्ध सभी चीजें, फिर tasks:, और अंत में post_tasks:; यह इस बात पर ध्यान नहीं देता कि आपकी फाइल में ये keys किस क्रम में लिखी हैं। tasks: को roles: के ऊपर लिखने से वे tasks पहले नहीं चलेंगे। यदि किसी कार्य को role से पहले होना अनिवार्य है, तो उसे pre_tasks: में रखें।
मेरा group_vars मान role को override क्यों नहीं कर रहा है?
जाँचें कि क्या variable role की vars/main.yml में सेट है, न कि defaults/main.yml में। Ansible की प्राथमिकता (precedence) के क्रम में vars/, group_vars और host_vars से ऊपर आता है, इसलिए inventory इसे override नहीं कर सकती। variable को defaults/main.yml में ले जाएँ, जो प्राथमिकता क्रम में नीचे की ओर है और किसी भी ऐसी चीज के लिए सही स्थान है जिसे caller द्वारा बदला जाना चाहिए। यह पुष्टि करने के लिए कि समस्या typo के बजाय प्राथमिकता के कारण है, एक बार -e name=value के साथ चलाएं, जो अन्य सभी स्रोतों से अधिक प्रभावी है।
Ansible यह क्यों कहता है कि role नहीं मिला?
खोज playbook फाइल के पास से शुरू होती है, इसलिए site.yml और roles/ को एक ही directory में होना चाहिए। error उन paths को print करता है जिन्हें उसने आजमाया, जैसा कि the role 'common' was not found in /home/deploy/lonely/roles:/home/deploy/lonely में दिखाया गया है। playbook को parent directory से चलाना ठीक है, क्योंकि खोज playbook के path का अनुसरण करती है, न कि आपके shell की working directory का। यदि आप ansible.cfg से roles_path पर निर्भर हैं, तो पुष्टि करें कि वह फाइल ansible --version के साथ लोड की गई थी, क्योंकि world writable working directory होने पर Ansible उसे अनदेखा कर देता है।
क्या role बनाने के लिए मुझे ansible-galaxy init की आवश्यकता है?
नहीं। एक role केवल अपेक्षित नामों वाली directories का समूह है, इसलिए mkdir -p roles/common/tasks और साथ में एक tasks/main.yml पहले से ही एक कार्यशील role है। ansible-galaxy init --init-path roles common टाइपिंग बचाता है और आपको पूरा ढांचा देता है, जिसमें meta/main.yml और एक README stub शामिल हैं। जिन directories को आप खाली छोड़ते हैं उन्हें हटा दें, क्योंकि एक खाली vars/main.yml यह छिपा देता है कि role में कौन सी फाइलें वास्तव में काम कर रही हैं।