Jinsi ya kuandika playbook yako ya kwanza ya Ansible
Sakinisha Ansible kwa pipx kwenye Ubuntu 24.04, andika inventory na playbook ya kuimarisha VPS, kisha rekebisha "Permission denied" na hitilafu za sudo.
Unachojenga
Mashine moja ya udhibiti yenye Ansible iliyosakinishwa, pamoja na VPS moja au zaidi mpya za Ubuntu 24.04 ambazo zina image ya kawaida pekee. Mwishoni utakuwa na inventory file inayotaja seva zako, ping ya ad-hoc inayothibitisha kuwa authentication inafanya kazi kutoka mwisho mmoja hadi mwingine, na playbook inayotekeleza checklist nzima ya VPS mpya kama code: mtumiaji wa deploy mwenye SSH key yako, sshd iliyoimarishwa kiusalama, fail2ban, masasisho yasiyohitaji uingiliaji, na firewall inayoruhusu OpenSSH kabla ya kukataa kila kitu kingine. Ielekeze kwenye seva moja au ishirini. Iendeshe mara mbili; mara ya pili haitabadilisha chochote. Hilo ndilo lengo kuu.
Baada ya miaka kumi na tano ya kuandaa VPS, naweza kusema utaratibu halisi ni huu: kila mtu huandaa seva tano za kwanza mwenyewe, kisha hupoteza wikendi kwenye seva ya sita kwa sababu hakuna anayekumbuka walichofanya kwenye seva tano za kwanza. Mwongozo huu unapanua uchunguzi katika kusimamia seva nyingi za Linux; ufuate mara tu unapojikuta ukiandika apt install ileile kwenye terminal tatu.
Ansible ni nini hasa, kwa aya moja
Ansible haina agent. Hakuna daemon ya kusakinisha kwenye seva inazozisimamia: mashine ya udhibiti huunganisha kupitia SSH ya kawaida, hunakili Python module ndogo kwenye target, huiendesha, husoma JSON inayochapisha, kisha huifuta. Kitu pekee kinachohitaji target ni python3, ambacho kila Ubuntu image ya kawaida huwa nacho tayari. Neno muhimu ni idempotent, na maana yake ni rahisi: task hueleza state, si kitendo. state: present kwa package humaanisha “hakikisha hii imesakinishwa”, si “endesha installer”. Ikiwa state hiyo tayari ipo, Ansible haibadili chochote na huripoti kama ok badala ya changed. Sifa hiyo ndiyo msingi wa bidhaa nzima, ndiyo inayofanya kuendesha playbook tena kuwe salama, na uendeshaji salama wa mara kwa mara ndio unaobadilisha shell script kuwa infrastructure.
Mahitaji ya awali na mambo muhimu ya kuzingatia
- Mashine ya kudhibiti: laptop yako au VPS ndogo. Ninachukulia kuwa unatumia Ubuntu 24.04; macOS hufanya kazi vivyo hivyo baada ya kusakinisha pipx kupitia Homebrew.
- VPS moja au zaidi zinazolengwa, zinazoendesha Ubuntu 24.04 kwenye KVM na zinazofikika ukiwa root. Hakuna kitu kitakachosakinishwa kwenye VPS hizo.
- Uthibitishaji wa SSH kwa kutumia key kwenye kila target. Ansible hutumia kiwango kilekile cha uthibitishaji kinachotumiwa na amri yako ya
ssh. Ikiwassh root@hostitaomba password, Ansible itashindwa. - Kwenye Ubuntu 24.04,
pip install ansiblehushindwa kwaerror: externally-managed-environment. Hii ni sera ya distro iliyowekwa kwa makusudi, si hitilafu. Tumia pipx. - Nafasi tupu za YAML ni sehemu ya syntax. Indent isiyo sahihi huzalisha
mapping values are not allowed in this context, na tab character popote husababisha hitilafu. - Weka SSH session inayofanya kazi wazi kwenye kila target wakati playbook inaimarisha usalama wa sshd. Kila lockout ambayo nimewasaidia wateja kurekebisha ilihusisha kufunga session ya mwisho “ili kujaribu kutoka kwenye mazingira safi”.
Hatua ya 1: sakinisha Ansible kwenye mashine ya udhibiti kwa kutumia pipx, si pip
Msukumo wa kawaida ni pip3 install ansible. Kwenye image mpya kabisa ya 24.04, hilo hushindikana hatua moja mapema, Command 'pip3' not found, but can be installed with: sudo apt install python3-pip, na kusakinisha pip hukufikisha tu kwenye kizuizi halisi:
pip3 install ansibleerror: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
python3-xyz, where xyz is the package you are trying to
install.Ubuntu 24.04 huweka Python ya mfumo kama inayosimamiwa nje (PEP 668), kwa hiyo pip haiwezi kushindana na apt kuhusu faili zilezile. Usitumie --break-system-packages; jina la flag hiyo linaeleza kazi yake wazi. Jibu salama ni pipx, ambayo huipa Ansible virtualenv yake iliyotengwa na kuweka binaries kwenye PATH yako:
sudo apt update && sudo apt install -y pipx
pipx ensurepath
pipx install --include-deps ansibleFungua shell mpya baada ya pipx ensurepath ili mabadiliko ya PATH yaanze kutumika. --include-deps si mapambo: package ya ansible haina console scripts zake, ansible, ansible-playbook, na nyingine ni entry points za dependency yake ya ansible-core, kwa hiyo bila flag hiyo pipx hukataa usakinishaji kwa No apps associated with package ansible or its dependencies. Pia sakinisha package ya ansible, si ansible-core tupu; package kamili hujumuisha community collections, na playbook hii hutumia modules kutoka mawili kati yake (ansible.posix na community.general).
ansible --versionMatokeo sahihi huanza na mstari kama ansible [core 2.19.x] na hutaja Python inayotumika kuiendesha; release yoyote ya sasa ya core inatosha kwa kila kitu hapa. ansible: command not found badala yake humaanisha kuwa ~/.local/bin bado haipo kwenye PATH yako; fungua shell mpya, au tumia source ~/.bashrc.
Huo ndio usakinishaji wote. Target hazipati chochote.
Hatua ya 2: Ufikiaji wa kila lengwa kwa kutumia SSH key
ssh-keygen -t ed25519 -C "ansible control"
ssh-copy-id root@10.0.0.10
ssh-copy-id root@10.0.0.20Kisha ithibitishe, mara moja kwa kila host:
ssh root@10.0.0.10 true && echo okMstari huo mmoja hufanya kazi mbili: unathibitisha kuwa key authentication inafanya kazi bila password, na unarekodi host key katika known_hosts. Fanya hivyo sasa, kwa sababu Ansible huonyesha host key ambayo haijarekodiwa kama kidokezo cha mwingiliano kilichofichika katikati ya mchakato wa kuendesha, jambo linalofanana kabisa na mfumo kuganda.
Hatua ya 3: inventory, anza na INI, tumia YAML inapokua
Inventory ni faili la maandishi linaloorodhesha mashine ambazo Ansible inaweza kufanyia kazi. Unda inventory.ini katika saraka mpya ya mradi:
[vps]
web1 ansible_host=10.0.0.10
web2 ansible_host=10.0.0.20
[vps:vars]
ansible_user=rootweb1 ni jina mbadala unalochagua. Jina hilo huonekana kwenye matokeo na ndilo unalolenga kwa --limit web1. ansible_host ni anwani halisi. [vps] ni group, na [vps:vars] huweka variables kwa kila host iliyo ndani yake; ansible_user ni mtumiaji ambaye Ansible huingia naye. Karibu nayo, weka ansible.cfg ili usiandike tena -i:
[defaults]
inventory = inventory.iniAnsible husoma ansible.cfg kutoka kwenye saraka ya sasa. Inventory hiyo hiyo ikiwa katika YAML, ihifadhi kama inventory.yml na uelekeze ansible.cfg kwenye jina hilo badala yake. Hii ndiyo utakayopendelea hosts zinapokuwa na variables kadhaa kila mmoja:
vps:
hosts:
web1:
ansible_host: 10.0.0.10
web2:
ansible_host: 10.0.0.20
vars:
ansible_user: rootZinafanya kazi sawa. INI ni rahisi kukagua kwa macho ukiwa na servers mbili; YAML hubadilika kwa urahisi zaidi ukiwa na servers ishirini. Chagua moja kisha usijishughulishe tena na suala hilo.
Hatua ya 4: amri za ad-hoc, pong ya kijani inayothibitisha kila kitu
ansible all -m pingHii si ICMP. Moduli ya ping ni jaribio kamili linalopitia hatua zote: kuingia kwa SSH, kunakili moduli, kutekeleza Python kwenye target, na kufanya cleanup. Matokeo sahihi ni ya kijani, yakiwa na block moja kwa kila host:
web1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}SUCCESS ya kijani inamaanisha authentication, Python interpreter na transport vinafanya kazi; playbook pia itafanya kazi. UNREACHABLE! ya nyekundu inamaanisha transport ilishindwa kabla ya moduli yoyote kuendeshwa. String halisi na suluhisho vimeelezwa katika sehemu ya failure modes hapa chini. Amri mbili zaidi za ad-hoc unazopaswa kujua:
ansible all -a "uptime"
ansible all -m apt -a "update_cache=true upgrade=dist" --becomeAd-hoc ni kwa kazi za mara moja na ukaguzi. Kitu chochote ambacho ungeendesha mara mbili kinapaswa kuwa kwenye playbook.
Hatua ya 5: playbook ya kwanza, checklist ya VPS mpya kama msimbo
Haya ndiyo yote ambayo ungefanya kwa mkono katika dakika kumi za kwanza kwenye seva mpya. Ihifadhi kama site.yml:
---
- name: Baseline a fresh Ubuntu VPS
hosts: vps
become: true
vars:
deploy_user: deploy
deploy_pubkey: "{{ lookup('file', '~/.ssh/id_ed25519.pub') }}"
baseline_packages:
- fail2ban
- unattended-upgrades
- ufw
baseline_services:
- fail2ban
- unattended-upgrades
tasks:
- name: Create the deploy user
ansible.builtin.user:
name: "{{ deploy_user }}"
groups: sudo
append: true
shell: /bin/bash
- name: Install the deploy user's SSH key
ansible.posix.authorized_key:
user: "{{ deploy_user }}"
key: "{{ deploy_pubkey }}"
- name: Passwordless sudo for the deploy user
ansible.builtin.copy:
dest: /etc/sudoers.d/deploy
content: "{{ deploy_user }} ALL=(ALL) NOPASSWD:ALL\n"
mode: "0440"
validate: /usr/sbin/visudo -cf %s
- name: Install baseline packages
ansible.builtin.apt:
name: "{{ baseline_packages }}"
state: present
update_cache: true
- name: Enable and start baseline services
ansible.builtin.service:
name: "{{ item }}"
state: started
enabled: true
loop: "{{ baseline_services }}"
- name: Harden sshd with a drop-in
ansible.builtin.copy:
dest: /etc/ssh/sshd_config.d/00-hardening.conf
content: |
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
X11Forwarding no
mode: "0644"
validate: /usr/sbin/sshd -t -f %s
notify: Restart ssh
- name: Allow OpenSSH through ufw
community.general.ufw:
rule: allow
name: OpenSSH
- name: Enable ufw with default deny
community.general.ufw:
state: enabled
policy: deny
handlers:
- name: Restart ssh
ansible.builtin.service:
name: ssh
state: restartedMistari inayofaa kuelewa badala ya kunakili:
Vigezo viko chini ya vars: na vinarejelewa kwa "{{ deploy_user }}". Weka usemi mzima ndani ya alama za kunukuu thamani inapoanza na mabano yaliyopinda, la sivyo kichanganua cha YAML kitausoma kimakosa. lookup('file', ...) husoma key yako ya umma kutoka kwenye mashine ya control wakati wa utekelezaji, kwa hiyo playbook haina nyenzo za key.
Kitanzi. loop: "{{ baseline_services }}" huendesha task ya huduma mara moja kwa kila kipengee, na matokeo huonyesha kila kipengee kwenye mstari wake. Kumbuka kuwa task ya apt hupokea orodha nzima ya packages kwa wakati mmoja. Transaction moja ya apt ni ya haraka zaidi, na ndiyo njia inayopendekezwa kwa packages. Tumia loops kwa modules zinazofanya kazi kwenye kipengee kimoja tu kwa wakati mmoja.
Handler ndiyo dhana ya kuielewa kikamilifu. notify: Restart ssh haimaanishi "restart ssh sasa". Huongeza handler kwenye foleni. Handler huendeshwa mara moja mwishoni mwa play, na ikiwa tu task iliyoiarifu iliripoti changed. Ukiendesha playbook tena kesho, drop-in file itakuwa tayari sahihi, task ya copy itaripoti ok, na sshd haitaanzishwa upya. Mstari wa validate: ni ulinzi wa trigger. sshd hukagua file kabla ya kubadilisha ya zamani, kwa hiyo typo husababisha task kushindwa badala ya kuvuruga daemon.
PermitRootLogin prohibit-password, si no, kimakusudi. Playbook hii huingia kama root kwa kutumia key. prohibit-password huzima kuingia kwa root kwa password huku ikiendelea kuruhusu muunganisho wako. Baada ya kuthibitisha deploy user (ssh deploy@10.0.0.10 sudo true, anwani halisi, kwa kuwa web1 ni alias inayojulikana na Ansible pekee), badilisha ansible_user=deploy kwenye inventory na uikaze kuwa no katika utekelezaji wa baadaye. Fanya hardening kwa mpangilio ambao hauwezi kukufungia nje.
Kiambishi cha 00- ni muhimu. Kwa keywords nyingi, sshd hutumia tukio la kwanza inalolichanganua. Ubuntu's sshd_config hujumuisha sshd_config.d/*.conf kwa mpangilio wa kilaksika kabla ya body yake yenyewe. Cloud images za Ubuntu 24.04 tayari huwa na 60-cloudimg-settings.conf kwenye directory hiyo, na providers wanaowezesha password logins kupitia cloud-init huongeza 50-cloud-init.conf yenye PasswordAuthentication yes. Kukiita chetu 00-hardening.conf kunakifanya kipangwe kwanza na kitawale vyote viwili.
Mpangilio wa tasks ndiyo usalama wa firewall. Allow OpenSSH huendeshwa kabla ya Enable ufw yenye sera ya deny. Ansible hutekeleza tasks kwa mpangilio uleule ulioorodheshwa, kwa hiyo mwanya huwa wazi kabla ya ukuta kuwekwa. fail2ban haihitaji configuration ili iwe na manufaa hapa. Defaults zake za Ubuntu hu-monitor sshd moja kwa moja, na kinachofanywa na jails pamoja na mambo ya kurekebisha kimeelezwa kwenye mwongozo wa fail2ban kwenye Ubuntu 24.04.
Hatua ya 6: fanya dry run kwa kutumia --check, kisha iendeshe kikamilifu
ansible-playbook site.yml --checkHali ya check huunganisha, huhesabu kitakachofanyika, na haibadilishi chochote. Soma hesabu ya changed= kwenye PLAY RECAP iliyo chini. Hiyo ndiyo idadi ya tasks ambazo zingebadilisha kila host. Kuna tahadhari moja muhimu: hali ya check ina kikomo cha kimuundo pale task ya baadaye inapohitaji mabadiliko yaliyofanywa na task ya awali. Ubuntu's standard server image huja ikiwa na ufw tayari, kwa hiyo playbook hii hufanya dry run bila hitilafu. Hata hivyo, kwenye image ndogo isiyo na ufw, tasks za ufw hushindwa katika hali ya check kwa sababu hali ya check haisakinishi package hiyo. Kwa hiyo module haina kitu cha kuita. Hiki ni kikomo cha dry run, si hitilafu kwenye playbook yako. Mpango unapoonekana kuwa sahihi:
ansible-playbook site.ymlKila task huchapisha mstari mmoja kwa kila host: changed ya njano, ok ya kijani, na recap inapaswa kusomeka hivi:
PLAY RECAP *********************************************************************
web1 : ok=10 changed=9 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
web2 : ok=10 changed=9 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0Hizi ok ni fact-gathering pamoja na tasks nane na handler. changed yako inaruhusiwa kutofautiana na yangu kwa moja au mbili. Ubuntu's standard image huja ikiwa na ufw na unattended-upgrades tayari, na fail2ban huanza yenyewe mara tu apt inapoisakinisha. Kwa hiyo task inaweza kuripoti kihalali ok katika uendeshaji wake wa kwanza kabisa, kwa sababu hali iliyotangazwa tayari ilikuwa imekuwapo. Hesabu zinazopaswa kuwa sifuri ni unreachable na failed. Kuhusu become: true, hiyo ni taratibu tu unapoingia kama root. Lakini mara tu unapobadilisha ansible_user kuwa deploy, sudo huwa inatumika kweli. Faili ya sudoers yenye NOPASSWD ambayo playbook hii husakinisha ndiyo inayozuia -K kuonekana kwenye command line yako. Bila faili hiyo utapata Missing sudo password, kama ilivyoelezwa hapa chini.
Hatua ya 7: iendeshe mara mbili, hivi ndivyo idempotence inavyoonekana
Tekeleza amri hiyo hiyo tena mara moja:
web1 : ok=9 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0changed=0 na ok zilipungua kwa moja kwa sababu handler ambayo haikupewa taarifa haikuendeshwa. Hakuna kitu kilichosakinishwa tena, sshd haikuwashwa upya, na ufw haikuguswa. Hiki ndicho kinachofanya playbook iwe audit pamoja na provisioner: ongeza web3 kwenye inventory mwezi ujao na utekeleze tena; box mpya itajengwa, na box za zamani zitathibitishwa. changed isiyo sifuri kwenye box ambayo hujaigusa ni drift. Hii inaonyesha kuwa mtu alihariri kwa mkono kitu ambacho kilipaswa kuhaririwa kwenye playbook.
Kuanzia hapa, muundo huu huendelea kupanuka. Playbook inayofuata inayofaa kuandikwa inaweza kusanidi WireGuard VPN kwenye VPS hiyo hiyo na kukaza rule ya ufw ili SSH ijibu kupitia tunnel pekee. Baada ya hapo, andika playbook inayosakinisha Docker na Compose kwenye kila app server. site.yml ikizidi skrini tatu, igawanye katika roles, lakini usifanye hivyo kabla ya hapo.
Njia za kushindwa, pamoja na mistari utakayoona
UNREACHABLE with Permission denied.
web1 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: root@10.0.0.10: Permission denied (publickey).",
"unreachable": true
}Usafirishaji wa SSH ulishindwa kabla ya module yoyote kuendeshwa: ansible_user si sahihi, key haikuwahi kunakiliwa kwenye host hiyo, au key isiyo sahihi inatolewa. Rudia kwa ssh root@10.0.0.10 ya kawaida, kisha tumia ssh -v kuona ni keys zipi zilitolewa. Ikiwa SSH ya password inafanya kazi lakini Ansible haifanyi kazi, uliruka ssh-copy-id.
Missing sudo password.
web1 | FAILED! => {
"msg": "Missing sudo password"
}Uliweka become: true, ukaunganisha ukiwa mtumiaji asiye root, na mtumiaji huyo anahitaji password kwa sudo. Ama ongeza -K (--ask-become-pass) kwenye command line, au mpe mtumiaji huyo ingizo la NOPASSWD katika sudoers. Hii ndiyo sababu playbook husakinisha moja kwa deploy kabla hujawahi kubadili na kuitumia.
error: externally-managed-environment. Uliendesha pip dhidi ya Python ya mfumo kwenye Ubuntu 24.04. Hili limeelezwa katika hatua ya 1: tumia pipx, si pip, na si --break-system-packages.
mapping values are not allowed in this context.
ERROR! Syntax Error while loading YAML.
mapping values are not allowed in this contextKaribu kila mara tatizo ni indentation: key iko kwenye kina kisicho sahihi, au hakuna space baada ya colon. Namba ya mstari iliyoripotiwa huonyesha eneo lililo karibu na kosa, si lazima mstari wenye kosa. Kagua pia mstari ulio juu yake. Kosa linalofanana, found character '\t' that cannot start any token, linamaanisha tab imeingia kwenye faili; YAML hairuhusu tab. Fanya ansible-playbook site.yml --syntax-check kuwa hatua ya kawaida kabla ya kila run, na weka editor yako itumie indentation ya space mbili kwa YAML.
/usr/bin/python3: not found. Hili ni nadra kwenye images za kawaida za Ubuntu 24.04, lakini ni la kawaida kwenye images ndogo au za netboot. Uendeshaji wa module hushindwa kwa sababu target haina Python. Isakinishe kwa module ya raw, ambayo ndiyo module pekee isiyohitaji kitu upande wa mbali: ansible all -m raw -a "apt-get update && apt-get install -y python3" --become, kisha endesha playbook tena.
FAQ
Je, ninahitaji kusakinisha Ansible kwenye seva inazozisimamia?
Hapana. Ansible haina agent: mashine ya udhibiti hutuma modules ndogo za Python kupitia SSH, huzitekeleza, kisha huziondoa. Mfumo lengwa unahitaji python3 na ufikiaji wa SSH pekee; Ubuntu images za kawaida tayari vina vitu hivyo. Usakinishaji pekee katika mwongozo huu wote unafanyika kwenye mashine yako ya udhibiti.
Kwa nini Ansible inasema "Permission denied (publickey)"?
Kizuizi cha UNREACHABLE! chenye Permission denied (publickey) kinamaanisha uthibitishaji wa SSH umeshindwa kabla Ansible haijatekeleza chochote. Hakikisha ansible_user kwenye inventory inalingana na account uliyosanidi, kwamba uliendesha ssh-copy-id kwenda kwenye host hiyo, na kwamba ssh user@host ya kawaida inaingia bila password. Marekebisho yoyote ya command ya kawaida ya ssh yatatengeneza Ansible pia, kwa sababu zote zinatumia transport ileile.
Idempotent inamaanisha nini katika Ansible?
Task hutangaza hali inayotakiwa, kama "package hii ipo" au "mstari huu umo kwenye file hili", badala ya kutangaza action ya kufanya. Ikiwa hali hiyo tayari ipo, Ansible haifanyi chochote na huripoti ok badala ya changed. Ndiyo maana kuendesha playbook mara mbili huonyesha changed=0 mara ya pili, na kwa nini kuiendesha tena ni ukaguzi salama badala ya usakinishaji upya wenye hatari.
Je, nitumie pip au pipx kusakinisha Ansible kwenye Ubuntu 24.04?
pipx. Ubuntu 24.04 huweka mfumo wa Python kuwa unaosimamiwa nje, kwa hiyo pip install ansible hushindwa kwa error: externally-managed-environment kimakusudi. pipx install --include-deps ansible huweka Ansible kwenye virtualenv iliyotengwa na huweka ansible, ansible-playbook na vingine kwenye PATH yako kwa usafi.
Kuna tofauti gani kati ya packages za ansible na ansible-core?
ansible-core ni engine pamoja na modules za ansible.builtin pekee. Package ya ansible hujumuisha core pamoja na community collections zilizochaguliwa, ikiwemo ansible.posix (module ya authorized_key) na community.general (module ya ufw), ambazo zote zinatumika katika mwongozo huu. Anza na package kamili; punguza hadi core pamoja na collections ulizochagua mwenyewe tu unapokuwa na sababu ya kufanya hivyo.