SSD Nodes Learn Hosting plans →
Mwongozo Matt ConnorNa Matt Connor · Imeboreshwa 2026-08-31

Ansible playbook dhidi ya role: ipi utumie?

Jifunze wakati mwafaka wa kuhama kutoka playbook ya faili moja kwenda kwenye muundo wa role. Tunachambua vigezo vya ukubwa wa faili, utumiaji wa ansible-galaxy na vipaumbele.

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. Huchora ramani ya kundi la hosts na kazi wanazopaswa kufanya. 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 iliyo na orodha ya tasks: ndiyo umbo sahihi kwa otomatiki yako ya kwanza, na inabaki kuwa sahihi kwa muda mrefu kuliko watu wengi wanavyotarajia. Badilisha kuwa role wakati kizuizi kilekile cha tasks kinapohitajika kuendeshwa kwa kundi la pili la hosts, au wakati faili linapozidi takriban mistari 100 na huwezi tena kupata task kwa kusogeza (scrolling).

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

Wakati playbook ya kiwango kimoja (flat) inapofaa

Playbook ya kiwango kimoja 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 kinachohitaji muundo wa saraka (directory tree). Role huongeza saraka saba na safu moja ya ziada ya kuelekeza (indirection). Ikiwa mpigaji simu pekee ni playbook iliyo karibu nayo, kuelekeza huko hakuna faida yoyote na kunakulazimisha kuruka kila wakati unapotaka kusoma kile kinachoendeshwa.

Playbook ya kiwango kimoja huacha kufaa 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 ndani ya 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 kina nguvu zaidi yake.
  • vars/main.yml huhifadhi vigezo ambavyo anayetoa wito hatarajiwi kuvibadilisha. Kipaumbele chake kiko juu ya inventory, jambo ambalo ni la msingi sana. Itumie kwa nadra.
  • handlers/main.yml huhifadhi tasks zinazoanzishwa na notify. Handler huendeshwa mwishoni mwa play, mara moja tu, bila kujali ni tasks ngapi zimeiita.
  • files/ huhifadhi faili zinazonakiliwa kama zilivyo na module ya copy, na templates/ huhifadhi Jinja2 templates zinazotafsiriwa na module ya template. Ndani ya role, unarejelea zote mbili kwa kutumia jina la faili pekee bila njia (path), kwa sababu Ansible hutafuta kwanza kwenye saraka za role yenyewe.
  • meta/main.yml hutangaza utegemezi wa role na metadata inayosomwa na Ansible Galaxy.

Mpangilio huu si suala la upendeleo wa mtindo. Ansible hutafuta kwenye 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

Hii huandika mfumo 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 katika role hiyo ambazo ni muhimu.

Sasa jaza faili zinazofanya kazi hiyo. 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 huhifadhi thamani hiyo 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 hushindwa tu wakati kitu kinapobadilisha template, ndiyo maana tatizo hili mara nyingi hujitokeza wiki kadhaa baadaye.

Mstari wa validate ndio kitu muhimu zaidi katika task hiyo. Ansible hutengeneza template kwenye faili ya muda, hubadilisha njia ya faili hiyo na %s, na kuendesha amri hiyo. Lengo hubadilishwa tu ikiwa amri itatoka na exit code 0. Weka directive isiyo na maana kwenye template na uendeshe tena: task itashindwa na failed to validate, /etc/ssh/sshd_config.d/99-hardening.conf halisi 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 hiyo hiyo, 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 ambayo role moja hutumikia 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 huzikimbiza kwa mpangilio huo bila kujali mpangilio uliouandika kwenye faili. Weka tasks: juu ya roles: na roles bado zitaanza kukimbia kwanza. Kwa hivyo ikiwa kitu lazima kitokee kabla ya role, ni lazima kiwe 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 parse na tasks zake huwa sehemu ya play, kwa hivyo ansible-playbook --list-tasks site.yml huziorodhesha na tag iliyowekwa kwenye import hutumika kwa kila task iliyo ndani. include_role ni dinamiki (dynamic). Hakuna kinachosomwa hadi task ikimbie, 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 kwenye scope. Andika when: common_packages | length > 0 kwenye include na uendeshaji utasitishwa na 'common_packages' is undefined, ingawa variable hiyo imefafanuliwa ndani ya role yenyewe unayoiingiza. Suluhisho ni kuondoa toggle hiyo nje ya role: iweke kwenye group_vars/all.yml, ambapo iko kwenye scope kila mahali, na uache defaults za role kwa ajili ya thamani ambazo role yenyewe huzitumia.

