Szerver beállítása Rails alkalmazás telepítéséhez az Ansible használatával

Nemrég több Ansible-játékkönyvet kellett írnom, hogy felkészítsem a szervert egy Rails alkalmazás telepítésére. És meglepő módon nem találtam egyszerű, lépésről lépésre útmutatót. Nem akartam valaki más játékkönyvét másolni anélkül, hogy megértettem volna, mi történik, és végül el kellett olvasnom a dokumentációt, mindent magamnak gyűjtve. Talán segíthetek valakinek felgyorsítani ezt a folyamatot ennek a cikknek a segítségével.

Az első dolog, amit meg kell érteni, az az, hogy az ansible kényelmes felületet biztosít a műveletek előre meghatározott listájának végrehajtásához egy távoli szerver(ek)en SSH-n keresztül. Nincs itt semmi varázslat, nem telepíthet beépülő modult, és nem kaphatja meg az alkalmazás leállás nélküli üzembe helyezését dockerrel, felügyelettel és egyéb cuccokkal. Ahhoz, hogy játékkönyvet írhass, tudnod kell, hogy pontosan mit és hogyan kell csinálni. Ezért nem vagyok megelégedve a GitHub kész játékkönyveivel vagy az olyan cikkekkel, mint például: „Másolja és futtassa, működni fog.”

Mire van szükségünk?

Ahogy már mondtam, ahhoz, hogy játékkönyvet írhass, tudnod kell, mit és hogyan kell csinálni. Döntsük el, mire van szükségünk. Egy Rails alkalmazáshoz több rendszercsomagra lesz szükségünk: nginx, postgresql (redis stb.). Ezenkívül szükségünk van a rubin egy speciális változatára. A legjobb az rbenv-n keresztül telepíteni (rvm, asdf...). Mindezt root felhasználóként futtatni mindig rossz ötlet, ezért külön felhasználót kell létrehozni, és be kell állítani a jogait. Ezek után fel kell töltened a kódunkat a szerverre, át kell másolnod az nginx, postgres stb. konfigurációit, és el kell indítanod ezeket a szolgáltatásokat.

Ennek eredményeként a műveletek sorrendje a következő:

  1. Jelentkezzen be rootként
  2. telepítse a rendszercsomagokat
  3. új felhasználó létrehozása, jogok konfigurálása, ssh kulcs
  4. konfigurálja a rendszercsomagokat (nginx stb.), és futtassa őket
  5. Felhasználót hozunk létre az adatbázisban (azonnal létrehozhat adatbázist)
  6. Jelentkezzen be új felhasználóként
  7. Telepítse az rbenv-t és a rubyt
  8. A kötegelő telepítése
  9. Az alkalmazás kódjának feltöltése
  10. A Puma szerver indítása

Sőt, az utolsó szakaszokat a capistrano segítségével is meg lehet tenni, legalábbis a dobozból ki tud másolni kódot kiadási könyvtárakba, sikeres telepítés esetén symlink-el váltani a kiadást, megosztott könyvtárból másolni a konfigurációkat, újraindítani a pumát stb. Mindez megtehető az Ansible segítségével, de miért?

Fájlszerkezet

Az Ansible szigorú fájlszerkezet az összes fájlhoz, ezért a legjobb, ha mindezt külön könyvtárban tárolja. Sőt, az sem olyan fontos, hogy magában a sín alkalmazásban lesz-e, vagy külön. A fájlokat külön git-tárolóban tárolhatja. Személy szerint a legkényelmesebbnek találtam egy lehetséges könyvtárat létrehozni a rails alkalmazás /config könyvtárában, és mindent egy tárolóban tárolni.

Egyszerű játékkönyv

A Playbook egy yml fájl, amely speciális szintaxissal leírja, mit és hogyan kell tennie az Ansible-nek. Hozzuk létre az első olyan játékkönyvet, amely nem csinál semmit:

---
- name: Simple playbook
  hosts: all

Itt egyszerűen azt mondjuk, hogy a mi játékkönyvünk ún Simple Playbook és hogy a tartalmát minden gazdagépen végre kell hajtani. A névvel az /ansible könyvtárba menthetjük playbook.yml és próbálj futni:

ansible-playbook ./playbook.yml

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

