SSD Nodes Learn 🎉 VPS kutoka $5.50/mwezi
Mwongozo Matt ConnorNa Matt Connor · Imeboreshwa 2026-08-13

Tofauti kati ya Ansible playbook na role

Jifunze wakati mwafaka wa kutumia playbook ya kawaida dhidi ya Ansible role. Tunachambua mpangilio wa saraka, matumizi ya ansible-galaxy init, na kanuni za kipaumbele za vigezo.

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, July 30, 2026.

Tofauti kati ya Ansible playbook na role

Ansible playbook ni faili unaloliendesha kwa kutumia ansible-playbook. Linahusisha kundi la hosts na kazi zinazopaswa kufanyika. Ansible role ni saraka yenye mpangilio maalum inayohifadhi tasks, templates, handlers na default variables, na playbook huiita kwa jina lake. Sintaksia ya task ndani ya zote mbili inafanana, kwa hivyo hii si swali la kile unachoweza kuelezea. Ni swali la matumizi ya kurudia (reuse).

Anza na playbook ya kawaida. site.yml moja inayoshikilia orodha ya tasks: ndiyo umbo sahihi kwa ajili ya otomatiki yako ya kwanza, na inabaki kuwa sahihi kwa muda mrefu kuliko watu wengi wanavyotarajia. Badilisha kuwa role wakati kundi lilelile la tasks linapohitajika kuendeshwa kwa kundi la pili la hosts, au wakati faili linapozidi takriban mistari 100 na huwezi tena kupata task kwa kusogeza ukurasa.

Ikiwa bado hujaandika hata moja, anza na playbook ya kwanza dhidi ya VPS moja na urudi hapa wakati inapoanza kukua.

Wakati playbook ya kawaida inapofaa

Playbook ya kawaida (flat playbook) inafaa wakati kazi inafanyika mara moja, au kwenye host moja, au wakati hakuna mtu mwingine atakayeisoma. Kusanidi seva moja ya programu, au kufanya patching ya seva kabla ya muda wa matengenezo: hakuna kati ya hayo linalohitaji muundo wa saraka (directory tree). Role huongeza saraka saba na safu moja ya ziada ya kurejelea (indirection). Ikiwa mpigaji simu pekee ni playbook iliyo karibu nayo, kurejelea huko hakuna faida yoyote na kunakulazimisha kuruka kurasa kila wakati unapotaka kusoma kile kinachoendeshwa kihalisi.

Playbook ya kawaida huacha kuwa sahihi katika wakati maalum, na wakati huo ni rahisi kuutambua. Unapokopi kizuizi cha tasks kwenye playbook ya pili. Kopi hiyo ndiyo ishara. Kuanzia hapo, kila marekebisho lazima yafanyike mara mbili, na siku moja yatafanywa mara moja tu.

Yaliyomo halisi kwenye saraka ya role

roles/common/
  defaults/main.yml
  vars/main.yml
  tasks/main.yml
  handlers/main.yml
  templates/99-hardening.conf.j2
  files/
  meta/main.yml
  • tasks/main.yml ndiyo sehemu ya kuanzia. Ansible huendesha faili hili wakati role inapoitwa, na kila saraka nyingine ni ya hiari.
  • defaults/main.yml huhifadhi vigezo (variables) ambavyo anayetoa wito anatarajiwa kuvibadilisha. Hii ndiyo chanzo chenye kipaumbele cha chini kabisa katika Ansible, kwa hivyo karibu kila kitu kingine huizidi kwa nguvu.
  • vars/main.yml huhifadhi vigezo ambavyo anayetoa wito hatarajiwi kuvibadilisha. Inakaa juu ya inventory katika kipaumbele, jambo ambalo ni agizo zito. Itumie kwa nadra.
  • handlers/main.yml huhifadhi tasks zinazochochewa na notify. Handler huendeshwa mwishoni mwa play, mara moja tu, bila kujali ni tasks ngapi zimeiita.
  • files/ huhifadhi faili zinazonakiliwa kama zilivyo na moduli ya copy, na templates/ huhifadhi Jinja2 templates zinazotafsiriwa na moduli ya template. Ndani ya role, unarejelea zote mbili kwa jina la faili pekee bila njia (path), kwa sababu Ansible hutafuta kwenye saraka za role yenyewe kwanza.
  • meta/main.yml hutangaza utegemezi wa role (dependencies) na metadata inayosomwa na Ansible Galaxy.