Ni kigezo kipi kinashinda: defaults, group_vars, vars, extra vars

Ansible ina viwango zaidi ya ishirini vya kipaumbele cha vigezo (variable precedence). Vinne kati ya hivyo hutatua karibu kila mjadala wa kweli, na hivi hapa ni kuanzia dhaifu hadi imara zaidi.

  • roles/<name>/defaults/main.yml kipo karibu na chini kabisa. Karibu kila kitu unachoweka mahali pengine kinakishinda, na ndiyo maana ndipo mahali sahihi pa kuweka vigezo vinavyoweza kurekebishwa vya role.
  • group_vars/ na host_vars/ vipo katikati. Hapa ndipo majibu ya tovuti yako yanapopaswa kuwa, na yanabatilisha kwa usafi defaults za role.
  • roles/<name>/vars/main.yml kipo juu ya host_vars. Thamani unayoweka hapa haiwezi kubatilishwa kutoka kwenye inventory. Kihifadhi kwa ajili ya mambo ambayo role inahitaji ili kubaki na uwiano wa ndani, kama vile jina la kifurushi (package) ambalo lazima lilingane na jina la huduma.
  • Kigezo cha role kinachopitishwa mahali pa wito (call site) kinashinda vars/main.yml, na -e kwenye mstari wa amri (command line) kinashinda kila kitu, ikiwemo vigezo vya role.

Unaweza kutazama utatuzi huu ndani ya dakika moja. Ipe role ndogo default moja na role var moja, kisha weka majina hayo hayo kwenye 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

Uendeshaji wa kwanza huchapisha tunable=from-hostvars internal=from-rolevars. Inventory ilishinda default ya role na kushindwa na role var. Uendeshaji wa pili huchapisha internal=from-cli, kwa sababu extra vars zipo juu kabisa na hakuna kitu kilicho chini kinachoweza kuzipinga. Hiyo ndiyo sababu pia -e inafaa kwa uendeshaji wa mara moja tu na si sahihi katika script unayohifadhi: inashinda kimya kimya kila uamuzi uliotafakariwa katika repository yako.

Kanuni ya kazi: kama unataka thamani iweze kubadilishwa, iweke kwenye defaults/. Kuiweka kwenye vars/ humwambia kila mtumiaji wa baadaye wa role hiyo kwamba inventory haiwezi kuibadilisha. Hilo wakati mwingine ndilo uliokusudia, na mara nyingi huwa ni bahati mbaya.

Thibitisha kuwa role ni idempotent: iendeshe mara mbili

Ansible inayotegemeka hutoa matokeo yaleyale katika mara ya pili na kuripoti kuwa haikubadilisha chochote. 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 kazi imeshakamilika. changed=2 katika uendeshaji wa pili inamaanisha kuna tasks mbili ambazo haziwezi kutofautisha hali, hivyo zitaendelea kuandika upya faili na kuanzisha upya huduma milele. Sababu ya kawaida ni command au shell, kwa sababu Ansible haina njia ya kujua kile ambacho 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 uendeshaji wa pili, task iliyolindwa haikutekelezwa kabisa, na matokeo yake yana ujumbe skipped, since /tmp/guarded.txt exists, kwa sababu creates huipa moduli bidhaa inayoonekana ya kutafuta kwanza. Amri inaposhindwa kuacha bidhaa kama hiyo, sajili matokeo yake 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 bado unaweza kuficha kazi inayofanyika.

