Serverio nustatymas „Rails“ programai diegti naudojant „Ansible“.

Neseniai man reikėjo parašyti keletą Ansible žaidimų knygų, kad paruoščiau serverį „Rails“ programos diegimui. Ir, stebėtinai, aš neradau paprasto žingsnis po žingsnio vadovo. Nenorėjau kopijuoti kažkieno pjesės nesuprasdamas, kas vyksta, ir galų gale turėjau perskaityti dokumentaciją, viską rinkti pačiam. Galbūt galėčiau padėti kam nors pagreitinti šį procesą šio straipsnio pagalba.

Pirmas dalykas, kurį reikia suprasti, yra tai, kad ansible suteikia jums patogią sąsają atlikti iš anksto nustatytą veiksmų sąrašą nuotoliniame (-iuose) serveryje (-iuose) per SSH. Čia nėra jokios magijos, jūs negalite įdiegti papildinio ir pasiekti, kad jūsų programa būtų įdiegta be prastovos su dokeriu, stebėjimu ir kitomis gėrybėmis. Norėdami parašyti žaidimų knygą, turite žinoti, ką tiksliai norite daryti ir kaip tai padaryti. Štai kodėl manęs netenkina paruoštos „GitHub“ žaidimų knygos arba tokie straipsniai kaip: „Nukopijuokite ir paleiskite, tai veiks“.

Ko mums reikia?

Kaip jau sakiau, norėdami parašyti žaidimų knygą, turite žinoti, ką norite daryti ir kaip tai padaryti. Nuspręskime, ko mums reikia. Rails programai mums reikės kelių sistemos paketų: nginx, postgresql (redis ir kt.). Be to, mums reikia konkrečios rubino versijos. Geriausia jį įdiegti per rbenv (rvm, asdf...). Visa tai paleisti kaip root naudotojui visada yra bloga idėja, todėl reikia sukurti atskirą vartotoją ir sukonfigūruoti jo teises. Po to turite įkelti mūsų kodą į serverį, nukopijuoti nginx, postgres ir kt. konfigūracijas ir paleisti visas šias paslaugas.

Dėl to veiksmų seka yra tokia:

  1. Prisijunkite kaip root
  2. įdiegti sistemos paketus
  3. sukurti naują vartotoją, sukonfigūruoti teises, ssh raktą
  4. sukonfigūruokite sistemos paketus (nginx ir tt) ir paleiskite juos
  5. Duomenų bazėje sukuriame vartotoją (galite iš karto sukurti duomenų bazę)
  6. Prisijunkite kaip naujas vartotojas
  7. Įdiekite rbenv ir ruby
  8. Sujungiklio montavimas
  9. Įkeliamas programos kodas
  10. Puma serverio paleidimas

Be to, paskutinius etapus galima atlikti naudojant capistrano, bent jau iš dėžutės jis gali nukopijuoti kodą į leidimų katalogus, sėkmingai įdiegus perjungti leidimą su simpatija, nukopijuoti konfigūracijas iš bendro katalogo, iš naujo paleisti puma ir pan. Visa tai galima padaryti naudojant Ansible, bet kodėl?

Failo struktūra

Ansible turi griežtą failo struktūra visiems failams, todėl geriausia visa tai laikyti atskirame kataloge. Be to, nėra taip svarbu, ar tai bus pačioje bėgių programoje, ar atskirai. Failus galite saugoti atskiroje git saugykloje. Asmeniškai man patogiausia buvo sukurti ansible katalogą rails programos /config kataloge ir viską saugoti vienoje saugykloje.

Paprasta žaidimų knyga

Playbook yra yml failas, kuriame, naudojant specialią sintaksę, aprašoma, ką Ansible turėtų daryti ir kaip. Sukurkime pirmąją žaidimų knygą, kuri nieko nedaro:

---
- name: Simple playbook
  hosts: all