Mpangilio huu si suala la upendeleo wa mtindo. Ansible hutafuta katika njia hizi kamili, kwa hivyo template unayoiweka kwenye roles/common/template/ (umoja) haitapatikana kamwe.

Jenga role ya kawaida kwa kutumia ansible-galaxy init

mkdir -p ~/infra/roles
cd ~/infra
ansible-galaxy init --init-path roles common

Amri hiyo huandika muundo mzima wa faili chini ya roles/common, ikijumuisha saraka ambazo hutazitumia na stubs za main.yml zenye --- pekee. Futa zile unazoziaacha tupu. Faili tupu ya vars/main.yml haina madhara kwa Ansible, lakini huficha ni faili zipi ndani ya role hiyo ambazo ni muhimu.

Sasa jaza faili zinazotekeleza kazi. Anza na defaults, kwa sababu ndizo interface ya umma ya role hiyo.

# roles/common/defaults/main.yml
---
common_packages:
  - ufw
  - fail2ban
  - unattended-upgrades
common_admin_group: admins
common_permit_root_login: "no"
common_password_authentication: "no"

Weka alama za kunukuu kwenye "no" na "yes". Ansible huchakata YAML kwa kutumia PyYAML, ambayo husoma no tupu kama boolean false, kwa hivyo mstari wa usanidi unaotokana huwa PermitRootLogin False na sshd huukataa. Alama za kunukuu huhakikisha thamani hiyo inabaki kama 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 }}

Kwenye Debian na Ubuntu, unit ya systemd inaitwa ssh, na kwenye mifumo ya familia ya RHEL inaitwa sshd. Handler inayotaja jina lisilo sahihi itafeli tu wakati kitu fulani kinapobadilisha template, ndiyo maana tatizo hili mara nyingi hujitokeza wiki kadhaa baadaye.

Mstari wa validate ndio kitu muhimu zaidi katika task hiyo. Ansible huchakata template na kuiweka kwenye faili ya muda, hubadilisha njia ya faili hiyo na %s, kisha huendesha amri hiyo. Faili ya mwisho hubadilishwa tu ikiwa amri itatoka na exit code 0. Weka directive isiyo na maana kwenye template na uendeshe tena: task itafeli na failed to validate, faili halisi ya /etc/ssh/sshd_config.d/99-hardening.conf haitaguswa, na bado utakuwa na seva unayoweza kuingia. Fahamu kuwa ukaguzi huu hujaribu zaidi ya syntax yako. Ikiwa sshd -t haiwezi kusoma host keys, itatoka na sshd: no hostkeys available -- exiting. na Ansible itaripoti failed to validate hiyohiyo, kwa hivyo soma msg ya module hiyo kabla ya kulaumu template.

Jinsi playbook inavyoita role

# site.yml
---
- name: Base configuration for every server
  hosts: all
  become: true
  roles:
    - common
# inventory.ini
[local]
localhost ansible_connection=local
ansible-playbook -i inventory.ini site.yml

Play inapaswa kumalizika na failed=0 katika muhtasari. Pitisha vigezo (parameters) kwenye sehemu ya mwito kwa kutumia fomu iliyopanuliwa, ambayo ndiyo njia ya role moja kuhudumia makundi mawili ya hosts:

  roles:
    - role: common
      common_admin_group: ops
      common_permit_root_login: prohibit-password

Kuna kanuni moja ya mpangilio inayowashangaza karibu watu wote. Play inaweza kuwa na pre_tasks, roles, tasks na post_tasks, na Ansible huzitekeleza kwa mpangilio huo bila kujali mpangilio uliouandika kwenye faili. Weka tasks: juu ya roles: na roles bado zitatekelezwa kwanza. Kwa hivyo, ikiwa kitu lazima kitokee kabla ya role, kinapaswa kuwa ndani ya pre_tasks:, siyo juu ya 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: post