Az Ansible azt mondja, hogy nem ismer olyan gazdagépeket, amelyek megfelelnek az összes listának. Ezeket külön listában kell feltüntetni leltári fájl.

Hozzuk létre ugyanabban a lehetséges könyvtárban:

123.123.123.123

Így egyszerűen megadjuk a gazdagépet (ideális esetben a VPS-ünk gazdagépét teszteléshez, vagy regisztrálhat localhost-ot), és elmentjük néven inventory.
Megpróbálhatja az ansible futtatását egy leltárfájllal:

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

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

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

Ha rendelkezik ssh hozzáféréssel a megadott gazdagéphez, akkor az ansible csatlakozik és információkat gyűjt a távoli rendszerről. (alapértelmezett FELADAT [Tények gyűjtése]), amely után rövid jelentést ad a végrehajtásról (PLAY RECAP).

Alapértelmezés szerint a kapcsolat azt a felhasználónevet használja, amellyel bejelentkezett a rendszerbe. Valószínűleg nem lesz a gazdagépen. A playbook fájlban megadhatja, hogy melyik felhasználó csatlakozzon a remote_user direktívával. Ezenkívül a távoli rendszerrel kapcsolatos információk gyakran szükségtelenek lehetnek az Ön számára, és nem szabad időt pazarolnia az összegyűjtésére. Ez a feladat le is tiltható:

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

Próbálja meg újra futtatni a forgatókönyvet, és ellenőrizze, hogy működik-e a kapcsolat. (Ha a root felhasználót adtad meg, akkor a bevált: true direktívát is meg kell adnod a magasabb jogosultságok megszerzéséhez. A dokumentációban leírtak szerint: become set to ‘true’/’yes’ to activate privilege escalation. bár nem teljesen világos, hogy miért).

Talán hibaüzenetet kap, amelyet az okoz, hogy az ansible nem tudja meghatározni a Python értelmezőt, akkor manuálisan megadhatja:

ansible_python_interpreter: /usr/bin/python3 

A paranccsal megtudhatja, hol van a python whereis python.

Rendszercsomagok telepítése

Az Ansible szabványos disztribúciója számos modult tartalmaz a különféle rendszercsomagokkal való munkavégzéshez, így semmilyen okból nem kell bash szkripteket írnunk. Most ezekre a modulokra van szükségünk a rendszer frissítéséhez és a rendszercsomagok telepítéséhez. Ubuntu Linux van a VPS-emen, így az általam használt csomagok telepítéséhez apt-get и modul hozzá. Ha más operációs rendszert használ, akkor lehet, hogy más modulra lesz szüksége (ne feledje, az elején mondtam, hogy előre tudnunk kell, mit és hogyan fogunk csinálni). A szintaxis azonban valószínűleg hasonló lesz.

Egészítsük ki a füzetünket az első feladatokkal:

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

A feladat pontosan az a feladat, amelyet az Ansible távoli szervereken hajt végre. A feladatnak nevet adunk, hogy a naplóban nyomon tudjuk követni a végrehajtását. És egy adott modul szintaxisával leírjuk, mit kell tennie. Ebben az esetben apt: update_cache=yes - azt mondja, hogy frissítse a rendszercsomagokat az apt modul segítségével. A második parancs egy kicsit bonyolultabb. Átadjuk a csomagok listáját az apt modulnak, és azt mondjuk, hogy azok state válnia kell present, vagyis azt mondjuk, hogy telepítsük ezeket a csomagokat. Hasonló módon megmondhatjuk nekik, hogy töröljék vagy egyszerűen módosítsák őket state. Kérjük, vegye figyelembe, hogy ahhoz, hogy a sínek működjenek a postgresql-lel, szükségünk van a postgresql-contrib csomagra, amelyet most telepítünk. Ezt ismét tudnod kell és meg kell tenned; az Ansible önmagában ezt nem fogja megtenni.

Próbálja meg újra futtatni a playbookot, és ellenőrizze, hogy a csomagok telepítve vannak-e.

Új felhasználók létrehozása.

A felhasználókkal való együttműködéshez az Ansible-nek van egy modulja is - user. Adjunk hozzá még egy feladatot (a játékkönyv már ismert részeit elrejtettem a megjegyzések mögé, nehogy minden alkalommal teljesen lemásoljuk):

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

