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.
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.ymltasks/main.ymlndiyo sehemu ya kuanzia. Ansible huendesha faili hili wakati role inapoitwa, na kila saraka nyingine ni ya hiari.defaults/main.ymlhuhifadhi 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.ymlhuhifadhi vigezo ambavyo anayetoa wito hatarajiwi kuvibadilisha. Kipaumbele chake kiko juu ya inventory, jambo ambalo ni la msingi sana. Itumie kwa nadra.handlers/main.ymlhuhifadhi tasks zinazoanzishwa nanotify. Handler huendeshwa mwishoni mwa play, mara moja tu, bila kujali ni tasks ngapi zimeiita.files/huhifadhi faili zinazonakiliwa kama zilivyo na module yacopy, natemplates/huhifadhi Jinja2 templates zinazotafsiriwa na module yatemplate. 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.ymlhutangaza 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 commonHii 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=localansible-playbook -i inventory.ini site.ymlPlay 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-passwordKuna 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: postIli 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.ymlkipo 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/nahost_vars/vipo katikati. Hapa ndipo majibu ya tovuti yako yanapopaswa kuwa, na yanabatilisha kwa usafi defaults za role.roles/<name>/vars/main.ymlkipo juu yahost_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-ekwenye 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-cliUendeshaji 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.ymlMuhtasari wa pili unapaswa kuonekana hivi:
PLAY RECAP *********************************************************************
localhost : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0changed=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.txtEndesha 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/lonelyUjumbe 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.ymlKuna 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.0ansible-galaxy install -r requirements.yml -p galaxy_rolesWeka 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_rolesRoles 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.