Ansible istifadə edərək Rails Tətbiqini Yerləşdirmək üçün Serverin Konfiqurasiyası

Bir müddət əvvəl mən serveri Rails tətbiqini yerləşdirməyə hazırlamaq üçün bir neçə Ansible kitabçası yazmalı oldum. Və təəccüblüdür ki, sadə bir addım-addım təlimat tapmadım. Nə baş verdiyini başa düşmədən başqasının oyun kitabını köçürmək istəmədim və sonda hər şeyi özüm toplayıb sənədləri oxumalı oldum. Bəlkə də bu məqalənin köməyi ilə kiməsə bu prosesi sürətləndirməyə kömək edə bilərəm.

Anlamaq lazım olan ilk şey odur ki, ansible sizə SSH vasitəsilə uzaq server(lər)də əvvəlcədən müəyyən edilmiş hərəkətlərin siyahısını yerinə yetirmək üçün rahat interfeys təqdim edir. Burada heç bir sehr yoxdur, siz plagin quraşdıra bilməzsiniz və docker, monitorinq və qutudan çıxarılan digər ləzzətlər ilə tətbiqinizin sıfır dayanıqlı yerləşdirilməsini əldə edə bilməzsiniz. Bir oyun kitabı yazmaq üçün siz tam olaraq nə etmək istədiyinizi və bunu necə edəcəyinizi bilməlisiniz. Buna görə də məni GitHub-dan hazır dərs kitabları və ya “Kopyala və işlət, işləyəcək” kimi məqalələr qane etmir.

Bizə nə lazımdır?

Artıq dediyim kimi, oyun kitabı yazmaq üçün nə etmək istədiyinizi və bunu necə edəcəyinizi bilməlisiniz. Nəyə ehtiyacımız olduğuna qərar verək. Rails tətbiqi üçün bizə bir neçə sistem paketi lazımdır: nginx, postgresql (redis və s.). Bundan əlavə, bizə ruby-nin xüsusi bir versiyası lazımdır. Ən yaxşısı onu rbenv (rvm, asdf...) vasitəsilə quraşdırmaqdır. Bütün bunları kök istifadəçi kimi işlətmək həmişə pis fikirdir, ona görə də ayrıca istifadəçi yaratmalı və onun hüquqlarını konfiqurasiya etməlisiniz. Bundan sonra kodumuzu serverə yükləməli, nginx, postgres və s. üçün konfiqurasiyaları köçürməli və bütün bu xidmətləri işə salmalısınız.

Nəticədə, hərəkətlərin ardıcıllığı aşağıdakı kimidir:

  1. Kök kimi daxil olun
  2. sistem paketlərini quraşdırın
  3. yeni istifadəçi yaradın, hüquqları konfiqurasiya edin, ssh açarı
  4. sistem paketlərini (nginx və s.) konfiqurasiya edin və onları işə salın
  5. Verilənlər bazasında istifadəçi yaradırıq (dərhal verilənlər bazası yarada bilərsiniz)
  6. Yeni istifadəçi kimi daxil olun
  7. Rbenv və Ruby quraşdırın
  8. Bundler quraşdırılması
  9. Tətbiq kodu yüklənir
  10. Puma serverinin işə salınması

Üstəlik, son mərhələlər capistrano istifadə edərək həyata keçirilə bilər, ən azı qutudan kənarda kodu buraxılış qovluqlarına köçürə bilər, müvəffəqiyyətli yerləşdirmədən sonra buraxılışı simvolik əlaqə ilə dəyişdirə, konfiqurasiyaları paylaşılan qovluqdan köçürə, pumanı yenidən başladın və s. Bütün bunlar Ansible vasitəsilə edilə bilər, bəs niyə?

Fayl strukturu

Ansible sərtdir fayl strukturu bütün fayllarınız üçün, ona görə də hamısını ayrı bir kataloqda saxlamaq yaxşıdır. Üstəlik, rels tətbiqinin özündə və ya ayrıca olması o qədər də vacib deyil. Faylları ayrıca git deposunda saxlaya bilərsiniz. Şəxsən mən rails tətbiqinin /config kataloqunda ansible kataloq yaratmaq və hər şeyi bir depoda saxlamağı ən əlverişli hesab etdim.