Létrehozunk egy új felhasználót, beállítunk neki egy shellt és jelszót. És akkor több problémába ütközünk. Mi a teendő, ha a felhasználóneveknek eltérőnek kell lenniük a különböző gazdagépeknél? A jelszót tiszta szövegben tárolni a játékkönyvben pedig nagyon rossz ötlet. Kezdésként tegyük változókba a felhasználónevet és a jelszót, és a cikk vége felé megmutatom, hogyan kell titkosítani a jelszót.

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

A változók beállítása a játékfüzetekben dupla kapcsos kapcsos zárójelekkel történik.

A leltárfájlban feltüntetjük a változók értékeit:

123.123.123.123

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

Kérjük, vegye figyelembe az irányelvet [all:vars] - azt mondja, hogy a következő szövegblokk a változók (vars), és ezek az összes gazdagépre (all) vonatkoznak.

A dizájn is érdekes "{{ user_password | password_hash('sha512') }}". Az a helyzet, hogy az ansible nem ezen keresztül telepíti a felhasználót user_add mintha kézzel tenné. És minden adatot közvetlenül ment el, ezért a jelszót is előzetesen hash-be kell konvertálnunk, amit ez a parancs tesz.

Adjuk hozzá a felhasználónkat a sudo csoporthoz. Előtte azonban meg kell győződnünk arról, hogy létezik ilyen csoport, mert ezt senki nem fogja megtenni helyettünk:

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

Minden nagyon egyszerű, van egy csoport modulunk is a csoportok létrehozására, szintaxisa nagyon hasonlít az apt-hez. Ezután elég regisztrálni ezt a csoportot a felhasználóhoz (groups: "sudo").
Az is hasznos, ha ehhez a felhasználóhoz ssh kulcsot adunk, hogy ezzel jelszó nélkül tudjunk bejelentkezni:

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

Ebben az esetben a design érdekes "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" — lemásolja az id_rsa.pub fájl tartalmát (a neved eltérhet), vagyis az ssh kulcs nyilvános részét, és feltölti a szerveren a felhasználó számára engedélyezett kulcsok listájára.

szerep

Mindhárom felhasználási feladatot könnyen be lehet sorolni egy feladatcsoportba, és ezt a csoportot célszerű a fő füzettől elkülönítve tárolni, hogy ne nőjön túl nagyra. Erre a célra az Ansible rendelkezik szerepek.
A legelején jelzett fájlstruktúra szerint a szerepköröket külön szerepkönyvtárba kell elhelyezni, minden szerephez külön azonos nevű könyvtár tartozik, a feladatok, fájlok, sablonok stb. könyvtárán belül
Hozzunk létre egy fájlstruktúrát: ./ansible/roles/user/tasks/main.yml (a main az a fő fájl, amely betöltődik és végrehajtódik, amikor egy szerep kapcsolódik a játékfüzethez; más szerepfájlok is csatlakoztathatók hozzá). Most átviheti a felhasználóval kapcsolatos összes feladatot ebbe a fájlba:

# 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

A fő útmutatóban meg kell adnia a felhasználói szerepkör használatát:

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

Ezenkívül érdemes lehet a rendszert minden más feladat előtt frissíteni; ehhez átnevezheti a blokkot tasks amelyben meghatározásra kerülnek pre_tasks.

Az nginx beállítása

Az Nginx-nek már telepítve kell lennie; konfigurálnunk kell és futtatnunk kell. Tegyük meg azonnal a szerepben. Hozzunk létre egy fájlstruktúrát:

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

Most fájlokra és sablonokra van szükségünk. A különbség köztük az, hogy az ansible közvetlenül másolja a fájlokat, ahogy vannak. A sablonoknak j2 kiterjesztéssel kell rendelkezniük, és ugyanazt a dupla kapcsos zárójelet használva változó értékeket használhatnak.

Engedélyezzük az nginx-et main.yml fájlt. Ehhez van egy systemd modulunk:

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

Itt nem csak azt mondjuk, hogy az nginx-et el kell indítani (vagyis elindítjuk), hanem rögtön azt mondjuk, hogy engedélyezni kell.
Most másoljuk a konfigurációs fájlokat:

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