Čia mes tiesiog sakome, kad mūsų žaidimų knyga yra vadinama Simple Playbook ir kad jo turinys turėtų būti vykdomas visiems pagrindiniams kompiuteriams. Galime išsaugoti /ansible kataloge su pavadinimu playbook.yml ir bandyk paleisti:

ansible-playbook ./playbook.yml

PLAY [Simple Playbook] ************************************************************************************************************************************
skipping: no hosts matched

Ansible sako nežinantis jokių prieglobų, atitinkančių visų sąrašą. Jie turi būti išvardyti specialiame sąraše inventoriaus byla.

Sukurkime jį tame pačiame galimame kataloge:

123.123.123.123

Taip mes tiesiog nurodome pagrindinį kompiuterį (idealiu atveju mūsų VPS pagrindinį kompiuterį testavimui arba galite užregistruoti localhost) ir išsaugome jį pavadinimu inventory.
Galite pabandyti paleisti ansible su inventoriaus failu:

ansible-playbook ./playbook.yml -i inventory
PLAY [Simple Playbook] ************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************

PLAY RECAP ************************************************************************************************************************************

Jei turite ssh prieigą prie nurodyto pagrindinio kompiuterio, ansible prisijungs ir rinks informaciją apie nuotolinę sistemą. (numatytasis UŽDUOTIS [Rinkti faktus]), po kurio pateiks trumpą ataskaitą apie vykdymą (PLAY RECAP).

Pagal numatytuosius nustatymus ryšys naudoja vartotojo vardą, kuriuo esate prisijungę prie sistemos. Greičiausiai jos nebus pagrindiniame kompiuteryje. Žaidimų knygelės faile galite nurodyti, kurį vartotoją naudoti norint prisijungti naudojant nuotolinio_vartotojo direktyvą. Be to, informacija apie nuotolinę sistemą jums dažnai gali būti nereikalinga, todėl neturėtumėte gaišti laiko ją rinkdami. Šią užduotį taip pat galima išjungti:

---
- name: Simple playbook
  hosts: all
  remote_user: root
  become: true
  gather_facts: no

Pabandykite dar kartą paleisti žaidimų knygą ir įsitikinkite, kad ryšys veikia. (Jei nurodėte šakninį vartotoją, tuomet taip pat turite nurodyti direktyvą tapti: true, kad įgytumėte padidintas teises. Kaip parašyta dokumentacijoje: become set to ‘true’/’yes’ to activate privilege escalation. nors iki galo neaišku kodėl).

Galbūt gausite klaidą, kurią sukelia tai, kad ansible negali nustatyti Python interpretatoriaus, tada galite jį nurodyti rankiniu būdu:

ansible_python_interpreter: /usr/bin/python3 

Su komanda galite sužinoti, kur turite python whereis python.

Sistemos paketų diegimas

Standartiniame Ansible paskirstyme yra daug modulių, skirtų darbui su įvairiais sistemos paketais, todėl mums dėl kokių nors priežasčių nereikia rašyti bash scenarijų. Dabar mums reikia vieno iš šių modulių, kad galėtume atnaujinti sistemą ir įdiegti sistemos paketus. VPS turiu „Ubuntu Linux“, todėl naudoju paketų diegimui apt-get и tam skirtas modulis. Jei naudojate kitą operacinę sistemą, tuomet jums gali prireikti kitokio modulio (atminkite, pradžioje sakiau, kad turime iš anksto žinoti, ką ir kaip darysime). Tačiau sintaksė greičiausiai bus panaši.

Papildykime savo žaidimų knygelę pirmomis užduotimis:

---
- 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