Ili kuita role kutoka ndani ya orodha ya tasks badala ya kutumia ufunguo wa roles:, tumia import_role au 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 ni tuli (static). Ansible husoma role wakati wa kuchanganua (parse time) na tasks zake huwa sehemu ya play, kwa hivyo ansible-playbook --list-tasks site.yml huziorodhesha na tag iliyowekwa kwenye import huathiri kila task iliyo ndani. include_role ni dinamiki (dynamic). Hakuna kinachosomwa hadi task itekelezwe, jambo ambalo hukuruhusu kuendesha jina la role kutoka kwa variable au loop. Gharama yake ni kwamba tasks hizo hazionekani na --list-tasks na --start-at-task.

Mtego mmoja upo hapa. when: kwenye task ya include_role hutathminiwa kabla ya defaults/main.yml ya role iliyojumuishwa (included) kuwa katika wigo (scope). Andika when: common_packages | length > 0 kwenye include na utekelezaji utasitishwa na 'common_packages' is undefined, ingawa variable hiyo imefafanuliwa ndani ya role yenyewe unayoiingiza. Suluhisho ni kuondoa kigezo hicho nje ya role: kiweke kwenye group_vars/all.yml, ambapo kinapatikana kila mahali, na uache defaults za role kwa ajili ya thamani ambazo role yenyewe huzitumia.

Which variable wins: defaults, group_vars, vars, extra vars

Ansible documents more than twenty levels of variable precedence. Four of them settle nearly every real argument, and here they are from weakest to strongest.

  • roles/<name>/defaults/main.yml sits near the bottom. Almost anything you set anywhere else beats it, which is exactly why it is the right home for a role's tunable knobs.
  • group_vars/ and host_vars/ sit in the middle. This is where your site's own answers belong, and they cleanly override role defaults.
  • roles/<name>/vars/main.yml sits above host_vars. A value you put here cannot be overridden from inventory. Reserve it for things the role needs to stay internally consistent, such as a package name that has to match a service name.
  • A role parameter passed at the call site beats vars/main.yml, and -e on the command line beats everything, including role parameters.

You can watch this resolve in about a minute. Give a small role one default and one role var, then set the same names in 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

The first run prints tunable=from-hostvars internal=from-rolevars. Inventory beat the role default and lost to the role var. The second run prints internal=from-cli, because extra vars sit at the very top and nothing below can push back. That is also why -e is fine for a one-off run and wrong in a script you keep: it silently outranks every considered decision in your repository.

The working rule: if you want a value to be settable, it goes in defaults/. Putting it in vars/ tells every future user of the role that inventory may not change it. That is occasionally what you meant, and usually an accident.

Thibitisha kuwa role ni idempotent: iendeshe mara mbili

Ansible playbook inayotegemeka hutoa matokeo sawa katika jaribio la pili na kuripoti kuwa hakuna kilichobadilika. Endesha playbook mara mbili na usome muhtasari wake.

ansible-playbook -i inventory.ini site.yml
ansible-playbook -i inventory.ini site.yml

Muhtasari wa pili unapaswa kuonekana hivi:

PLAY RECAP *********************************************************************
localhost   : ok=4  changed=0  unreachable=0  failed=0  skipped=0  rescued=0  ignored=0

changed=0 inamaanisha kila moduli ilikagua hali ya sasa na kugundua kuwa kazi imeshakamilika. changed=2 katika jaribio la pili inamaanisha kuna tasks mbili ambazo haziwezi kutofautisha hali ya sasa na inayotakiwa, hivyo zitaendelea kuandika upya faili na kuanzisha upya huduma bila kikomo. Sababu ya kawaida ni command au shell, kwa sababu Ansible haina njia ya kujua nini amri ya kiholela imefanya.

# 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

Endesha playbook hiyo mara mbili, kisha uhesabu mistari yenye wc -l /tmp/grow.txt /tmp/guarded.txt. /tmp/grow.txt ina mistari miwili na /tmp/guarded.txt ina mstari mmoja. Katika jaribio la pili, task iliyolindwa haikutekelezwa kabisa, na matokeo yake yana ujumbe skipped, since /tmp/guarded.txt exists, kwa sababu creates huipa moduli kitu kinachoonekana cha kukagua kwanza. Amri inaposhindwa kuacha kitu kama hicho, hifadhi matokeo yake (register) na uamue mwenyewe kwa kutumia changed_when.