Sadə oyun kitabı

Playbook xüsusi sintaksisdən istifadə edərək Ansible-ın nə etməli olduğunu və necə edəcəyini təsvir edən yml faylıdır. Heç bir şey etməyən ilk oyun kitabını yaradaq:

---
- name: Simple playbook
  hosts: all

Burada sadəcə olaraq oyun kitabımızın adlandığını söyləyirik Simple Playbook və onun məzmunu bütün hostlar üçün icra edilməlidir. Biz onu /ansible qovluğunda adı ilə saxlaya bilərik playbook.yml və qaçmağa çalışın:

ansible-playbook ./playbook.yml

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

Ansible deyir ki, bütün siyahıya uyğun gələn hostları tanımır. Onlar xüsusi siyahıda göstərilməlidir inventar faylı.

Gəlin onu eyni ansible kataloqda yaradaq:

123.123.123.123

Biz sadəcə olaraq hostu (test üçün VPS-nin aparıcısı və ya siz localhost-u qeydiyyatdan keçirə bilərsiniz) necə müəyyənləşdiririk və onu ad altında saxlayırıq. inventory.
Siz inventar faylı ilə ansible işləməyə cəhd edə bilərsiniz:

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

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

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

Göstərilən hosta ssh girişiniz varsa, o zaman ansible uzaq sistem haqqında məlumatı birləşdirəcək və toplayacaq. (standart TASK [Faktların toplanması]) bundan sonra icra haqqında qısa hesabat verəcək (RECAP PLAY).

Varsayılan olaraq, əlaqə sistemə daxil olduğunuz istifadəçi adından istifadə edir. Çox güman ki, hostda olmayacaq. Playbook faylında siz remote_user direktivindən istifadə edərək qoşulmaq üçün hansı istifadəçidən istifadə edəcəyinizi təyin edə bilərsiniz. Həmçinin, uzaq sistem haqqında məlumat çox vaxt sizin üçün lazımsız ola bilər və siz onu toplamaq üçün vaxt itirməməlisiniz. Bu tapşırıq da deaktiv edilə bilər:

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

Oyun kitabını yenidən işə salın və əlaqənin işlədiyinə əmin olun. (Əgər siz kök istifadəçini qeyd etmisinizsə, yüksək hüquqlar əldə etmək üçün siz həmçinin olur: true direktivini göstərməlisiniz. Sənədlərdə yazıldığı kimi: become set to ‘true’/’yes’ to activate privilege escalation. səbəb tam aydın olmasa da).

Ola bilsin ki, siz ansible-in Python tərcüməçisini təyin edə bilməməsi ilə əlaqədar xəta alacaqsınız, onda siz onu əl ilə təyin edə bilərsiniz:

ansible_python_interpreter: /usr/bin/python3 

Komanda ilə python-un harada olduğunu öyrənə bilərsiniz whereis python.

Sistem paketlərinin quraşdırılması

Ansible-ın standart paylanması müxtəlif sistem paketləri ilə işləmək üçün bir çox modulları ehtiva edir, ona görə də hər hansı bir səbəbdən bash skriptləri yazmaq məcburiyyətində deyilik. İndi sistemi yeniləmək və sistem paketlərini quraşdırmaq üçün bu modullardan birinə ehtiyacımız var. Mənim VPS-də Ubuntu Linux var, ona görə də istifadə etdiyim paketləri quraşdırmaq üçün apt-get и onun üçün modul. Fərqli əməliyyat sistemindən istifadə edirsinizsə, o zaman başqa modula ehtiyacınız ola bilər (unutmayın, əvvəldə dedim ki, nəyi və necə edəcəyimizi əvvəlcədən bilməliyik). Bununla belə, sintaksis çox güman ki, oxşar olacaq.

Oyun dəftərimizi ilk tapşırıqlarla tamamlayaq:

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