Safu nyingine katika muhtasari huo inastahili uangalifu uleule: host ambayo Ansible haikuweza kuunganishwa nayo huhesabiwa chini ya unreachable badala ya failed na hakuna hata task moja yake iliyotekelezwa, kwa hivyo amua mapema ikiwa host moja isiyoweza kufikika inapaswa kusimamisha uendeshaji mzima kabla ya kuelekeza role hii kwenye mashine zaidi ya mbili.

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/ zimepishana, 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 jinsi unavyoendesha kazi zako.

[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 huwa haipo kimyakimya, na utafutaji wa role hushindwa kwa sababu isiyo na uhusiano wowote na role. 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 unapoona uendeshaji unafanya kazi kana kwamba usanidi wako haupo.

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

Role iliyoandikwa na mtu mwingine inapaswa kusakinishwa, si kunakiliwa. Ieleze 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 default branch siku unayotekeleza amri hiyo, hivyo deployment iliyofanya kazi mwezi uliopita inaweza kufeli bila mabadiliko yoyote kwenye repository yako. Elekeza roles_path kwenye saraka ya kupakua (download directory), 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 zitapatikana, kwa sababu njia hiyo hutafutwa kila wakati pamoja na roles_path. Hivyo, roles zako mwenyewe hubaki zikiwa zimefanyiwa commit na kukaguliwa, wakati roles za watu wengine ni vipakuliwa vinavyoweza kurudiwa (reproducible) na vilivyofungwa kwenye tag mahususi.

Wakati ambapo roles hazitoshi tena

Role ni kitengo cha matumizi ya mara kwa mara ndani ya operesheni moja ya Ansible. Haiwezi kutengeneza seva au DNS records kwa mtoa huduma wako, na kujaribu kuilazimisha kufanya hivyo ndiyo njia inayofanya playbooks kuwa kitu ambacho hakuna mtu anayetaka kukitunza. mgawanyo wa kazi kati ya Ansible na Terraform inafaa kusomwa kabla ya kuanza. Vilevile, role haichukui nafasi ya usanifu wa inventory: pindi unapovuka idadi ndogo ya mashine, jinsi unavyopanga na kufikia seva hizo ni muhimu zaidi kuliko jinsi tasks zilivyohifadhiwa.

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

FAQ

Ni wakati gani ninapaswa kubadilisha Ansible playbook kuwa role?

Wakati kundi lilelile la tasks linapohitajika kufanya kazi 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 hufanya kazi kabla ya tasks katika play ileile?

Ndiyo. Ansible huendesha 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 zianze kufanya kazi kwanza. Ikiwa kitu lazima kitokee kabla ya role, kiweke ndani ya pre_tasks:.

Kwa nini thamani yangu ya group_vars haibatilishi role?

Angalia ikiwa 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 mpigaji anapaswa kuwa na uwezo wa kukibadilisha. Ili kuthibitisha kuwa kipaumbele ndiyo sababu badala ya kosa la uchapaji, endesha mara moja ukitumia -e name=value, ambayo inashinda kila chanzo kingine.

Kwa nini Ansible inasema role haikupatikana?

Utafutaji huanza karibu na faili ya playbook, kwa hivyo site.yml na roles/ lazima viwe katika saraka moja. Hitilafu huchapisha njia ilizojaribu, kama ilivyo katika the role 'common' was not found in /home/deploy/lonely/roles:/home/deploy/lonely. Kuendesha playbook kutoka saraka kuu ni sawa, kwa sababu utafutaji hufuata njia ya playbook na si saraka ya sasa ya shell yako. Ikiwa unategemea roles_path kutoka ansible.cfg, thibitisha kuwa faili hiyo ilipakiwa na ansible --version, kwa sababu saraka ya kazi inayoweza kuandikwa na kila mtu 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 README ya awali. 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