Užduotis yra būtent ta užduotis, kurią Ansible atliks nuotoliniuose serveriuose. Užduočiai suteikiame pavadinimą, kad galėtume sekti jos vykdymą žurnale. Ir mes aprašome, naudodami konkretaus modulio sintaksę, ką jis turi daryti. Tokiu atveju apt: update_cache=yes - sako atnaujinti sistemos paketus naudojant apt modulį. Antroji komanda yra šiek tiek sudėtingesnė. Mes perduodame paketų sąrašą apt moduliui ir sakome, kad jie yra state turėtų tapti present, tai yra, mes sakome, kad įdiekite šiuos paketus. Panašiai galime liepti juos ištrinti arba atnaujinti tiesiog pakeisdami state. Atkreipkite dėmesį, kad bėgiai veiktų su postgresql, mums reikia paketo postgresql-contrib, kurį dabar diegiame. Vėlgi, jūs turite tai žinoti ir padaryti; vienas ansible to nepadarys.

Pabandykite dar kartą paleisti grojaraštį ir patikrinkite, ar paketai įdiegti.

Naujų vartotojų kūrimas.

Norėdami dirbti su vartotojais, Ansible taip pat turi modulį - vartotoją. Pridėkime dar vieną užduotį (jau žinomas pjesės dalis paslėpiau už komentarų, kad kaskart jos visiškai nenukopijuočiau):

---
- name: Simple playbook
  # ...
  tasks:
    # ...
    - name: Add a new user
      user:
        name: my_user
        shell: /bin/bash
        password: "{{ 123qweasd | password_hash('sha512') }}"

Sukuriame naują vartotoją, nustatome jam schemą ir slaptažodį. Ir tada susiduriame su keliomis problemomis. Ką daryti, jei skirtingų kompiuterių naudotojų vardai turi skirtis? Saugoti slaptažodį aiškiu tekstu žaidimo knygelėje yra labai bloga idėja. Pirmiausia įdėkime vartotojo vardą ir slaptažodį į kintamuosius, o straipsnio pabaigoje parodysiu, kaip užšifruoti slaptažodį.

---
- name: Simple playbook
  # ...
  tasks:
    # ...
    - name: Add a new user
      user:
        name: "{{ user }}"
        shell: /bin/bash
        password: "{{ user_password | password_hash('sha512') }}"

Kintamieji žaidimo knygelėse nustatomi naudojant dvigubus skliaustus.

Inventorizavimo faile nurodysime kintamųjų reikšmes:

123.123.123.123

[all:vars]
user=my_user
user_password=123qweasd

Atkreipkite dėmesį į direktyvą [all:vars] - sakoma, kad kitas teksto blokas yra kintamieji (vars) ir jie taikomi visiems pagrindiniams kompiuteriams (visiems).

Dizainas taip pat įdomus "{{ user_password | password_hash('sha512') }}". Reikalas tas, kad ansible neįdiegia vartotojo per user_add kaip tai darytumėte rankiniu būdu. Ir jis išsaugo visus duomenis tiesiogiai, todėl mes taip pat turime iš anksto konvertuoti slaptažodį į maišą, ką ši komanda daro.

Pridėkime savo vartotoją į sudo grupę. Tačiau prieš tai turime įsitikinti, kad tokia grupė egzistuoja, nes niekas už mus to nepadarys:

---
- 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"

Viskas gana paprasta, turime ir grupinį modulį grupėms kurti, kurio sintaksė labai panaši į apt. Tada pakanka užregistruoti šią grupę vartotojui (groups: "sudo").
Taip pat naudinga prie šio vartotojo pridėti ssh raktą, kad galėtume prisijungti naudodami jį be slaptažodžio:

---
- 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

Šiuo atveju dizainas yra įdomus "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" — nukopijuoja failo id_rsa.pub turinį (jūsų vardas gali skirtis), tai yra, viešąją ssh rakto dalį ir įkelia jį į serverio vartotojo įgaliotų raktų sąrašą.

Vaidmenys