ansible-playbook --check --diff site.yml hutabiri mabadiliko bila kuyafanya, na --diff huchapisha mistari kamili ambayo template ingeandika upya. Soma matokeo hayo kwa kuzingatia tahadhari moja: tasks za shell na command hurukwa katika check mode, kwa hivyo mpango unaoonekana kuwa safi unaweza bado kuficha kazi inayopaswa kufanyika.

Kwa nini Ansible inasema role haikupatikana

Ansible hutafuta saraka ya roles/ karibu na faili ya playbook, kisha katika roles_path. Utafutaji hufuata playbook, si shell yako.

ERROR! the role 'common' was not found in /home/deploy/lonely/roles:/home/deploy/lonely

Ujumbe huo unamaanisha kuwa site.yml na roles/ zimetofautiana, na inachapisha njia ilizojaribu kwa manufaa yako. Weka faili hizo mbili katika saraka moja. Kuendesha kutoka saraka kuu ni sawa, kwa sababu njia ya playbook ndiyo inayozingatiwa:

ansible-playbook -i infra/inventory.ini infra/site.yml

Kuna toleo tulivu zaidi la tatizo hilo hilo. Ansible hupuuza ansible.cfg katika saraka ya sasa wakati saraka hiyo ina ruhusa ya kuandikwa na kila mtu (world writable), kwa sababu mtumiaji yeyote kwenye seva anaweza kuweka usanidi hapo na kubadilisha utendaji wa run yako.

[WARNING]: Ansible is being run in a world writable directory (/tmp/infra), ignoring it as an ansible.cfg source.

Mipangilio yako ya roles_path na inventory inakuwa haipo kimyakimya, na utafutaji wa role unashindwa kwa sababu isiyo na uhusiano wowote na roles. ansible --version huchapisha config file iliyopakia, na ansible-config dump --only-changed huchapisha kila mpangilio unaotofautiana na chaguo-msingi za mfumo. Kagua zote mbili wakati wowote run inapoonekana kama usanidi wako haupo.

Kushiriki roles: mahitaji ya requirements.yml na toleo lililofungwa (pinned)

Role iliyoandikwa na mtu mwingine husakinishwa, hainakiliwi. Itangaze mara moja:

# requirements.yml
---
roles:
  - name: postgres
    src: https://github.com/example/ansible-role-postgres
    scm: git
    version: v1.4.0
ansible-galaxy install -r requirements.yml -p galaxy_roles

Weka version kila wakati. Bila hiyo, utapata toleo lolote lililopo kwenye branch chaguo-msingi siku unayotekeleza amri hiyo, hivyo deployment iliyofanya kazi mwezi uliopita itafeli bila mabadiliko yoyote kwenye repository yako. Elekeza roles_path kwenye saraka ya kupakua, na uweke saraka hiyo nje ya git:

# ansible.cfg
[defaults]
inventory = inventory.ini
roles_path = ./galaxy_roles

Roles zilizo ndani ya roles/ karibu na playbook bado hupatikana, kwa sababu njia hiyo hutafutwa kila wakati pamoja na roles_path. Kwa hivyo, roles zako mwenyewe hubaki zikiwa zimefanyiwa commit na kupitiwa, huku roles za watu wengine zikiwa ni vipakuliwa vinavyoweza kurudiwa na vilivyofungwa kwenye tag fulani.

Wakati roles zinapoacha kuwa suluhisho

Role ni kitengo cha matumizi ya mara kwa mara ndani ya Ansible run moja. Haitengenezi seva au DNS records kwa mtoa huduma wako, na kujaribu kuilazimisha kufanya hivyo ndiyo njia inayofanya playbooks kugeuka kuwa kitu ambacho hakuna mtu anayetaka kukitunza. mgawanyo wa kazi kati ya Ansible na Terraform inafaa kusomwa kabla ya kuanza. Pia, role haichukui nafasi ya usanifu wa inventory: ukishavuka idadi ndogo ya mashine, jinsi unavyozipanga na kuzifikia seva hizo ni muhimu zaidi kuliko jinsi tasks zinavyohifadhiwa kwenye faili.