Létrehozzuk a fő nginx konfigurációs fájlt (leveheti közvetlenül a szerverről, vagy megírhatja saját maga). És az alkalmazásunk konfigurációs fájlja is a sites_available könyvtárban (ez nem szükséges, de hasznos). Az első esetben a másoló modult használjuk a fájlok másolására (a fájlnak be kell lennie /ansible/roles/nginx/files/nginx.conf). A másodikban másoljuk a sablont, helyettesítve a változók értékeit. A sablonnak benne kell lennie /ansible/roles/nginx/templates/my_app.j2). És valahogy így nézhet ki:

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

Ügyeljen a betétekre {{ app_name }}, {{ app_path }}, {{ server_name }}, {{ inventory_hostname }} — ezek mind azok a változók, amelyek értékeit az Ansible behelyettesíti a sablonba a másolás előtt. Ez akkor hasznos, ha játékkönyvet használ a házigazdák különböző csoportjaihoz. Például hozzáadhatjuk a leltárfájlunkat:

[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

Ha most elindítjuk a játékkönyvünket, akkor mindkét gazdagépnél elvégzi a megadott feladatokat. Ugyanakkor egy staging host esetében a változók eltérnek a produkcióstól, és nem csak a szerepekben és a játékkönyvekben, hanem az nginx konfigurációkban is. {{ inventory_hostname }} nem kell megadni a leltárfájlban - ezt speciális lehetséges változó és ott van tárolva az a gazdagép, amelyen a játékkönyv éppen fut.
Ha több gazdagéphez szeretne egy leltárfájlt, de csak egy csoportra fut, ezt a következő paranccsal teheti meg:

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

Egy másik lehetőség, hogy a különböző csoportokhoz külön leltárfájlokat készítsen. Vagy kombinálhatja a két megközelítést, ha sok különböző gazdagépe van.

Térjünk vissza az nginx beállításához. A konfigurációs fájlok másolása után létre kell hoznunk egy szimbolikus hivatkozást a sitest_enabled fájlban a my_app.conf fájlra a sites_available fájlból. És indítsa újra az nginx-et.

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

Itt minden egyszerű - ismét elérhető modulok meglehetősen szabványos szintaxissal. De van egy pont. Nincs értelme minden alkalommal újraindítani az nginxet. Észrevetted, hogy nem írunk ki olyan parancsokat, mint: „tegye ezt így”, a szintaxis inkább úgy néz ki, mint „ennek ilyennek kell lennie”. És legtöbbször pontosan így működik az ansible. Ha a csoport már létezik, vagy a rendszercsomag már telepítve van, akkor az ansible ellenőrzi ezt, és kihagyja a feladatot. Ezenkívül a fájlok nem kerülnek másolásra, ha azok teljesen megegyeznek a kiszolgálón lévővel. Ezt csak akkor tudjuk kihasználni és újraindítani az nginxet, ha a konfigurációs fájlok megváltoztak. Erre van egy regisztrációs direktíva:

# 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

Ha valamelyik konfigurációs fájl megváltozik, a rendszer másolatot készít és a változót regisztrálja restart_nginx. És csak akkor indul újra a szolgáltatás, ha ez a változó regisztrálva van.

És természetesen hozzá kell adnia az nginx szerepet a fő játékkönyvhöz.

A postgresql beállítása

Engedélyeznünk kell a postgresql-t a systemd használatával ugyanúgy, mint az nginx-nél, és létre kell hoznunk egy felhasználót, amellyel elérjük az adatbázist és magát az adatbázist.
Hozzunk létre egy szerepet /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 }}"

Nem írom le, hogyan kell változókat hozzáadni a készlethez, ezt már sokszor megtették, valamint a postgresql_db és a postgresql_user modulok szintaxisát. További információk a dokumentációban találhatók. A legérdekesebb irányelv itt az become_user: postgres. A helyzet az, hogy alapértelmezés szerint csak a postgres felhasználó fér hozzá a postgresql adatbázishoz és csak helyileg. Ez a direktíva lehetővé teszi számunkra, hogy parancsokat hajtsunk végre a felhasználó nevében (természetesen ha van hozzáférésünk).
Ezenkívül előfordulhat, hogy hozzá kell adnia egy sort a pg_hba.conf fájlhoz, hogy új felhasználók hozzáférjenek az adatbázishoz. Ezt ugyanúgy megtehetjük, ahogy az nginx konfigurációt megváltoztattuk.