Visas tris naudojimo kūrimo užduotis galima nesunkiai suskirstyti į vieną užduočių grupę, todėl būtų gerai šią grupę laikyti atskirai nuo pagrindinio žaidimo knygos, kad ji neišaugtų per didelė. Šiuo tikslu Ansible turi vaidmenis.
Pagal pačioje pradžioje nurodytą failo struktūrą vaidmenys turi būti dedami į atskirą vaidmenų katalogą, kiekvienam vaidmeniui yra atskiras katalogas tuo pačiu pavadinimu, užduočių, failų, šablonų ir tt kataloge
Sukurkime failo struktūrą: ./ansible/roles/user/tasks/main.yml (pagrindinis yra pagrindinis failas, kuris bus įkeltas ir vykdomas, kai vaidmuo bus prijungtas prie žaidimo knygos; prie jo galima prijungti kitus vaidmenų failus). Dabar visas su vartotoju susijusias užduotis galite perkelti į šį failą:

# 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

Pagrindiniame žaidimo knygelėje turite nurodyti, kad naudotumėte vartotojo vaidmenį:

---
- 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

Be to, gali būti prasminga atnaujinti sistemą prieš visas kitas užduotis; norėdami tai padaryti, galite pervardyti bloką tasks kurioje jie apibrėžti pre_tasks.

Nginx nustatymas

„Nginx“ jau turėtų būti įdiegtas; turime jį sukonfigūruoti ir paleisti. Padarykime tai iš karto vaidmenyje. Sukurkime failo struktūrą:

- ansible
  - roles
    - nginx
      - files
      - tasks
        - main.yml
      - templates

Dabar mums reikia failų ir šablonų. Skirtumas tarp jų yra tas, kad ansible tiesiogiai kopijuoja failus, kaip yra. Šablonai turi turėti j2 plėtinį ir gali naudoti kintamąsias reikšmes naudodami tuos pačius dvigubus riestinius skliaustus.

Įgalinkime nginx main.yml failą. Tam turime sisteminį modulį:

# Copy nginx configs and start it
- name: enable service nginx and start
  systemd:
    name: nginx
    state: started
    enabled: yes

Čia mes ne tik sakome, kad nginx turi būti paleistas (tai yra, paleidžiame), bet iš karto sakome, kad jis turi būti įjungtas.
Dabar nukopijuokime konfigūracijos failus:

# 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'

Sukuriame pagrindinį nginx konfigūracijos failą (galite paimti tiesiai iš serverio arba parašyti patys). Taip pat mūsų programos konfigūracijos failas kataloge sites_available (tai nėra būtina, bet naudinga). Pirmuoju atveju failams kopijuoti naudojame kopijavimo modulį (failas turi būti /ansible/roles/nginx/files/nginx.conf). Antrajame nukopijuojame šabloną, pakeisdami kintamųjų reikšmes. Šablonas turi būti /ansible/roles/nginx/templates/my_app.j2). Ir tai gali atrodyti maždaug taip:

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 }};
  ....
}

Atkreipkite dėmesį į įdėklus {{ app_name }}, {{ app_path }}, {{ server_name }}, {{ inventory_hostname }} — tai visi kintamieji, kurių reikšmės Ansible pakeis šabloną prieš kopijuojant. Tai naudinga, jei naudojate skirtingų šeimininkų grupių žaidimų knygą. Pavyzdžiui, galime pridėti savo inventoriaus failą:

[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

Jei dabar paleisime savo grojaraštį, jis atliks nurodytas užduotis abiem pagrindiniams kompiuteriams. Tačiau tuo pačiu metu rengiančiojo kintamieji skirsis nuo gamybinių ir ne tik vaidmenyse ir žaidimų knygelėse, bet ir nginx konfigūracijose. {{ inventory_hostname }} inventorinėje byloje nurodyti nereikia – š specialus galimas kintamasis ir ten saugomas pagrindinis kompiuteris, kuriam šiuo metu veikia žaidimų knyga.
Jei norite turėti kelių kompiuterių inventoriaus failą, bet paleisti tik vienai grupei, tai galite padaryti naudodami šią komandą:

ansible-playbook -i inventory ./playbook.yml -l "staging"

Kita galimybė yra turėti atskirus inventoriaus failus skirtingoms grupėms. Arba galite derinti abu metodus, jei turite daug skirtingų šeimininkų.

Grįžkime prie nginx nustatymo. Nukopijavę konfigūracijos failus, turime sukurti nuorodą sitest_enabled į my_app.conf iš sites_available. Ir paleiskite nginx iš naujo.

... # 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

Čia viskas paprasta - vėlgi galimi moduliai su gana standartine sintaksė. Tačiau yra vienas dalykas. Nėra prasmės kiekvieną kartą paleisti nginx iš naujo. Ar pastebėjote, kad mes nerašome tokių komandų kaip: „daryk tai taip“, sintaksė labiau atrodo kaip „tai turėtų turėti tokią būseną“. Ir dažniausiai ansible veikia būtent taip. Jei grupė jau yra arba sistemos paketas jau įdiegtas, ansible patikrins, ar tai nėra, ir praleis užduotį. Be to, failai nebus nukopijuoti, jei jie visiškai atitiks tai, kas jau yra serveryje. Galime tuo pasinaudoti ir iš naujo paleisti nginx tik tuo atveju, jei buvo pakeisti konfigūracijos failai. Tam yra registro direktyva:

# 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

Jei pasikeičia vienas iš konfigūracijos failų, bus padaryta kopija ir kintamasis bus užregistruotas restart_nginx. Ir tik tada, kai šis kintamasis buvo užregistruotas, paslauga bus paleista iš naujo.

Ir, žinoma, nginx vaidmenį turite įtraukti į pagrindinį žaidimų knygą.

Postgresql nustatymas

Turime įjungti postgresql naudodami systemd taip pat, kaip tai padarėme su nginx, taip pat sukurti vartotoją, kurį naudosime norėdami pasiekti duomenų bazę ir pačią duomenų bazę.
Sukurkime vaidmenį /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 }}"

Neapibūdinsiu, kaip pridėti kintamuosius į inventorių, tai jau buvo padaryta daug kartų, taip pat postgresql_db ir postgresql_user modulių sintaksė. Daugiau informacijos rasite dokumentacijoje. Įdomiausia direktyva čia yra become_user: postgres. Faktas yra tas, kad pagal numatytuosius nustatymus tik „postgres“ vartotojas turi prieigą prie „postgresql“ duomenų bazės ir tik lokaliai. Ši direktyva leidžia mums vykdyti komandas šio vartotojo vardu (jei turime prieigą, žinoma).
Be to, prie pg_hba.conf gali tekti pridėti eilutę, kad naujas vartotojas galėtų pasiekti duomenų bazę. Tai galima padaryti taip pat, kaip mes pakeitėme nginx konfigūraciją.

Ir, žinoma, turite pridėti postgresql vaidmenį į pagrindinį žaidimų knygą.

Rubino diegimas per rbenv

Ansible neturi modulių darbui su rbenv, bet jis įdiegtas klonuojant git saugyklą. Todėl ši problema tampa pati nestandartiškiausia. Sukurkime jai vaidmenį /ansible/roles/ruby_rbenv/main.yml ir pradėkime pildyti:

# Install rbenv and ruby
- name: Install rbenv
  become_user: "{{ user }}"
  git: repo=https://github.com/rbenv/rbenv.git dest=~/.rbenv

Mes vėl naudojame direktyvą tapti_vartotoju, kad veiktų pagal vartotoją, kurį sukūrėme šiems tikslams. Kadangi rbenv yra įdiegtas savo namų kataloge, o ne visame pasaulyje. Taip pat naudojame git modulį saugyklai klonuoti, nurodydami repo ir pask.

Tada turime užregistruoti rbenv init į bashrc ir pridėti rbenv prie PATH. Tam turime lineinfile modulį:

- 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 -)"'

Tada turite įdiegti ruby_build:

- name: Install ruby-build
  become_user: "{{ user }}"
  git: repo=https://github.com/rbenv/ruby-build.git dest=~/.rbenv/plugins/ruby-build

Ir galiausiai įdiekite rubiną. Tai atliekama per rbenv, tai yra tiesiog naudojant bash komandą:

- name: Install ruby
  become_user: "{{ user }}"
  shell: |
    export PATH="${HOME}/.rbenv/bin:${PATH}"
    eval "$(rbenv init -)"
    rbenv install {{ ruby_version }}
  args:
    executable: /bin/bash

Mes sakome, kurią komandą vykdyti ir su kokia. Tačiau čia susiduriame su tuo, kad ansible nepaleidžia kodo, esančio bashrc prieš paleisdamas komandas. Tai reiškia, kad rbenv turės būti apibrėžtas tiesiogiai tame pačiame scenarijuje.

Kita problema kyla dėl to, kad apvalkalo komanda neturi jokios būsenos iš galimo požiūrio taško. Tai reiškia, kad nebus automatinio patikrinimo, ar ši rubino versija įdiegta, ar ne. Tai galime padaryti patys:

- 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

Belieka įdiegti paketėlį:

- name: Install bundler
  become_user: "{{ user }}"
  shell: |
    export PATH="${HOME}/.rbenv/bin:${PATH}"
    eval "$(rbenv init -)"
    gem install bundler

Ir vėl pridėkite mūsų vaidmenį ruby_rbenv prie pagrindinio žaidimo knygos.

Bendrinami failai.

Apskritai sąranka gali būti baigta čia. Toliau belieka paleisti capistrano ir jis pats nukopijuos kodą, sukurs reikiamus katalogus ir paleis programą (jei viskas sukonfigūruota teisingai). Tačiau capistrano dažnai reikalauja papildomų konfigūracijos failų, pvz database.yml arba .env Juos galima nukopijuoti kaip ir nginx failus bei šablonus. Yra tik vienas subtilumas. Prieš kopijuodami failus, turite sukurti jiems katalogų struktūrą, maždaug taip:

# Copy shared files for deploy
- name: Ensure shared dir
  become_user: "{{ user }}"
  file:
    path: "{{ app_path }}/shared/config"
    state: directory

nurodome tik vieną katalogą ir prireikus ansible automatiškai sukurs pirminius.

Ansible Vault

Jau susidūrėme su tuo, kad kintamuosiuose gali būti slaptų duomenų, tokių kaip vartotojo slaptažodis. Jei sukūrėte .env paraiškos failą ir database.yml tada tokių kritinių duomenų turi būti dar daugiau. Būtų gerai juos paslėpti nuo pašalinių akių. Šiuo tikslu jis naudojamas galimas skliautas.

Sukurkime failą kintamiesiems /ansible/vars/all.yml (čia galite sukurti skirtingus failus skirtingoms kompiuterių grupėms, kaip ir inventoriaus faile: production.yml, staging.yml ir tt).
Visi kintamieji, kuriuos reikia užšifruoti, turi būti perkelti į šį failą naudojant standartinę yml sintaksę:

# 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

Po to šis failas gali būti užšifruotas komanda:

ansible-vault encrypt ./vars/all.yml

Natūralu, kad šifruodami turėsite nustatyti iššifravimo slaptažodį. Iškvietę šią komandą galite pamatyti, kas bus failo viduje.

Pasinaudojant ansible-vault decrypt failą galima iššifruoti, modifikuoti ir vėl užšifruoti.

Kad veiktų, failo iššifruoti nereikia. Saugote jį užšifruotą ir paleidžiate žaidimų knygą su argumentu --ask-vault-pass. Ansible paprašys slaptažodžio, nuskaitys kintamuosius ir vykdys užduotis. Visi duomenys liks užšifruoti.

Visa komanda kelioms prieglobos grupėms ir ansible saugykla atrodys maždaug taip:

ansible-playbook -i inventory ./playbook.yml -l "staging" --ask-vault-pass

Bet aš jums nepateiksiu viso pjesių ir vaidmenų tekstų, rašykite patys. Nes ansible yra toks - jei nesupranti, ką reikia padaryti, tai jis to nepadarys už tave.

Šaltinis: www.habr.com

Добавить комментарий