Uimarishaji wa usalama (hardening) ambao role hii ya common inasakinisha unastahili maamuzi yake yenyewe pia. Usanidi wa haraka hapo juu unaweka maelekezo mawili tu na si zaidi, kwa hivyo soma ni mipangilio ipi ya SSH inayostahili kubadilishwa kweli na jinsi ya kuifanya Ubuntu itekeleze masasisho ya usalama yenyewe kabla ya kuamua ni nini kinachopaswa kuwemo kwenye role kwa kila host unayomiliki.

FAQ

Ni lini ninapaswa kubadilisha Ansible playbook kuwa role?

Wakati kundi lilelile la tasks linapohitajika kutekelezwa katika play ya pili, au dhidi ya kundi la pili la hosts. Kunakili tasks kati ya playbooks ndiyo ishara ya kufanya hivyo, kwa sababu kuanzia wakati huo kila marekebisho yatalazimika kufanywa mara mbili na siku moja yatafanywa mara moja tu. Playbook moja yenye takriban mistari 100 ambayo inalenga kundi moja tu haipati faida yoyote kutoka kwa role, na saraka za ziada hufanya iwe vigumu kusoma.

Je, roles hutekelezwa kabla ya tasks katika play moja?

Ndiyo. Ansible hutekeleza pre_tasks, kisha kila kitu kilichoorodheshwa chini ya roles:, kisha tasks:, kisha post_tasks:, na hupuuza mpangilio ambao funguo hizo zinaonekana kwenye faili yako. Kuandika tasks: juu ya roles: hakufanyi tasks hizo kutekelezwa kwanza. Ikiwa kitu lazima kitokee kabla ya role, kiweke ndani ya pre_tasks:.

Kwa nini thamani yangu ya group_vars haibatilishi role?

Angalia kama variable imewekwa ndani ya vars/main.yml ya role badala ya defaults/main.yml. vars/ iko juu ya group_vars na host_vars katika mpangilio wa kipaumbele wa Ansible, kwa hivyo inventory haiwezi kuibatilisha. Hamisha variable hiyo kwenda defaults/main.yml, ambayo iko karibu na chini ya mpangilio na ndiyo mahali sahihi kwa chochote ambacho mwitaji anapaswa kuwa na uwezo wa kukibadilisha. Ili kuthibitisha kuwa kipaumbele ndiyo sababu badala ya kosa la uchapaji, tekeleza mara moja kwa kutumia -e name=value, ambayo inazidi kila chanzo kingine.

Kwa nini Ansible inasema role haikupatikana?

Utafutaji huanzia karibu na faili ya playbook, kwa hivyo site.yml na roles/ lazima viwe katika saraka moja. Ujumbe wa kosa huchapisha njia zilizojaribiwa, kama ilivyo katika the role 'common' was not found in /home/deploy/lonely/roles:/home/deploy/lonely. Kutekeleza playbook kutoka saraka kuu ni sawa, kwa sababu utafutaji hufuata njia ya playbook na si saraka ya kazi ya shell yako. Ikiwa unategemea roles_path kutoka ansible.cfg, thibitisha kuwa faili hiyo ilipakiwa na ansible --version, kwa kuwa saraka ya kazi inayoweza kuandikwa na kila mtu (world writable) huifanya Ansible kuipuuza.

Je, ninahitaji ansible-galaxy init ili kuunda role?

Hapana. Role ni saraka tu zenye majina yanayotarajiwa, kwa hivyo mkdir -p roles/common/tasks pamoja na tasks/main.yml tayari ni role inayofanya kazi. ansible-galaxy init --init-path roles common huokoa muda wa kuandika na kukupa muundo kamili, ikijumuisha meta/main.yml na sehemu ya README. Futa saraka unazoziaacha wazi, kwa sababu vars/main.yml tupu huficha ni faili zipi ndani ya role zinazofanya kazi kweli.

#ansible#roles#playbook#structure#automation