Tapşırıq, Ansible-ın uzaq serverlərdə yerinə yetirəcəyi vəzifədir. Tapşırıqa ad veririk ki, onun icrasını jurnalda izləyə bilək. Və biz konkret modulun sintaksisindən istifadə edərək onun nə etməli olduğunu təsvir edirik. Bu halda apt: update_cache=yes - apt modulundan istifadə edərək sistem paketlərini yeniləməyi söyləyir. İkinci əmr bir az daha mürəkkəbdir. Paketlərin siyahısını apt moduluna ötürürük və onların olduğunu deyirik state çevrilməlidir present, yəni bu paketləri quraşdırın deyirik. Bənzər şəkildə, biz onlara onları silmələrini və ya sadəcə dəyişdirməklə yeniləmələrini söyləyə bilərik state. Nəzərə alın ki, relslərin postgresql ilə işləməsi üçün bizə indi quraşdırdığımız postgresql-contrib paketi lazımdır. Yenə də bunu bilməli və etməlisən; ansible öz başına bunu etməyəcək.

Oyun kitabını yenidən işə salın və paketlərin quraşdırıldığını yoxlayın.

Yeni istifadəçilərin yaradılması.

İstifadəçilərlə işləmək üçün Ansible modulu da var - istifadəçi. Gəlin daha bir tapşırıq əlavə edək (hər dəfə onu tamamilə köçürməmək üçün kitabçanın artıq məlum olan hissələrini şərhlərin arxasında gizlətmişəm):

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

Yeni istifadəçi yaradırıq, onun üçün sxem və parol təyin edirik. Və sonra bir neçə problemlə qarşılaşırıq. Fərqli hostlar üçün istifadəçi adları fərqli olmalıdırsa necə? Və parolu oyun kitabında aydın mətndə saxlamaq çox pis fikirdir. Başlamaq üçün, istifadəçi adı və parolu dəyişənlərə daxil edək və məqalənin sonunda parolun necə şifrələnəcəyini göstərəcəyəm.

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

Dəyişənlər ikiqat buruq mötərizələrdən istifadə edərək oyun kitablarında təyin olunur.

İnventar faylında dəyişənlərin dəyərlərini göstərəcəyik:

123.123.123.123

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

Direktivə diqqət yetirin [all:vars] - növbəti mətn blokunun dəyişənlər (vars) olduğunu və onların bütün hostlara (hamısına) aid olduğunu söyləyir.

Dizaynı da maraqlıdır "{{ user_password | password_hash('sha512') }}". İş ondadır ki, ansible istifadəçini vasitəsilə quraşdırmır user_add bunu əl ilə edəcəyiniz kimi. Və bütün məlumatları birbaşa saxlayır, buna görə də parolu əvvəlcədən hash-a çevirməliyik, bu əmrin etdiyi budur.

İstifadəçimizi sudo qrupuna əlavə edək. Bununla belə, bundan əvvəl belə bir qrupun mövcud olduğundan əmin olmalıyıq, çünki bunu bizim yerimizə heç kim etməyəcək:

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

Hər şey olduqca sadədir, bizdə qruplar yaratmaq üçün bir qrup modulumuz var, sintaksisi apt ilə çox oxşardır. O zaman bu qrupu istifadəçiyə qeydiyyatdan keçirmək kifayətdir (groups: "sudo").
Bu istifadəçiyə ssh açarı əlavə etmək də faydalıdır ki, parol olmadan istifadə edərək daxil ola bilək:

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

Bu vəziyyətdə dizayn maraqlıdır "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" — id_rsa.pub faylının məzmununu (adınız fərqli ola bilər), yəni ssh açarının ictimai hissəsini kopyalayır və serverdə istifadəçi üçün icazə verilən açarlar siyahısına yükləyir.

Roles

