Jo shumë kohë më parë më duhej të shkruaja disa libra lojërash Ansible për të përgatitur serverin për vendosjen e një aplikacioni Rails. Dhe, çuditërisht, nuk gjeta një manual të thjeshtë hap pas hapi. Nuk doja të kopjoja librin e lojërave të dikujt tjetër pa kuptuar se çfarë po ndodhte dhe në fund më duhej të lexoja dokumentacionin, duke mbledhur gjithçka vetë. Ndoshta mund të ndihmoj dikë që ta përshpejtojë këtë proces me ndihmën e këtij artikulli.
Gjëja e parë që duhet kuptuar është se ansible ju ofron një ndërfaqe të përshtatshme për të kryer një listë të paracaktuar veprimesh në një server(ët) në distancë nëpërmjet SSH. Nuk ka magji këtu, ju nuk mund të instaloni një shtojcë dhe të merrni një vendosje zero joproduktive të aplikacionit tuaj me docker, monitorim dhe të mira të tjera jashtë kutisë. Për të shkruar një libër lojërash, duhet të dini se çfarë saktësisht dëshironi të bëni dhe si ta bëni atë. Kjo është arsyeja pse unë nuk jam i kënaqur me libra të gatshëm të lojës nga GitHub, ose artikuj si: "Kopjo dhe ekzekuto, do të funksionojë".
Çfarë na nevojitet?
Siç thashë tashmë, për të shkruar një libër lojërash, duhet të dini se çfarë doni të bëni dhe si ta bëni atë. Le të vendosim se çfarë na nevojitet. Për një aplikacion Rails do të na duhen disa paketa sistemore: nginx, postgresql (redis, etj). Përveç kësaj, ne kemi nevojë për një version specifik të rubinit. Më së miri është ta instaloni nëpërmjet rbenv (rvm, asdf...). Drejtimi i gjithë kësaj si përdorues rrënjë është gjithmonë një ide e keqe, kështu që ju duhet të krijoni një përdorues të veçantë dhe të konfiguroni të drejtat e tij. Pas kësaj, ju duhet të ngarkoni kodin tonë në server, të kopjoni konfigurimet për nginx, postgres, etj dhe të filloni të gjitha këto shërbime.
Si rezultat, sekuenca e veprimeve është si më poshtë:
- Identifikohu si rrënjë
- instaloni paketat e sistemit
- krijoni një përdorues të ri, konfiguroni të drejtat, çelësin ssh
- konfiguroni paketat e sistemit (nginx etj) dhe ekzekutoni ato
- Ne krijojmë një përdorues në bazën e të dhënave (ju mund të krijoni menjëherë një bazë të dhënash)
- Hyni si përdorues i ri
- Instaloni rbenv dhe rubin
- Instalimi i paketës
- Ngarkimi i kodit të aplikacionit
- Nisja e serverit Puma
Për më tepër, fazat e fundit mund të kryhen duke përdorur capistrano, të paktën jashtë kutisë mund të kopjojë kodin në drejtoritë e lëshimit, të ndërrojë lëshimin me një lidhje simbolike pas vendosjes së suksesshme, të kopjojë konfigurimet nga një direktori e përbashkët, të rifillojë pumën, etj. E gjithë kjo mund të bëhet duke përdorur Ansible, por pse?
Struktura e skedarit
Ansible ka strikte
Libër lojërash i thjeshtë
Playbook është një skedar yml që, duke përdorur sintaksë të veçantë, përshkruan se çfarë duhet të bëjë Ansible dhe si. Le të krijojmë librin e parë të lojërave që nuk bën asgjë:
---
- name: Simple playbook
hosts: all
Këtu thjesht themi se libri ynë i lojërave quhet Simple Playbook
dhe se përmbajtja e tij duhet të ekzekutohet për të gjithë hostet. Mund ta ruajmë në drejtorinë /ansible me emrin playbook.yml
dhe përpiquni të vraponi:
ansible-playbook ./playbook.yml
PLAY [Simple Playbook] ************************************************************************************************************************************
skipping: no hosts matched
Ansible thotë se nuk njeh asnjë host që përputhet me listën e të gjithëve. Ato duhet të renditen në një të veçantë
Le ta krijojmë atë në të njëjtën direktori ansible:
123.123.123.123
Kjo është mënyra se si ne thjesht specifikojmë hostin (në mënyrë ideale hostin e VPS-së tonë për testim, ose ju mund të regjistroni localhost) dhe e ruajmë atë nën emrin inventory
.
Mund të provoni të ekzekutoni ansible me një skedar inventar:
ansible-playbook ./playbook.yml -i inventory
PLAY [Simple Playbook] ************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************
PLAY RECAP ************************************************************************************************************************************
Nëse keni akses ssh në hostin e specifikuar, atëherë ansible do të lidhet dhe do të mbledhë informacione rreth sistemit në distancë. (DETYRA e parazgjedhur [Mbledhja e fakteve]) pas së cilës do të japë një raport të shkurtër mbi ekzekutimin (PLAY RECAP).
Si parazgjedhje, lidhja përdor emrin e përdoruesit me të cilin jeni regjistruar në sistem. Me shumë mundësi nuk do të jetë në host. Në skedarin e librit të luajtjes, mund të specifikoni cilin përdorues të përdorni për t'u lidhur duke përdorur direktivën remote_user. Gjithashtu, informacioni në lidhje me një sistem në distancë shpesh mund të jetë i panevojshëm për ju dhe nuk duhet të humbni kohë për ta mbledhur atë. Kjo detyrë gjithashtu mund të çaktivizohet:
---
- name: Simple playbook
hosts: all
remote_user: root
become: true
gather_facts: no
Provoni të ekzekutoni përsëri librin e luajtjes dhe sigurohuni që lidhja të funksionojë. (Nëse keni specifikuar përdoruesin rrënjë, atëherë duhet të specifikoni edhe direktivën e bërë: e vërtetë për të fituar të drejta të larta. Siç shkruhet në dokumentacion: become set to ‘true’/’yes’ to activate privilege escalation.
edhe pse nuk është plotësisht e qartë pse).
Ndoshta do të merrni një gabim të shkaktuar nga fakti se ansible nuk mund të përcaktojë interpretuesin Python, atëherë mund ta specifikoni manualisht:
ansible_python_interpreter: /usr/bin/python3
Mund të zbuloni se ku keni python me komandën whereis python
.
Instalimi i paketave të sistemit
Shpërndarja standarde e Ansible përfshin shumë module për të punuar me paketa të ndryshme të sistemit, kështu që nuk kemi nevojë të shkruajmë skriptet bash për asnjë arsye. Tani na duhet një nga këto module për të përditësuar sistemin dhe instaluar paketat e sistemit. Unë kam Ubuntu Linux në VPS-në time, kështu që për të instaluar paketat përdor apt-get
и
Le të plotësojmë librin tonë të lojërave me detyrat e para:
---
- name: Simple playbook
hosts: all
remote_user: root
become: true
gather_facts: no
tasks:
- name: Update system
apt: update_cache=yes
- name: Install system dependencies
apt:
name: git,nginx,redis,postgresql,postgresql-contrib
state: present
Task është pikërisht detyra që Ansible do të kryejë në serverët në distancë. Ne i japim detyrës një emër në mënyrë që të mund të gjurmojmë ekzekutimin e saj në regjistër. Dhe ne përshkruajmë, duke përdorur sintaksën e një moduli specifik, atë që duhet të bëjë. Në këtë rast apt: update_cache=yes
- thotë për të përditësuar paketat e sistemit duke përdorur modulin apt. Komanda e dytë është pak më e ndërlikuar. Ne kalojmë një listë të paketave në modulin apt dhe themi se janë state
duhet të bëhet present
, domethënë themi instaloni këto paketa. Në mënyrë të ngjashme, ne mund t'u themi që t'i fshijnë ato, ose t'i përditësojnë ato thjesht duke i ndryshuar state
. Ju lutemi vini re se që binarët të punojnë me postgresql ne kemi nevojë për paketën postgresql-contrib, të cilën po e instalojmë tani. Përsëri, ju duhet ta dini dhe ta bëni këtë; insible në vetvete nuk do ta bëjë këtë.
Provoni të ekzekutoni përsëri librin e luajtjes dhe kontrolloni nëse paketat janë të instaluara.
Krijimi i përdoruesve të rinj.
Për të punuar me përdoruesit, Ansible ka gjithashtu një modul - përdorues. Le të shtojmë një detyrë tjetër (kam fshehur pjesët tashmë të njohura të librit të lojërave pas komenteve në mënyrë që të mos e kopjoj plotësisht çdo herë):
---
- name: Simple playbook
# ...
tasks:
# ...
- name: Add a new user
user:
name: my_user
shell: /bin/bash
password: "{{ 123qweasd | password_hash('sha512') }}"
Ne krijojmë një përdorues të ri, vendosim një skemë dhe fjalëkalim për të. Dhe pastaj hasim në disa probleme. Po sikur emrat e përdoruesve të jenë të ndryshëm për hoste të ndryshëm? Dhe ruajtja e fjalëkalimit në tekst të qartë në librin e lojërave është një ide shumë e keqe. Për të filluar, le të vendosim emrin e përdoruesit dhe fjalëkalimin në variabla, dhe në fund të artikullit do të tregoj se si të kriptohet fjalëkalimi.
---
- name: Simple playbook
# ...
tasks:
# ...
- name: Add a new user
user:
name: "{{ user }}"
shell: /bin/bash
password: "{{ user_password | password_hash('sha512') }}"
Variablat vendosen në librat e lojërave duke përdorur kllapa të dyfishtë kaçurrelë.
Ne do të tregojmë vlerat e variablave në skedarin e inventarit:
123.123.123.123
[all:vars]
user=my_user
user_password=123qweasd
Ju lutemi vini re direktivën [all:vars]
- thotë se blloku tjetër i tekstit është variablat (vars) dhe ato janë të zbatueshme për të gjithë hostet (të gjithë).
Dizajni është gjithashtu interesant "{{ user_password | password_hash('sha512') }}"
. Puna është se ansible nuk e instalon përdoruesin nëpërmjet user_add
siç do ta bënit me dorë. Dhe i ruan të gjitha të dhënat drejtpërdrejt, kjo është arsyeja pse ne gjithashtu duhet ta kthejmë fjalëkalimin në një hash paraprakisht, gjë që bën kjo komandë.
Le të shtojmë përdoruesin tonë në grupin sudo. Megjithatë, para kësaj ne duhet të sigurohemi që një grup i tillë ekziston sepse askush nuk do ta bëjë këtë për ne:
---
- name: Simple playbook
# ...
tasks:
# ...
- name: Ensure a 'sudo' group
group:
name: sudo
state: present
- name: Add a new user
user:
name: "{{ user }}"
shell: /bin/bash
password: "{{ user_password | password_hash('sha512') }}"
groups: "sudo"
Gjithçka është mjaft e thjeshtë, ne kemi gjithashtu një modul grupi për krijimin e grupeve, me një sintaksë shumë të ngjashme me apt. Atëherë mjafton të regjistrohet ky grup te përdoruesi (groups: "sudo"
).
Është gjithashtu e dobishme t'i shtohet një çelës ssh këtij përdoruesi në mënyrë që të mund të identifikohemi duke e përdorur atë pa një fjalëkalim:
---
- name: Simple playbook
# ...
tasks:
# ...
- name: Ensure a 'sudo' group
group:
name: sudo
state: present
- name: Add a new user
user:
name: "{{ user }}"
shell: /bin/bash
password: "{{ user_password | password_hash('sha512') }}"
groups: "sudo"
- name: Deploy SSH Key
authorized_key:
user: "{{ user }}"
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
state: present
Në këtë rast, dizajni është interesant "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
— kopjon përmbajtjen e skedarit id_rsa.pub (emri juaj mund të jetë i ndryshëm), domethënë pjesën publike të çelësit ssh dhe e ngarkon atë në listën e çelësave të autorizuar për përdoruesin në server.
rol
Të tre detyrat për krijimin e përdorimit mund të klasifikohen lehtësisht në një grup detyrash dhe do të ishte mirë ta ruani këtë grup veçmas nga libri kryesor i lojës, në mënyrë që të mos rritet shumë. Për këtë qëllim, Ansible ka
Sipas strukturës së skedarit të treguar në fillim, rolet duhet të vendosen në një direktori rolesh të veçantë, për secilin rol ka një drejtori të veçantë me të njëjtin emër, brenda drejtorisë së detyrave, skedarëve, shablloneve, etj.
Le të krijojmë një strukturë skedari: ./ansible/roles/user/tasks/main.yml
(main është skedari kryesor që do të ngarkohet dhe ekzekutohet kur një rol lidhet me librin e lojërave; skedarë të tjerë rolesh mund të lidhen me të). Tani mund të transferoni të gjitha detyrat që lidhen me përdoruesin në këtë skedar:
# Create user and add him to groups
- name: Ensure a 'sudo' group
group:
name: sudo
state: present
- name: Add a new user
user:
name: "{{ user }}"
shell: /bin/bash
password: "{{ user_password | password_hash('sha512') }}"
groups: "sudo"
- name: Deploy SSH Key
authorized_key:
user: "{{ user }}"
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
state: present
Në librin kryesor të lojërave, duhet të specifikoni për të përdorur rolin e përdoruesit:
---
- name: Simple playbook
hosts: all
remote_user: root
gather_facts: no
tasks:
- name: Update system
apt: update_cache=yes
- name: Install system dependencies
apt:
name: git,nginx,redis,postgresql,postgresql-contrib
state: present
roles:
- user
Gjithashtu, mund të ketë kuptim të përditësoni sistemin përpara të gjitha detyrave të tjera; për ta bërë këtë, mund ta riemërtoni bllokun tasks
në të cilën ato përcaktohen në pre_tasks
.
Konfigurimi i nginx
Tashmë duhet të kemi të instaluar Nginx; duhet ta konfigurojmë dhe ta ekzekutojmë. Le ta bëjmë menjëherë në rol. Le të krijojmë një strukturë skedari:
- ansible
- roles
- nginx
- files
- tasks
- main.yml
- templates
Tani na duhen skedarë dhe shabllone. Dallimi midis tyre është se ansible kopjon skedarët drejtpërdrejt, siç është. Dhe shabllonet duhet të kenë shtrirjen j2 dhe ata mund të përdorin vlera të ndryshueshme duke përdorur të njëjtat mbajtëse kaçurrela të dyfishta.
Le të aktivizojmë nginx in main.yml
dosje. Për këtë ne kemi një modul systemd:
# Copy nginx configs and start it
- name: enable service nginx and start
systemd:
name: nginx
state: started
enabled: yes
Këtu jo vetëm që themi që nginx duhet të fillojë (d.m.th., ne e lançojmë), por themi menjëherë se duhet të aktivizohet.
Tani le të kopjojmë skedarët e konfigurimit:
# Copy nginx configs and start it
- name: enable service nginx and start
systemd:
name: nginx
state: started
enabled: yes
- name: Copy the nginx.conf
copy:
src: nginx.conf
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
backup: yes
- name: Copy template my_app.conf
template:
src: my_app_conf.j2
dest: /etc/nginx/sites-available/my_app.conf
owner: root
group: root
mode: '0644'
Ne krijojmë skedarin kryesor të konfigurimit nginx (mund ta merrni direkt nga serveri, ose ta shkruani vetë). Dhe gjithashtu skedari i konfigurimit për aplikacionin tonë në drejtorinë sites_available (kjo nuk është e nevojshme, por e dobishme). Në rastin e parë, ne përdorim modulin e kopjimit për të kopjuar skedarët (skedari duhet të jetë brenda /ansible/roles/nginx/files/nginx.conf
). Në të dytën, ne kopjojmë shabllonin, duke zëvendësuar vlerat e variablave. Shablloni duhet të jetë në /ansible/roles/nginx/templates/my_app.j2
). Dhe mund të duket diçka si kjo:
upstream {{ app_name }} {
server unix:{{ app_path }}/shared/tmp/sockets/puma.sock;
}
server {
listen 80;
server_name {{ server_name }} {{ inventory_hostname }};
root {{ app_path }}/current/public;
try_files $uri/index.html $uri.html $uri @{{ app_name }};
....
}
Kushtojini vëmendje futjeve {{ app_name }}
, {{ app_path }}
, {{ server_name }}
, {{ inventory_hostname }}
- këto janë të gjitha variablat, vlerat e të cilave Ansible do t'i zëvendësojë në shabllon përpara kopjimit. Kjo është e dobishme nëse përdorni një libër lojërash për grupe të ndryshme hostesh. Për shembull, ne mund të shtojmë skedarin tonë të inventarit:
[production]
123.123.123.123
[staging]
231.231.231.231
[all:vars]
user=my_user
user_password=123qweasd
[production:vars]
server_name=production
app_path=/home/www/my_app
app_name=my_app
[staging:vars]
server_name=staging
app_path=/home/www/my_stage
app_name=my_stage_app
Nëse tani e hapim librin tonë të lojërave, ai do të kryejë detyrat e specifikuara për të dy hostet. Por në të njëjtën kohë, për një host të skenës, variablat do të jenë të ndryshëm nga ato të prodhimit, dhe jo vetëm në role dhe libra lojërash, por edhe në konfigurimin e nginx. {{ inventory_hostname }}
nuk ka nevojë të specifikohet në skedarin e inventarit - kjo
Nëse dëshironi të keni një skedar inventar për disa hoste, por të ekzekutoni vetëm për një grup, kjo mund të bëhet me komandën e mëposhtme:
ansible-playbook -i inventory ./playbook.yml -l "staging"
Një tjetër mundësi është që të keni skedarë të veçantë të inventarit për grupe të ndryshme. Ose mund të kombinoni të dy qasjet nëse keni shumë host të ndryshëm.
Le të kthehemi te konfigurimi i nginx. Pas kopjimit të skedarëve të konfigurimit, duhet të krijojmë një lidhje simbolike në sitet_enabled te my_app.conf nga sites_available. Dhe rinisni nginx.
... # old code in mail.yml
- name: Create symlink to sites-enabled
file:
src: /etc/nginx/sites-available/my_app.conf
dest: /etc/nginx/sites-enabled/my_app.conf
state: link
- name: restart nginx
service:
name: nginx
state: restarted
Gjithçka është e thjeshtë këtu - përsëri module të besueshme me një sintaksë mjaft standarde. Por ka një pikë. Nuk ka asnjë pikë për të rifilluar nginx çdo herë. A e keni vënë re se ne nuk shkruajmë komanda si: "bëje këtë kështu", sintaksa duket më shumë si "kjo duhet të ketë këtë gjendje". Dhe më shpesh kjo është saktësisht se si funksionon ansible. Nëse grupi ekziston tashmë, ose paketa e sistemit është instaluar tashmë, atëherë ansible do ta kontrollojë këtë dhe do ta kapërcejë detyrën. Gjithashtu, skedarët nuk do të kopjohen nëse përputhen plotësisht me atë që është tashmë në server. Ne mund të përfitojmë nga kjo dhe të rifillojmë nginx vetëm nëse skedarët e konfigurimit janë ndryshuar. Ekziston një direktivë regjistri për këtë:
# Copy nginx configs and start it
- name: enable service nginx and start
systemd:
name: nginx
state: started
enabled: yes
- name: Copy the nginx.conf
copy:
src: nginx.conf
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
backup: yes
register: restart_nginx
- name: Copy template my_app.conf
template:
src: my_app_conf.j2
dest: /etc/nginx/sites-available/my_app.conf
owner: root
group: root
mode: '0644'
register: restart_nginx
- name: Create symlink to sites-enabled
file:
src: /etc/nginx/sites-available/my_app.conf
dest: /etc/nginx/sites-enabled/my_app.conf
state: link
- name: restart nginx
service:
name: nginx
state: restarted
when: restart_nginx.changed
Nëse një nga skedarët e konfigurimit ndryshon, do të bëhet një kopje dhe ndryshorja do të regjistrohet restart_nginx
. Dhe vetëm nëse kjo variabël është regjistruar, shërbimi do të riniset.
Dhe, sigurisht, duhet të shtoni rolin nginx në librin kryesor të lojërave.
Vendosja e postgresql
Ne duhet të aktivizojmë postgresql duke përdorur systemd në të njëjtën mënyrë si kemi bërë me nginx, dhe gjithashtu të krijojmë një përdorues që do ta përdorim për të hyrë në bazën e të dhënave dhe vetë bazën e të dhënave.
Le të krijojmë një rol /ansible/roles/postgresql/tasks/main.yml
:
# Create user in postgresql
- name: enable postgresql and start
systemd:
name: postgresql
state: started
enabled: yes
- name: Create database user
become_user: postgres
postgresql_user:
name: "{{ db_user }}"
password: "{{ db_password }}"
role_attr_flags: SUPERUSER
- name: Create database
become_user: postgres
postgresql_db:
name: "{{ db_name }}"
encoding: UTF-8
owner: "{{ db_user }}"
Unë nuk do të përshkruaj se si të shtoni variabla në inventar, kjo tashmë është bërë shumë herë, si dhe sintaksa e moduleve postgresql_db dhe postgresql_user. Më shumë informacion mund të gjeni në dokumentacion. Direktiva më interesante këtu është become_user: postgres
. Fakti është se si parazgjedhje, vetëm përdoruesi i postgres ka qasje në bazën e të dhënave postgresql dhe vetëm në nivel lokal. Kjo direktivë na lejon të ekzekutojmë komanda në emër të këtij përdoruesi (nëse kemi akses, sigurisht).
Gjithashtu, mund t'ju duhet të shtoni një linjë në pg_hba.conf për të lejuar një përdorues të ri akses në bazën e të dhënave. Kjo mund të bëhet në të njëjtën mënyrë siç kemi ndryshuar konfigurimin e nginx.
Dhe sigurisht, ju duhet të shtoni rolin postgresql në librin kryesor të lojërave.
Instalimi i rubinit nëpërmjet rbenv
Ansible nuk ka module për të punuar me rbenv, por instalohet duke klonuar një depo git. Prandaj, ky problem bëhet më jo standardi. Le të krijojmë një rol për të /ansible/roles/ruby_rbenv/main.yml
dhe le të fillojmë ta plotësojmë:
# Install rbenv and ruby
- name: Install rbenv
become_user: "{{ user }}"
git: repo=https://github.com/rbenv/rbenv.git dest=~/.rbenv
Ne përsëri përdorim direktivën bene_user për të punuar nën përdoruesin që kemi krijuar për këto qëllime. Meqenëse rbenv është instaluar në direktorinë e tij kryesore, dhe jo globalisht. Dhe ne përdorim gjithashtu modulin git për të klonuar depon, duke specifikuar repo dhe dest.
Më pas, duhet të regjistrojmë rbenv init në bashrc dhe të shtojmë rbenv te PATH atje. Për këtë kemi modulin lineinfile:
- name: Add rbenv to PATH
become_user: "{{ user }}"
lineinfile:
path: ~/.bashrc
state: present
line: 'export PATH="${HOME}/.rbenv/bin:${PATH}"'
- name: Add rbenv init to bashrc
become_user: "{{ user }}"
lineinfile:
path: ~/.bashrc
state: present
line: 'eval "$(rbenv init -)"'
Atëherë duhet të instaloni ruby_build:
- name: Install ruby-build
become_user: "{{ user }}"
git: repo=https://github.com/rbenv/ruby-build.git dest=~/.rbenv/plugins/ruby-build
Dhe së fundi instaloni rubin. Kjo bëhet përmes rbenv, domethënë thjesht me komandën bash:
- name: Install ruby
become_user: "{{ user }}"
shell: |
export PATH="${HOME}/.rbenv/bin:${PATH}"
eval "$(rbenv init -)"
rbenv install {{ ruby_version }}
args:
executable: /bin/bash
Ne themi se cilën komandë të ekzekutojmë dhe me çfarë. Sidoqoftë, këtu hasim në faktin se ansible nuk ekzekuton kodin e përfshirë në bashrc përpara se të ekzekutojë komandat. Kjo do të thotë që rbenv do të duhet të përcaktohet drejtpërdrejt në të njëjtin skenar.
Problemi tjetër është për faktin se komanda shell nuk ka gjendje nga një këndvështrim i arsyeshëm. Kjo do të thotë, nuk do të ketë kontroll automatik nëse ky version i rubinit është i instaluar apo jo. Ne mund ta bëjmë këtë vetë:
- name: Install ruby
become_user: "{{ user }}"
shell: |
export PATH="${HOME}/.rbenv/bin:${PATH}"
eval "$(rbenv init -)"
if ! rbenv versions | grep -q {{ ruby_version }}
then rbenv install {{ ruby_version }} && rbenv global {{ ruby_version }}
fi
args:
executable: /bin/bash
Gjithçka që mbetet është të instaloni bundler:
- name: Install bundler
become_user: "{{ user }}"
shell: |
export PATH="${HOME}/.rbenv/bin:${PATH}"
eval "$(rbenv init -)"
gem install bundler
Dhe përsëri, shtoni rolin tonë ruby_rbenv në librin kryesor të lojërave.
Skedarët e përbashkët.
Në përgjithësi, konfigurimi mund të përfundojë këtu. Tjetra, gjithçka që mbetet është të ekzekutoni capistrano dhe ai do të kopjojë vetë kodin, do të krijojë drejtoritë e nevojshme dhe do të nisë aplikacionin (nëse gjithçka është konfiguruar saktë). Sidoqoftë, capistrano shpesh kërkon skedarë shtesë të konfigurimit, si p.sh database.yml
ose .env
Ato mund të kopjohen ashtu si skedarët dhe shabllonet për nginx. Ka vetëm një hollësi. Përpara se të kopjoni skedarët, duhet të krijoni një strukturë drejtorie për to, diçka si kjo:
# Copy shared files for deploy
- name: Ensure shared dir
become_user: "{{ user }}"
file:
path: "{{ app_path }}/shared/config"
state: directory
ne specifikojmë vetëm një direktori dhe ansible do të krijojë automatikisht ato prindër nëse është e nevojshme.
Ansible Vault
Tashmë kemi hasur në faktin se variablat mund të përmbajnë të dhëna sekrete si fjalëkalimi i përdoruesit. Nëse keni krijuar .env
dosje për aplikim, dhe database.yml
atëherë duhet të ketë edhe më shumë të dhëna të tilla kritike. Do të ishte mirë t'i fshihni nga sytë kureshtarë. Për këtë qëllim përdoret
Le të krijojmë një skedar për variablat /ansible/vars/all.yml
(këtu mund të krijoni skedarë të ndryshëm për grupe të ndryshme hostesh, ashtu si në skedarin e inventarit: production.yml, staging.yml, etj.).
Të gjitha variablat që duhet të kodohen duhet të transferohen në këtë skedar duke përdorur sintaksën standarde yml:
# System vars
user_password: 123qweasd
db_password: 123qweasd
# ENV vars
aws_access_key_id: xxxxx
aws_secret_access_key: xxxxxx
aws_bucket: bucket_name
rails_secret_key_base: very_secret_key_base
Pas së cilës ky skedar mund të kodohet me komandën:
ansible-vault encrypt ./vars/all.yml
Natyrisht, kur kriptoni, do t'ju duhet të vendosni një fjalëkalim për deshifrim. Ju mund të shihni se çfarë do të jetë brenda skedarit pasi të keni thirrur këtë komandë.
Me anë të ansible-vault decrypt
skedari mund të deshifrohet, modifikohet dhe më pas të kodohet përsëri.
Ju nuk keni nevojë të deshifroni skedarin për të punuar. Ju e ruani atë të koduar dhe ekzekutoni librin e lojërave me argumentin --ask-vault-pass
. Ansible do të kërkojë fjalëkalimin, do të marrë variablat dhe do të ekzekutojë detyrat. Të gjitha të dhënat do të mbeten të koduara.
Komanda e plotë për disa grupe të hosteve dhe vault ansible do të duket diçka si kjo:
ansible-playbook -i inventory ./playbook.yml -l "staging" --ask-vault-pass
Por nuk do t'ju jap tekstin e plotë të librave dhe roleve, shkruani vetë. Sepse ansible është e tillë - nëse nuk e kuptoni se çfarë duhet bërë, atëherë nuk do ta bëjë atë për ju.
Burimi: www.habr.com