Kohë më parë, më ishte nevojitur të shkruaja disa ansible playbooks për përgatitjen e serverit për deploy të një aplikacioni Rails. Dhe, me befasinë time, nuk gjeta një manual të thjeshtë hapi-pas-hapi. Nuk doja të kopjoja playbook-un e dikujt tjetër pa kuptuar atë që po ndodhte dhe përfundimisht, më duhej të lexoj dokumentacionin, duke mbledhur gjithçka vetë. Ndoshta do të mund të ndihmoj dikë të përshpejtojë këtë proces përmes këtij artikulli.
E para, është e rëndësishme të kuptoni se ansible ju ofron një ndërfaqe të lehtë për të kryer një listë të paracaktuar veprimesh në një server (servera) të largët përmes SSH. Nuk ka ndonjë magji këtu, nuk mund të vendosni një plugin dhe të merrni një deploy zero downtime të aplikacionit tuaj me docker, monitorim dhe gjëra të tjera. Për të shkruar një playbook duhet të dini se çfarë dëshironi të bëni dhe si ta bëni atë. Prandaj, unë nuk jam i kënaqur me playbook-et e gatshme nga GitHub, ose artikuj që thonë: “Kopjoni dhe ekzekutoni, do të funksionojë”.
Çfarë na nevojitet?
Siç e thashë, për të shkruar një playbook duhet të dini se çfarë dëshironi të bëni dhe si ta bëni atë. Le të përcaktojmë se çfarë na nevojitet. Për aplikacionin Rails, do të na duhen disa paketa системike: nginx, postgresql (redis, etj). Përveç kësaj, na duhet ruby i një versioni të caktuar. E rekomandoj ta instaloni atë përmes rbenv (rvm, asdf…). Të gjitha këto nuk duhet të ekzekutohen nga përdoruesi root — gjithmonë është një ide e keqe, prandaj duhet të krijoni një përdorues të veçantë dhe t’i konfiguroheni të drejtat. Pas kësaj, është e nevojshme të ngarkohet kodi ynë në server, të kopjohen konfigurimet për nginx, postgres, etj dhe të nisën të gjitha këto shërbime.
Në fund, sekuenca e veprimeve është kështu:
- Bëjmë login si root.
- instalojmë paketat sistemike.
- krijojmë një përdorues të ri, konfigurojmë të drejtat, çelësin ssh.
- konfigurojmë paketat sistemike (nginx etj) dhe i nisim ato.
- Krijojmë një përdorues në DB (mund ta krijojmë menjëherë edhe bazën).
- Bëjmë login me përdoruesin e ri.
- Instalojmë rbenv dhe ruby.
- Instalojmë bundler.
- Ngarkojmë kodin e aplikacionit.
- Nisim serverin Puma.
Dhe këto hapat e fundit mund të bëhen me ndihmën e Capistrano, të paktën ai di nga e drejta të kopjojë kodin në direktoritë e lëshimeve, të kalojë në lidhjen simlink kur deploy është i suksesshëm, të kopjojë konfigurimet nga direktoria e ndarë, ta rinstalojë puma dhe etj. Të gjitha këto mund të bëhen edhe me Ansible, por përse?
Struktura e skedarëve
Ansible ka një strukturë të rreptë për të gjitha skedarët e tij, prandaj është më mirë t'i mbani të gjitha në një direktore të veçantë. Nuk ka rëndësi nëse do të jetë brenda aplikacionit Rails, apo ndaras. Mund të ruani skedarët në një depo git të veçantë. Më së shumti, më është dukur më e lehtë të krijoj një direktore ansible në /config të aplikacionit Rails dhe të ruaj të gjitha në një depo.
Playbook i Thjeshtë
Playbook është një skedar yml, në të cilin me ndihmën e një sintakse të veçantë është përshkruar se çfarë dhe si duhet ta bëjë ansible. Le të krijojmë playbook-in tonë të parë, që nuk bën asgjë:
---
- name: Playbook i Thjeshtë
hosts: allKëtu ne thjesht po themi se playbook-i ynë quhet Playbook i Thjeshtë dhe se përmbajtja e tij duhet të执行het për të gjitha hostet. Mund ta ruajmë atë në direktoren /ansible me emrin playbook.yml dhe të provojmë ta ranimojmë:
ansible-playbook ./playbook.yml
PLAY [Playbook i Thjeshtë] ************************************************************************************************************************************
skipping: no hosts matchedAnsible thotë se nuk di hostet që përputhen me listën e të gjitha. Duhet t'i rendisim ato në një .
Le të krijojmë atë në të njëjtën direktore ansible:
123.123.123.123Këtu thjesht tregojmë hostin (idealisht hostin tuaj VPS për teste, ose mund të shkruani localhost) dhe e ruajmë me emrin inventory.
Mund të provoni ta ekzekutoni ansible me skedarin e inventarit:
ansible-playbook ./playbook.yml -i inventory
PLAY [Playbook i Thjeshtë] ************************************************************************************************************************************
TASK [Mblidh Fakte] ************************************************************************************************************************************
PLAY RECAP ************************************************************************************************************************************Nëse keni qasje përmes ssh në hostin e specifikuar, ansible do të lidhet dhe do të mbledhë informacion rreth sistemit të largët. (detyra standarde TASK [Mblidh Fakte]) pas së cilës do të japë një raport të shkurtër për ekzekutimin (PLAY RECAP).
Sipas të dhënave, emri i përdoruesit që përdoret për lidhjen është ai me të cilin jeni loguar në sistem. Në host, ndoshta nuk do të jetë. Në skedarin e playbook-it mund të tregoni se cilin përdorues duhet të përdorni për lidhjen me ndihmën e direktivës remote_user. Gjithashtu, informacioni rreth sistemit të largët shpesh mund të mos jetë i nevojshëm dhe nuk ia vlen të humbni kohë për ta mbledhur. Këtë detyrë gjithashtu mund ta çaktivizoni:
---
- name: Playbook i Thjeshtë
hosts: all
remote_user: root
become: true
gather_facts: noProvoni përsëri të nisni playbook dhe sigurohuni që lidhja funksionon. (Nëse keni specifikuar përdoruesin root, gjithashtu duhet të specifikoni direktivën become: true, për të fituar të drejtat e rritura. Siç shkruhet në dokumentacion: become e vendosur në 'true'/'yes' për të aktivizuar shkallëzimin e privilegjeve. ndonëse nuk është krejt e qartë se përse).
Mund të merrni një gabim të shkaktuar nga fakti që ansible nuk mund të përcaktojë interpreterin e python, atëherë mund ta specifikoni manualisht:
ansible_python_interpreter: /usr/bin/python3 ku e keni python mund ta merrni me komandën whereis python.
Instalimi i paketeve sistemore
Në instalimin standard të Ansible përfshihen shumë module për punë me paketa të ndryshme sistemore, duke na i lehtësuar kështu krijimin e skripteve bash në çdo rast. Tani do na nevojitet një nga këto module për të përditësuar sistemin dhe instaluar paketat sistemore. Unë në VPS kam Ubuntu Linux, kështu që për të instaluar paketat përdor apt-get dhe Nëse përdorni një sistem operativ tjetër, ndoshta do të nevojitet një modul tjetër (mbani mend se në fillim thashë që duhet ta dimë paraprakisht se çfarë dhe si do të bëjmë). Megjithatë, sintaksa ndoshta do të jetë e ngjashme.
Do ta plotësojmë playbook-un tonë 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: presentTask — është pikërisht detyra që ansible do të ekzekutojë në serverët e largët. Ne japim emrin detyrës për të ndjekur ekzekutimin e saj në log. Dhe e përshkruajmë, duke përdorur sintaksën e modulit përkatës, se çfarë duhet të bëjë. Në këtë rast apt: update_cache=yes — thotë të përditësojë paketat e sistemit duke përdorur modulën apt. Komanda e dytë është disi më e komplikuar. Ne i kalojmë modulit apt një listë paketash dhe i themi që state duhet të bëhen present, domethënë i themi të instalojë këto paketa. Në të njëjtën mënyrë, mund të themi që t'i hiqni ose t'i përditësoni, thjesht duke ndryshuar state. Vini re se për punën e rails me postgresql na nevojitet paketa postgresql-contrib, të cilën po e instalojmë tani. Kjo duhet të dihet dhe të bëhet, ansible vetë nuk do ta bëjë këtë.
Provoni të ekzekutoni playbook-in përsëri dhe kontrolloni që paketat të instalohen.
Krijimi i përdoruesve të rinj.
Për të punuar me përdoruesit, Ansible ka gjithashtu një modul — user. Do të shtojmë një task tjetër (kam fshehur pjesët e njohura të playbook-ut me komente, që të mos e kopjoj tërë çdo herë):
---
- name: Playbook i thjeshtë
# ...
tasks:
# ...
- name: Shto një përdorues të ri
user:
name: my_user
shell: /bin/bash
password: "{{ 123qweasd | password_hash('sha512') }}"Ne po krijojmë një përdorues të ri, vendosim shell-in dhe fjalëkalimin e tij. Dhe këtu përballemi me disa probleme. Çfarë bëjmë nëse emrat e përdoruesve duhet të jenë të ndryshëm për hoste të ndryshme? Po ashtu, të ruash fjalëkalimin në formë të hapur në playbook është një ide shumë e keqe. Fillimisht, do të nxjerrim emrin e përdoruesit dhe fjalëkalimin në variabla, dhe më afër fundin e artikullit do të tregoj se si ta enkriptojmë fjalëkalimin.
---
- name: Playbook i thjeshtë
# ...
tasks:
# ...
- name: Shto një përdorues të ri
user:
name: "{{ user }}"
shell: /bin/bash
password: "{{ user_password | password_hash('sha512') }}"Me anë të dyfishtë të kllapave në playbook-e vendosen variablat.
Vlerat e variablave do t'i specifikojmë në skedarin e inventarit:
123.123.123.123
[all:vars]
user=my_user
user_password=123qweasdKujdesini për drejtpërsëdrejti [all:vars] — thotë se blloku i ardhshëm i tekstit është variablat (vars) dhe janë të aplikueshme për të gjithë hostet (all).
Po ashtu interesante është konstrukti "{{ user_password | password_hash('sha512') }}". Çështja është se ansible nuk e krijon përdoruesin përmes user_add siç do ta bënit manualisht. Ai ruan të dhënat drejtpërsëdrejti, për këtë arsye duhet ta konvertojmë fjalëkalimin në një hash paraprakisht, gjë që e bën kjo komandë.
Le të shtojmë përdoruesin tonë në grupin sudo. Megjithatë, përpara kësaj duhet të sigurohemi që një grup i tillë ekziston sepse askush tjetër nuk do ta bëjë këtë për ne:
---
- name: Playbook i thjeshtë
# ...
tasks:
# ...
- name: Siguro një grup 'sudo'
group:
name: sudo
state: present
- name: Shto një përdorues të ri
user:
name: "{{ user }}"
shell: /bin/bash
password: "{{ user_password | password_hash('sha512') }}"
groups: "sudo"Gjithçka është mjaft e thjeshtë, kemi gjithashtu modul grup për të krijuar grupe, me një sintaksë shumë të ngjashme me apt. Pas kësaj mjafton të regjistrojmë këtë grup te përdoruesi (groups: "sudo").
Po ashtu është e dobishme të shtojmë këtij përdoruesi një çelës ssh, që të mund të hyjmë nën të pa fjalëkalim:
---
- name: Playbook i thjeshtë
# ...
tasks:
# ...
- name: Siguro një grup 'sudo'
group:
name: sudo
state: present
- name: Shto një përdorues të ri
user:
name: "{{ user }}"
shell: /bin/bash
password: "{{ user_password | password_hash('sha512') }}"
groups: "sudo"
- name: Nxjerr çelësin SSH
authorized_key:
user: "{{ user }}"
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
state: presentNë këtë rast është interesante struktura "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" — ajo kopjon përmbajtjen e skedës id_rsa.pub (emri mund të jetë ndryshe), pra 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.
Rolet
Të tria këto detyra për krijimin e përdoruesit mund të përfshihen lehtësisht në një grup detyrash, dhe do të ishte mirë ta mbani këtë grup ndarë nga playbook-u kryesor, në mënyrë që të mos shfaqet shumë i madh. Për këtë në ansible ekzistojnë .
Sipas strukturës së skedarëve të specifikuar në fillim, rolet duhet të vendosen në një drejtorinë të veçantë roles, për çdo rol — një drejtorinë të veçantë me emrin përkatës, brenda drejtorisë tasks, files, templates, etj.
Të krijojmë strukturën e skedarëve: ./ansible/roles/user/tasks/main.yml (main — ky është skedari kryesor që do të ngarkohet dhe ekzekutohet kur lidhet roli me playbook-un, në të mund të lidhni skedarë të tjerë të rolit). Tani mund të transferoni në këtë skedar të gjitha detyrat që lidhen me përdoruesin:
# 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: presentNë playbook-un kryesor duhet të specifikoni të përdorni rolin user:
---
- name: Playbook i thjeshtë
hosts: all
remote_user: root
gather_facts: no
tasks:
- name: Përditëso sistemin
apt: update_cache=yes
- name: Instaloni varësitë e sistemit
apt:
name: git,nginx,redis,postgresql,postgresql-contrib
state: present
roles:
- userGjithashtu, ndoshta ka kuptim të kryeni përditësimin e sistemit para detyrave të tjera, për këtë mund të riemëroni bllokun tasks në të cilin ato janë të përcaktuara si pre_tasks.
Konfigurimi i nginx
Nginx duhet të jetë tashmë i instaluar, duhet ta konfigurojmë dhe ta nxjerrim në punë. Le të bëjmë këtë menjëherë në rol. Krijojmë strukturën e skedarëve:
- ansible
- roles
- nginx
- files
- tasks
- main.yml
- templatesTani na duhen skedarët dhe shabllonët. Diferenca midis tyre është se skedarët ansible i kopjon drejtpërdrejt, ashtu si janë. Ndërsa shabllonët duhet të kenë zgjerimin j2 dhe brenda tyre mund të përdoren vlerat e variablave duke përdorur të njëjtat dyfish figura të skëmbëve.
Le të përfshijmë nginx në main.yml skedarin. Për këtë kemi modul systemd:
# Copy nginx configs and start it
- name: enable service nginx and start
systemd:
name: nginx
state: started
enabled: yesKëtu ne jo vetëm që themi se nginx duhet të jetë started (domethënë ta nisim atë), por gjithashtu i themi se ai duhet të jetë enabled.
Tani do 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'Krijojmë skedarin kryesor të konfigurimit për nginx (mund ta marrim direkt nga serveri ose ta shkruajmë vetë). Gjithashtu krijojmë skedarin e konfigurimit për aplikacionin tonë në drejtorinë sites_available (nuk është e detyrueshme, por është e dobishme). Në rastin e parë, ne përdorim modulin copy për të kopjuar skedarët (skedari duhet të jetë në /ansible/roles/nginx/files/nginx.conf). Në rastin e dytë, kopjojmë modelin, duke futur vlerat e variablave. Modeli duhet të jetë në /ansible/roles/nginx/templates/my_app.j2). Dhe mund të duket diçka si ky:
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 }};
....
}Vini re insertet {{ app_name }}, {{ app_path }}, {{ server_name }}, {{ inventory_hostname }} — këto janë të gjitha variabla, vlerat e të cilëve ansible do t'i vendosë në model para kopjimit. Kjo është e dobishme nëse përdorim një playbook për grupe të ndryshme hostesh. Për shembull, mund të shtojmë skedarin tonë të inventory:
[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_appNëse tani e fillojmë playbook-un tonë, do të ekzekutojë detyrat e përmendura për të dy hostet. Por në këtë rast, për hostin staging variablat do të jenë ndryshe nga production, dhe jo vetëm në role dhe playbooks, por edhe në konfigurimet e nginx. {{ inventory_hostname }} nuk duhet të theksohet në skedarin e inventory — kjo dhe aty ruhet hosti për të cilin ekzekutohet playbook-u në atë moment.
Nëse dëshironi të keni një skedar inventory për disa hoste, por të ekzekutoni vetëm për një grup, mund ta bëni këtë me komandën e mëposhtme:
ansible-playbook -i inventory .\/playbook.yml -l "staging"një alternativë tjetër — të keni skedarë inventory të ndarë për grupe të ndryshme. Ose mund të kombinoni dy qasje, nëse keni shumë hoste të ndryshëm.
Kthehemi te konfigurimi i nginx. Pas kopjimit të skedarëve të konfigurimit, na nevojitet të krijojmë një simlink në sites_enabled për my_app.conf nga sites_available. Dhe të rindiznim nginx.
... # kodi i vjetër në mail.yml
- name: Krijo simlink në sites-enabled
file:
src: \/etc\/nginx\/sites-available\/my_app.conf
dest: \/etc\/nginx\/sites-enabled\/my_app.conf
state: link
- name: rindizni nginx
service:
name: nginx
state: restartedKëtu është shumë e thjeshtë — përsëri modulet ansible me sintaksë mjaft standarde. Por ka një moment. Nuk ka kuptim të rinit nginx çdo herë. A keni vënë re se ne nuk shkruajmë komanda të tipit: «bëni këtë kështu», sintaksa duket më shumë si «kësaj duhet të ketë një gjendje të tillë». Dhe shpesh, kështu punon ansible. Nëse grupi tashmë ekziston, ose paketa sistemike është instaluar, ansible do ta kontrollojë këtë dhe do ta kalojë detyrën. Po ashtu, skedarët nuk do të kopohen nëse ata përputhen plotësisht me ato që janë tashmë në server. Ne mund ta përfitojmë këtë dhe të rinisim nginx vetëm nëse skedarët e konfigurimit kanë ndryshuar. Për këtë ekziston direktiva register:
# 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.changedNëse ndonjë prej skedarëve të konfigurimit ndryshon, do të kryhet kopjimi dhe do të regjistrohet variabla restart_nginx. Dhe vetëm nëse kjo variablë është regjistruar, do të kryhet rinisja e shërbimit.
Natyrisht, duhet të shtoni rolin nginx në playbook-un kryesor.
Konfigurimi i postgresql
Na nevojitet të aktivizojmë postgresql me anë të systemd njësoj siç e bëmë me nginx, si dhe të krijojmë një përdorues, të cilin do ta përdorim për qasje 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 }}"Nuk do të përshkruaj se si të shtoni variabla në inventory, kjo është bërë shumë herë, ashtu siç është sintaksa e modulit postgresql_db dhe postgresql_user. Më shumë të dhëna mund të gjenden në dokumentacion. Këtu është më interesant direktiva become_user: postgres. Çështja është se, sipas parashikimeve, qasja në bazën e të dhënave postgresql është vetëm për përdoruesin postgres dhe vetëm lokalisht. Kjo direktivë na lejon të ekzekutojmë komanda në emër të këtij përdoruesi (nëse natyrisht kemi qasje).
Po ashtu, ndoshta do t'ju duhet të shkruani një rresht në pg_hba.conf për të hapur aksesin e përdoruesit të ri në bazë. Këto mund të bëhen njësoj siç e ndryshuam konfigurimin e nginx.
Natyrisht, duhet të shtoni rolin postgresql në playbook-un kryesor.
Instalimi i ruby përmes rbenv
Në ansible nuk ka module për punën me rbenv, dhe ai instalohet duke klonuar depot git. Prandaj, kjo detyrë bëhet më e pazakontë. Le të krijojmë një rol për të /ansible/roles/ruby_rbenv/main.yml dhe të fillojmë ta mbushim:
# Install rbenv and ruby
- name: Install rbenv
become_user: "{{ user }}"
git: repo=https://github.com/rbenv/rbenv.git dest=~/.rbenvNe po përdorim përsëri direktivën become_user për të punuar si përdoruesi që kemi krijuar për këto qëllime. Duke qenë se rbenv instalohet në direktorinë e tij home dhe jo globalisht. Po ashtu, ne përdorim modulit git për të klonuar repozitorin, duke specifikuar repo dhe dest.
Më pas, na nevojitet të shkruajmë rbenv init në bashrc dhe atje të shtojmë rbenv në PATH. Për këtë, kemi modulit lineinfile:
- name: Shto rbenv në PATH
become_user: "{{ user }}"
lineinfile:
path: ~\/bashrc
state: present
line: 'export PATH="${HOME}\/\.rbenv\/bin:${PATH}"'
- name: Shto rbenv init në bashrc
become_user: "{{ user }}"
lineinfile:
path: ~\/bashrc
state: present
line: 'eval "$(rbenv init -)"'Pasi të bëhet kjo, duhet të instaloni ruby_build:
- name: Instaloni ruby-build
become_user: "{{ user }}"
git: repo=https:\/\/github.com\/rbenv\/ruby-build.git dest=~\/\.rbenv\/plugins\/ruby-buildDhe, në fund, instaloni ruby. Kjo bëhet përmes rbenv, thjesht me komandë bash:
- name: Instaloni ruby
become_user: "{{ user }}"
shell: |
export PATH="${HOME}\/\.rbenv\/bin:${PATH}"
eval "$(rbenv init -)"
rbenv install {{ ruby_version }}
args:
executable: \/bin\/bashNe tregojmë se cila komandë do të ekzekutohet dhe me çfarë. Megjithatë, këtu do të përballemi me faktin se ansible nuk ekzekuton kodin e pranishëm në bashrc përpara ekzekutimit të komandave. Kështu që, rbenv do të duhet të përcaktohet drejtpërdrejt në këtë skenar.
Problemi tjetër është se komanda shell nuk ka gjendje në këndvështrimin e ansible. domethënë nuk do të ketë verifikim automatik nëse kjo version ruby është instaluar apo jo — kjo duhet ta bëjmë vetë:
- name: Instaloni 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\/bashDhe mbetet të instaloni bundler:
- name: Instaloni bundler
become_user: "{{ user }}"
shell: |
export PATH="${HOME}\/\.rbenv\/bin:${PATH}"
eval "$(rbenv init -)"
gem install bundlerPo ashtu të shtoni rolin tonë ruby_rbenv në playbook-in kryesor.
Skedarët e ndarë.
Në përgjithësi, këtu mund të përfundohej konfigurimi. Më pas, mbetet të nisni capistrano dhe ajo do të kopjojë kodin vetë, do të krijojë katalogët e nevojshëm dhe do të niste aplikacionin (nëse është vendosur gjithçka saktë). Megjithatë, shpesh capistrano kërkon skedarë të tjerë konfigurohuese si database.yml или .env Ato mund të kopjohen njëlloj si skedarët dhe shabllonët për nginx. Ka vetëm një hollësi. Para kopjimit të skedarëve, është e nevojshme të krijoni strukturën e katalogëve për ta, diçka të tillë:
# Copy shared files for deploy
- name: Ensure shared dir
become_user: "{{ user }}"
file:
path: "{{ app_path }}/shared/config"
state: directoryne specifikojmë vetëm një direktori dhe ansible do ta krijojë automatikisht ata prind, nëse është e nevojshme.
Ansible Vault
Kemi has already encountered cases where sensitive data such as user passwords can be found in variables. If you created .env a file for the application, and database.yml there should be even more critical data in it. It’s best to hide them from prying eyes. For this purpose, we use .
Let's create a file for the variables /ansible/vars/all.yml (here you can create different files for different groups of hosts, just like in the inventory file: production.yml, staging.yml, etc.).
In this file, you need to transfer all variables that need to be encrypted, using standard yaml syntax:
# 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_baseAfter that, you can encrypt this file with the command:
ansible-vault encrypt ./vars/all.ymlNaturally, when encrypting, you will need to set a password for decryption. You can check what will be inside the file after invoking this command.
With the help of ansible-vault decrypt the file can be decrypted, modified, and then re-encrypted.
To work, you don't need to decrypt the file. You keep it encrypted and run the playbook with the argument --ask-vault-pass. Ansible will ask for the password, retrieve the variables, and execute the tasks. All data will remain encrypted.
The complete command for several groups of hosts and ansible vault will look something like this:
ansible-playbook -i inventory ./playbook.yml -l "staging" --ask-vault-passAnd I won’t provide you with the full text of the playbooks and roles, you write it yourself. Because ansible is such a thing — if you don’t understand what needs to be done, it won’t do it for you either.
Burimi: habr.com