És természetesen hozzá kell adni a postgresql szerepkört a fő forgatókönyvhöz.

A ruby ​​telepítése az rbenv-n keresztül

Az Ansible nem rendelkezik az rbenv-vel való együttműködéshez szükséges modulokkal, de egy git tároló klónozásával telepíthető. Ezért ez a probléma a leginkább nem szabványos. Alkossunk neki szerepet /ansible/roles/ruby_rbenv/main.yml és kezdjük kitölteni:

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

Ismét a bejövő_felhasználó direktívát használjuk az általunk erre a célra létrehozott felhasználóra. Mivel az rbenv a saját könyvtárába van telepítve, és nem globálisan. És a git modult is használjuk a tár klónozására, megadva a repo és a dest.

Ezután regisztrálnunk kell az rbenv init-et a bashrc-ban, és hozzá kell adnunk az rbenv-t a PATH-hoz. Ehhez a lineinfile modulunk van:

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

Ezután telepítenie kell a ruby_build programot:

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

És végül telepítse a rubint. Ez az rbenv-n keresztül történik, vagyis egyszerűen a bash paranccsal:

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

Megmondjuk, hogy melyik parancsot kell végrehajtani és mivel. Itt azonban azzal a ténnyel találkozunk, hogy az ansible nem futtatja le a bashrc-ban található kódot a parancsok futtatása előtt. Ez azt jelenti, hogy az rbenv-t közvetlenül ugyanabban a szkriptben kell meghatározni.

A következő probléma abból adódik, hogy a shell parancsnak nincs állapota lehetséges szempontból. Vagyis nem lesz automatikus ellenőrzés, hogy a rubin ezen verziója telepítve van-e vagy sem. Ezt magunk is megtehetjük:

- 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

Már csak a bundler telepítése van hátra:

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

És ismét add hozzá a ruby_rbenv szerepünket a fő játékkönyvhöz.

Megosztott fájlok.

Általában a beállítás itt befejezhető. Ezután már csak a capistrano futtatása van hátra, és magát a kódot másolja, létrehozza a szükséges könyvtárakat, és elindítja az alkalmazást (ha minden megfelelően van beállítva). A capistrano azonban gyakran további konfigurációs fájlokat igényel, mint pl database.yml vagy .env Ugyanúgy másolhatók, mint az nginx fájljai és sablonjai. Csak egy finomság van. Fájlok másolása előtt létre kell hoznia egy könyvtárstruktúrát, valami ilyesmit:

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

csak egy könyvtárat adunk meg, és az ansible automatikusan létrehozza a szülőkönyvtárakat, ha szükséges.

Ansible Vault

Már találkozhattunk azzal, hogy a változók titkos adatokat tartalmazhatnak, például a felhasználó jelszavát. Ha létrehoztad .env fájl a pályázathoz, és database.yml akkor még több olyan kritikus adatnak kell lennie. Jó lenne elrejteni őket a kíváncsi szemek elől. Erre a célra használják lehetséges boltozat.

Hozzunk létre egy fájlt a változókhoz /ansible/vars/all.yml (itt különböző fájlokat hozhat létre a különböző gazdagépcsoportokhoz, akárcsak a leltárfájlban: production.yml, staging.yml stb.).
Minden titkosítandó változót át kell vinni ebbe a fájlba szabvány yml szintaxissal:

# 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

Ezt követően a fájl titkosítható a következő paranccsal:

ansible-vault encrypt ./vars/all.yml

Természetesen titkosításkor jelszót kell beállítania a visszafejtéshez. A parancs meghívása után láthatja, hogy mi lesz a fájlban.

Révén ansible-vault decrypt a fájl visszafejthető, módosítható, majd újra titkosítható.

Nem kell visszafejteni a fájlt a működéshez. Titkosítva tárolja, és futtatja a játékkönyvet az argumentummal --ask-vault-pass. Az Ansible kéri a jelszót, lekéri a változókat, és végrehajtja a feladatokat. Minden adat titkosítva marad.

A több gazdagépcsoport és az ansible vault teljes parancsa így fog kinézni:

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

De nem adom meg a játékkönyvek és szerepek teljes szövegét, írd meg magad. Mert az ansible ilyen - ha nem érted, mit kell tenned, akkor nem fogja megtenni helyetted.

Forrás: will.com

Hozzászólás