İstifadə yaratmaq üçün hər üç tapşırıq asanlıqla bir qrup vəzifəyə təsnif edilə bilər və bu qrupu çox böyütməməsi üçün əsas kitabdan ayrı saxlamaq yaxşı olardı. Bu məqsədlə Ansible var rolları.
Başlanğıcda göstərilən fayl strukturuna uyğun olaraq, rollar ayrıca rollar kataloqunda yerləşdirilməlidir, hər rol üçün eyni adlı ayrıca qovluq var, tapşırıqlar, fayllar, şablonlar və s.
Fayl strukturunu yaradaq: ./ansible/roles/user/tasks/main.yml (əsas, oyun kitabına rol qoşulduqda yüklənəcək və icra ediləcək əsas fayldır; digər rol faylları ona qoşula bilər). İndi istifadəçi ilə əlaqəli bütün tapşırıqları bu fayla köçürə bilərsiniz:

# 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

Əsas oyun kitabında istifadəçi rolundan istifadə etmək üçün qeyd etməlisiniz:

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

Həmçinin, bütün digər tapşırıqlardan əvvəl sistemi yeniləməyin mənası ola bilər, bunu etmək üçün blokun adını dəyişdirə bilərsiniz tasks hansıda onlar müəyyən edilir pre_tasks.

Nginx qurulması

Bizdə artıq Nginx quraşdırılıb, onu konfiqurasiya edib işə salmalıyıq. Gəlin bunu dərhal rolda edək. Fayl strukturunu yaradaq:

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

İndi bizə fayllar və şablonlar lazımdır. Onların arasındakı fərq odur ki, ansible faylları olduğu kimi birbaşa kopyalayır. Şablonlarda j2 uzantısı olmalıdır və onlar eyni cüt qıvrımlı mötərizələrdən istifadə edərək dəyişən dəyərlərdən istifadə edə bilərlər.

Nginx-i aktivləşdirək main.yml fayl. Bunun üçün bir systemd modulumuz var:

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

Burada biz təkcə nginx-in işə salınmalı olduğunu demirik (yəni onu işə salırıq), həm də dərhal onu aktivləşdirmək lazım olduğunu deyirik.
İndi konfiqurasiya fayllarını kopyalayaq:

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

Biz əsas nginx konfiqurasiya faylını yaradırıq (onu birbaşa serverdən götürə və ya özünüz yaza bilərsiniz). Həmçinin sites_available qovluğunda tətbiqimiz üçün konfiqurasiya faylı (bu lazım deyil, lakin faydalıdır). Birinci halda, biz faylları kopyalamaq üçün surət modulundan istifadə edirik (fayl olmalıdır /ansible/roles/nginx/files/nginx.conf). İkincisində, dəyişənlərin dəyərlərini əvəz edərək şablonu kopyalayırıq. Şablon daxil olmalıdır /ansible/roles/nginx/templates/my_app.j2). Və belə bir şey görünə bilər:

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

Əlavələrə diqqət yetirin {{ app_name }}, {{ app_path }}, {{ server_name }}, {{ inventory_hostname }} — bunlar kopyalamadan əvvəl Ansible-in şablonda əvəzlənəcəyi bütün dəyişənlərdir. Müxtəlif host qrupları üçün oyun kitabından istifadə etsəniz, bu faydalıdır. Məsələn, biz inventar faylımızı əlavə edə bilərik:

[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

İndi playbookumuzu işə salsaq, o, hər iki host üçün müəyyən edilmiş tapşırıqları yerinə yetirəcək. Ancaq eyni zamanda, bir quruluş sahibi üçün dəyişənlər istehsaldan fərqli olacaq və təkcə rollarda və oyun kitablarında deyil, həm də nginx konfiqurasiyalarında. {{ inventory_hostname }} inventar faylında göstərilməsinə ehtiyac yoxdur - bu xüsusi cavab dəyişən və oyun kitabının hazırda işlədiyi host orada saxlanılır.
Bir neçə host üçün inventar faylına sahib olmaq, lakin yalnız bir qrup üçün işləmək istəyirsinizsə, bu, aşağıdakı əmrlə edilə bilər:

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

Başqa bir seçim, müxtəlif qruplar üçün ayrıca inventar fayllarının olmasıdır. Və ya bir çox fərqli hostunuz varsa, iki yanaşmanı birləşdirə bilərsiniz.

Nginx-in qurulmasına qayıdaq. Konfiqurasiya fayllarını kopyaladıqdan sonra biz sites_available saytından sitest_enabled-də my_app.conf-a simvolik əlaqə yaratmalıyıq. Və nginx-i yenidən başladın.

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

Burada hər şey sadədir - kifayət qədər standart sintaksisi olan yenidən uyğun modullar. Ancaq bir məqam var. Hər dəfə nginx-i yenidən başlatmağın mənası yoxdur. Diqqət etdinizmi ki, biz “bunu belə et” kimi əmrlər yazmırıq, sintaksis daha çox “bunun bu vəziyyətə sahib olması lazımdır” kimi görünür. Və çox vaxt bu, ansible necə işləyir. Qrup artıq mövcuddursa və ya sistem paketi artıq quraşdırılıbsa, ansible bunu yoxlayacaq və tapşırığı atlayacaq. Həmçinin, serverdə olanlara tam uyğun gələn fayllar kopyalanmayacaq. Biz bundan faydalana və yalnız konfiqurasiya faylları dəyişdirildikdə nginx-i yenidən başlada bilərik. Bunun üçün reyestr direktivi var:

# 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

Konfiqurasiya fayllarından biri dəyişərsə, surəti hazırlanacaq və dəyişən qeydə alınacaq restart_nginx. Və yalnız bu dəyişən qeydə alındıqda xidmət yenidən işə salınacaq.

Və təbii ki, əsas oyun kitabına nginx rolunu əlavə etməlisiniz.

Postgresql quraşdırma

Biz nginx ilə etdiyimiz kimi systemd istifadə edərək postgresql-i aktivləşdirməliyik, həmçinin verilənlər bazasına və verilənlər bazasına daxil olmaq üçün istifadə edəcəyimiz istifadəçi yaratmalıyıq.
Gəlin bir rol yaradaq /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 }}"

Dəyişənlərin inventara necə əlavə ediləcəyini təsvir etməyəcəyəm, bu, artıq dəfələrlə edilib, həmçinin postgresql_db və postgresql_user modullarının sintaksisi. Ətraflı məlumatı sənədlərdə tapa bilərsiniz. Burada ən maraqlı direktivdir become_user: postgres. Fakt budur ki, standart olaraq, yalnız postgres istifadəçisi postgresql verilənlər bazasına və yalnız yerli olaraq daxil ola bilər. Bu direktiv bizə bu istifadəçinin adından əmrləri yerinə yetirməyə imkan verir (əlbəttə ki, çıxışımız varsa).
Həmçinin, yeni istifadəçinin verilənlər bazasına girişinə icazə vermək üçün pg_hba.conf-a sətir əlavə etməli ola bilərsiniz. Bu, nginx konfiqurasiyasını dəyişdirdiyimiz kimi edilə bilər.

Və əlbəttə ki, əsas oyun kitabına postgresql rolunu əlavə etməlisiniz.

Rbenv vasitəsilə ruby ​​quraşdırılması

Ansible-da rbenv ilə işləmək üçün modullar yoxdur, lakin o, git repozitoriyasını klonlaşdırmaqla quraşdırılır. Buna görə də bu problem ən qeyri-standart problemə çevrilir. Gəlin onun üçün bir rol yaradaq /ansible/roles/ruby_rbenv/main.yml və onu doldurmağa başlayaq:

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

Biz bu məqsədlər üçün yaratdığımız istifadəçinin altında işləmək üçün yenidən become_user direktivindən istifadə edirik. Rbenv qlobal olaraq deyil, ev kataloqunda quraşdırıldığından. Həm də biz repo və hədəfi təyin edərək deponu klonlaşdırmaq üçün git modulundan istifadə edirik.

Sonra, bashrc-də rbenv init-i qeydiyyatdan keçirməliyik və orada PATH-ə rbenv əlavə etməliyik. Bunun üçün lineinfile modulumuz var:

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

Sonra ruby_build-i quraşdırmalısınız:

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

Və nəhayət, ruby ​​quraşdırın. Bu, rbenv vasitəsilə, yəni sadəcə bash əmri ilə edilir:

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

Hansı əmri və nə ilə icra edəcəyimizi deyirik. Bununla belə, burada biz ansible-nin əmrləri işə salmazdan əvvəl bashrc-də olan kodu işlətməməsi faktına rast gəlirik. Bu o deməkdir ki, rbenv birbaşa eyni skriptdə müəyyən edilməlidir.

Növbəti problem, qabıq əmrinin ansible baxımdan heç bir vəziyyətə malik olmaması ilə bağlıdır. Yəni, Ruby-nin bu versiyasının quraşdırılıb-quraşdırılmadığını avtomatik yoxlamaq olmayacaq. Bunu özümüz edə bilərik:

- 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

Qalan tək şey bundler quraşdırmaqdır:

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

Yenə də ruby_rbenv rolumuzu əsas oyun kitabına əlavə edin.

Paylaşılan fayllar.

Ümumiyyətlə, quraşdırma burada tamamlana bilər. Bundan sonra, yalnız capistrano-nu işə salmaq qalır və o, kodu özü kopyalayacaq, lazımi qovluqları yaradacaq və proqramı işə salacaq (hər şey düzgün konfiqurasiya olunubsa). Bununla belə, capistrano tez-tez əlavə konfiqurasiya faylları tələb edir, məsələn database.yml və ya .env Onlar nginx üçün fayllar və şablonlar kimi kopyalana bilər. Yalnız bir incəlik var. Faylları kopyalamadan əvvəl onlar üçün qovluq strukturu yaratmalısınız, buna bənzər bir şey:

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

biz yalnız bir qovluq təyin edirik və lazım gələrsə, ansible avtomatik olaraq ana kataloqları yaradacaq.

Ansible Vault

Dəyişənlərin istifadəçi parolu kimi gizli məlumatları ehtiva edə biləcəyi faktına artıq rast gəldik. yaratmısansa .env ərizə üçün fayl və database.yml onda belə kritik məlumatlar daha çox olmalıdır. Onları maraqlı gözlərdən gizlətmək yaxşı olardı. Bu məqsədlə istifadə olunur məqbul anbar.

Dəyişənlər üçün fayl yaradaq /ansible/vars/all.yml (burada siz inventar faylında olduğu kimi müxtəlif host qrupları üçün müxtəlif fayllar yarada bilərsiniz: production.yml, staging.yml və s.).
Şifrələnməli olan bütün dəyişənlər standart yml sintaksisindən istifadə edərək bu fayla köçürülməlidir:

# 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

Bundan sonra bu fayl əmrlə şifrələnə bilər:

ansible-vault encrypt ./vars/all.yml

Təbii ki, şifrələmə zamanı şifrəni açmaq üçün parol təyin etməlisiniz. Bu əmri çağırdıqdan sonra faylın içində nə olacağını görə bilərsiniz.

Vasitəsilə ansible-vault decrypt faylın şifrəsi açıla, dəyişdirilə və sonra yenidən şifrələnə bilər.

İşləmək üçün faylın şifrəsini açmağa ehtiyac yoxdur. Siz onu şifrələnmiş şəkildə saxlayırsınız və oyun kitabını arqumentlə işlədirsiniz --ask-vault-pass. Ansible parol istəyəcək, dəyişənləri əldə edəcək və tapşırıqları yerinə yetirəcək. Bütün məlumatlar şifrələnmiş qalacaq.

Bir neçə host qrupu və ansible vault üçün tam əmr bu kimi görünəcək:

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

Amma mən sizə oyun kitablarının və rolların tam mətnini verməyəcəyəm, özünüz yazın. Çünki ansible belədir - nə etmək lazım olduğunu başa düşmürsənsə, o zaman bunu sizin üçün etməyəcək.

Mənbə: www.habr.com

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