Ansible yordamida Rails ilovasini o'rnatish uchun serverni sozlash

Yaqinda men serverni Rails ilovasini o'rnatishga tayyorlash uchun bir nechta Ansible o'yin kitoblarini yozishim kerak edi. Va ajablanarlisi shundaki, men oddiy bosqichma-bosqich qo'llanmani topa olmadim. Men nima bo'layotganini tushunmasdan, boshqa birovning o'yin kitobini nusxalashni xohlamadim va oxir-oqibat hujjatlarni o'qishga majbur bo'ldim, hamma narsani o'zim to'pladim. Ehtimol, men ushbu maqola yordamida kimgadir bu jarayonni tezlashtirishga yordam bera olaman.

Tushunish kerak bo'lgan birinchi narsa shundaki, ansible sizga SSH orqali uzoq server(lar)da oldindan belgilangan harakatlar ro'yxatini bajarish uchun qulay interfeysni taqdim etadi. Bu erda hech qanday sehr yo'q, siz plaginni o'rnatolmaysiz va docker, monitoring va boshqa foydali narsalar bilan ilovangizning nol ishlamay qolishiga erisha olmaysiz. O'yin kitobini yozish uchun siz aniq nima qilishni va qanday qilishni bilishingiz kerak. Shuning uchun men GitHub-dan tayyor o'yin kitoblari yoki "Nusxa ko'ring va ishga tushiring, u ishlaydi" kabi maqolalardan qoniqmadim.

Bizga nima kerak?

Yuqorida aytganimdek, o'yin kitobini yozish uchun siz nima qilishni va qanday qilishni bilishingiz kerak. Keling, nima kerakligini hal qilaylik. Rails ilovasi uchun bizga bir nechta tizim paketlari kerak bo'ladi: nginx, postgresql (redis va boshqalar). Bundan tashqari, bizga rubyning o'ziga xos versiyasi kerak. Uni rbenv (rvm, asdf...) orqali o'rnatish yaxshidir. Bularning barchasini root foydalanuvchi sifatida ishlatish har doim yomon fikrdir, shuning uchun siz alohida foydalanuvchi yaratishingiz va uning huquqlarini sozlashingiz kerak. Shundan so'ng siz bizning kodimizni serverga yuklashingiz, nginx, postgres va boshqalar uchun konfiguratsiyalarni nusxalashingiz va ushbu xizmatlarning barchasini ishga tushirishingiz kerak.

Natijada, harakatlar ketma-ketligi quyidagicha:

  1. Root sifatida tizimga kiring
  2. tizim paketlarini o'rnating
  3. yangi foydalanuvchi yaratish, huquqlarni sozlash, ssh kaliti
  4. tizim paketlarini (nginx va boshqalar) sozlang va ularni ishga tushiring
  5. Biz ma'lumotlar bazasida foydalanuvchi yaratamiz (siz darhol ma'lumotlar bazasini yaratishingiz mumkin)
  6. Yangi foydalanuvchi sifatida tizimga kiring
  7. Rbenv va ruby-ni o'rnating
  8. Bundlerni o'rnatish
  9. Ilova kodi yuklanmoqda
  10. Puma serverini ishga tushirish

Bundan tashqari, oxirgi bosqichlar capistrano yordamida amalga oshirilishi mumkin, hech bo'lmaganda qutidan tashqarida u kodni relizlar kataloglariga nusxalashi, muvaffaqiyatli o'rnatilgandan so'ng relizni simli havola bilan almashtirishi, umumiy katalogdan konfiguratsiyalarni nusxalashi, puma-ni qayta ishga tushirishi va hokazo. Bularning barchasi Ansible yordamida amalga oshirilishi mumkin, lekin nima uchun?

Fayl tuzilishi

Ansible qattiqqo'llikka ega fayl tuzilishi barcha fayllaringiz uchun, shuning uchun hammasini alohida katalogda saqlash yaxshidir. Bundan tashqari, u rels ilovasining o'zida yoki alohida bo'ladimi, unchalik muhim emas. Siz fayllarni alohida git omborida saqlashingiz mumkin. Shaxsan men rails ilovasining /config katalogida aniq katalog yaratish va hamma narsani bitta omborda saqlashni eng qulay deb topdim.

Oddiy o'yin kitobi

Playbook - bu yml fayli bo'lib, maxsus sintaksisdan foydalanib, Ansible nima qilish kerakligini va qanday qilib tasvirlaydi. Hech narsa qilmaydigan birinchi o'yin kitobini yarataylik:

---
- name: Simple playbook
  hosts: all

Bu erda biz shunchaki o'yin kitobimiz chaqirilganligini aytamiz Simple Playbook va uning mazmuni barcha xostlar uchun bajarilishi kerak. Biz uni nomi bilan /ansible katalogida saqlashimiz mumkin playbook.yml va ishga tushirishga harakat qiling:

ansible-playbook ./playbook.yml

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

Ansible barcha ro'yxatga mos keladigan hostlarni bilmasligini aytdi. Ular maxsus ro'yxatga kiritilishi kerak inventar fayli.

Keling, uni bir xil ma'lumotli katalogda yarataylik:

123.123.123.123

Shunday qilib, biz oddiygina xostni belgilaymiz (ideal holda, sinov uchun VPS-ning xosti yoki siz localhost-ni ro'yxatdan o'tkazishingiz mumkin) va uni nom ostida saqlaymiz. inventory.
Siz inventar fayli bilan ansible ishlashga harakat qilishingiz mumkin:

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

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

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

Agar ko'rsatilgan xostga ssh ruxsatingiz bo'lsa, ansible ulanadi va masofaviy tizim haqida ma'lumot to'playdi. (standart TASK [Faktlarni yig'ish]), shundan so'ng u bajarilish haqida qisqacha hisobot beradi (RECAP PLAY).

Odatiy bo'lib, ulanish siz tizimga kirgan foydalanuvchi nomidan foydalanadi. Katta ehtimol bilan u uy egasida bo'lmaydi. Playbook faylida siz remote_user direktivasi yordamida ulanish uchun qaysi foydalanuvchidan foydalanishni belgilashingiz mumkin. Bundan tashqari, masofaviy tizim haqidagi ma'lumotlar ko'pincha siz uchun keraksiz bo'lishi mumkin va siz uni yig'ish uchun vaqt sarflamasligingiz kerak. Ushbu vazifani o'chirib qo'yish ham mumkin:

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

O'yin kitobini qayta ishga tushirib ko'ring va ulanish ishlayotganiga ishonch hosil qiling. (Agar siz ildiz foydalanuvchisini ko'rsatgan bo'lsangiz, yuqori huquqlarga ega bo'lish uchun siz ham become: true direktivasini ko'rsatishingiz kerak. Hujjatlarda yozilganidek: become set to ‘true’/’yes’ to activate privilege escalation. nima uchun to'liq aniq bo'lmasa ham).

Ehtimol, siz ansible Python tarjimonini aniqlay olmasligi sababli xatoga duch kelishingiz mumkin, keyin uni qo'lda belgilashingiz mumkin:

ansible_python_interpreter: /usr/bin/python3 

Buyruq yordamida sizda python qayerda borligini bilib olishingiz mumkin whereis python.

Tizim paketlarini o'rnatish

Ansible-ning standart taqsimoti turli xil tizim paketlari bilan ishlash uchun ko'plab modullarni o'z ichiga oladi, shuning uchun biz biron bir sababga ko'ra bash skriptlarini yozishimiz shart emas. Endi tizimni yangilash va tizim paketlarini o'rnatish uchun bizga ushbu modullardan biri kerak. Mening VPS-da Ubuntu Linux bor, shuning uchun paketlarni o'rnatish uchun men foydalanaman apt-get и Buning uchun modul. Agar siz boshqa operatsion tizimdan foydalanayotgan bo'lsangiz, unda sizga boshqa modul kerak bo'lishi mumkin (esda tuting, men boshida nima va qanday qilishimizni oldindan bilishimiz kerakligini aytdim). Biroq, sintaksis, ehtimol, o'xshash bo'ladi.

Keling, o'yin kitobimizni birinchi vazifalar bilan to'ldiramiz:

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

Vazifa aynan Ansible uzoq serverlarda bajaradigan vazifadir. Biz vazifaga nom beramiz, shunda uning bajarilishini jurnalda kuzatishimiz mumkin. Va biz ma'lum bir modulning sintaksisidan foydalanib, nima qilish kerakligini tasvirlaymiz. Ushbu holatda apt: update_cache=yes - apt moduli yordamida tizim paketlarini yangilashni aytadi. Ikkinchi buyruq biroz murakkabroq. Biz paketlar ro'yxatini apt moduliga o'tkazamiz va ular borligini aytamiz state bo'lishi kerak present, ya'ni bu paketlarni o'rnating deymiz. Xuddi shunga o'xshash tarzda, biz ularni o'chirishni yoki oddiygina o'zgartirish orqali yangilashni aytishimiz mumkin state. E'tibor bering, relslar postgresql bilan ishlashi uchun bizga hozir o'rnatayotgan postgresql-contrib paketi kerak. Shunga qaramay, siz buni bilishingiz va qilishingiz kerak; ansible o'z-o'zidan buni qilmaydi.

O'yin kitobini qayta ishga tushirib ko'ring va paketlar o'rnatilganligini tekshiring.

Yangi foydalanuvchilarni yaratish.

Foydalanuvchilar bilan ishlash uchun Ansible-da foydalanuvchi moduli ham mavjud. Keling, yana bir vazifani qo'shamiz (har safar to'liq nusxa ko'chirmaslik uchun o'yin kitobining allaqachon ma'lum qismlarini sharhlar orqasiga yashirganman):

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

Biz yangi foydalanuvchi yaratamiz, unga sxema va parolni o'rnatamiz. Va keyin biz bir nechta muammolarga duch kelamiz. Agar foydalanuvchi nomlari turli xostlar uchun boshqacha bo'lishi kerak bo'lsa-chi? Va parolni o'yin kitobida aniq matnda saqlash juda yomon fikr. Boshlash uchun, keling, foydalanuvchi nomi va parolni o'zgaruvchilarga kiritamiz va maqolaning oxirida men parolni qanday shifrlashni ko'rsataman.

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

O'zgaruvchilar o'yin kitoblarida qo'sh jingalak qavslar yordamida o'rnatiladi.

Biz inventar faylida o'zgaruvchilarning qiymatlarini ko'rsatamiz:

123.123.123.123

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

Iltimos, direktivaga e'tibor bering [all:vars] - bu matnning keyingi bloki o'zgaruvchilar (vars) ekanligini va ular barcha xostlarga (barchasi) tegishli ekanligini aytadi.

Dizayn ham qiziqarli "{{ user_password | password_hash('sha512') }}". Gap shundaki, ansible foydalanuvchini orqali o'rnatmaydi user_add xuddi qo'lda qilgandek. Va u barcha ma'lumotlarni to'g'ridan-to'g'ri saqlaydi, shuning uchun biz parolni oldindan xeshga aylantirishimiz kerak, bu buyruqni bajaradi.

Keling, foydalanuvchimizni sudo guruhiga qo'shamiz. Biroq, bundan oldin biz bunday guruh mavjudligiga ishonch hosil qilishimiz kerak, chunki hech kim buni biz uchun qilmaydi:

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

Hammasi juda oddiy, bizda guruhlar yaratish uchun guruh moduli ham bor, sintaksisi apt ga juda o'xshash. Keyin ushbu guruhni foydalanuvchiga ro'yxatdan o'tkazish kifoya (groups: "sudo").
Shuningdek, ushbu foydalanuvchiga parolsiz kirishimiz uchun ssh kalitini qo'shish foydalidir:

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

Bunday holda, dizayn qiziqarli "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" — u id_rsa.pub faylining mazmunini (sizning ismingiz boshqacha boʻlishi mumkin), yaʼni ssh kalitining umumiy qismini nusxalaydi va uni serverdagi foydalanuvchi uchun ruxsat berilgan kalitlar roʻyxatiga yuklaydi.

Rollar

Foydalanishni yaratish bo'yicha barcha uchta vazifani osonlikcha bitta vazifalar guruhiga ajratish mumkin va bu guruhni juda katta bo'lmasligi uchun asosiy o'yin kitobidan alohida saqlash yaxshi bo'lar edi. Shu maqsadda Ansible bor rollar.
Eng boshida ko'rsatilgan fayl tuzilishiga ko'ra, rollar alohida rollar katalogiga joylashtirilishi kerak, har bir rol uchun vazifalar, fayllar, shablonlar va boshqalar katalogida bir xil nomdagi alohida katalog mavjud.
Fayl strukturasini yaratamiz: ./ansible/roles/user/tasks/main.yml (asosiy - o'yin kitobiga rol ulanganda yuklanadigan va bajariladigan asosiy fayl; boshqa rol fayllari unga ulanishi mumkin). Endi siz foydalanuvchi bilan bog'liq barcha vazifalarni ushbu faylga o'tkazishingiz mumkin:

# 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

Asosiy o'yin kitobida siz foydalanuvchi rolidan foydalanishni belgilashingiz kerak:

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

Bundan tashqari, boshqa barcha vazifalardan oldin tizimni yangilash mantiqiy bo'lishi mumkin, buning uchun siz blokning nomini o'zgartirishingiz mumkin tasks unda ular belgilangan pre_tasks.

Nginx o'rnatilmoqda

Bizda Nginx allaqachon o'rnatilgan bo'lishi kerak; biz uni sozlashimiz va ishga tushirishimiz kerak. Keling, buni darhol rolda bajaramiz. Fayl strukturasini yaratamiz:

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

Endi bizga fayllar va shablonlar kerak. Ularning orasidagi farq shundaki, ansible fayllarni to'g'ridan-to'g'ri nusxa ko'chiradi. Shablonlar j2 kengaytmasiga ega bo'lishi kerak va ular bir xil juft jingalak qavslar yordamida o'zgaruvchan qiymatlardan foydalanishlari mumkin.

Keling, nginx-ni yoqaylik main.yml fayl. Buning uchun bizda systemd moduli mavjud:

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

Bu erda biz nafaqat nginxni ishga tushirish kerakligini aytamiz (ya'ni biz uni ishga tushiramiz), balki darhol uni yoqish kerakligini aytamiz.
Endi konfiguratsiya fayllarini nusxalaymiz:

# 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 asosiy nginx konfiguratsiya faylini yaratamiz (uni to'g'ridan-to'g'ri serverdan olishingiz yoki o'zingiz yozishingiz mumkin). Shuningdek, saytlar_available katalogidagi ilovamiz uchun konfiguratsiya fayli (bu kerak emas, lekin foydali). Birinchi holda, biz fayllarni nusxalash uchun nusxa ko'chirish modulidan foydalanamiz (fayl ichida bo'lishi kerak /ansible/roles/nginx/files/nginx.conf). Ikkinchisida biz o'zgaruvchilar qiymatlarini almashtirib, shablonni nusxalaymiz. Shablon ichida bo'lishi kerak /ansible/roles/nginx/templates/my_app.j2). Va u shunday ko'rinishi mumkin:

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

Qo'shimchalarga e'tibor bering {{ app_name }}, {{ app_path }}, {{ server_name }}, {{ inventory_hostname }} — bu barcha oʻzgaruvchilar, ularning qiymatlari Ansible nusxa koʻchirishdan oldin shablonga almashtiriladi. Bu turli xostlar guruhlari uchun o'yin kitobidan foydalansangiz foydali bo'ladi. Masalan, biz inventar faylimizni qo'shishimiz mumkin:

[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

Endi biz o'yin kitobimizni ishga tushirsak, u ikkala xost uchun ham belgilangan vazifalarni bajaradi. Shu bilan birga, staging host uchun o'zgaruvchilar ishlab chiqarishdan farq qiladi va nafaqat rollar va o'yin kitoblarida, balki nginx konfiguratsiyasida ham. {{ inventory_hostname }} inventar faylida ko'rsatilishi shart emas - bu maxsus qabul qilinadigan o'zgaruvchi va hozirda o'yin kitobi ishlayotgan xost u erda saqlanadi.
Agar siz bir nechta xostlar uchun inventar fayliga ega bo'lishni istasangiz, lekin faqat bitta guruh uchun ishlasangiz, buni quyidagi buyruq bilan bajarish mumkin:

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

Yana bir variant - turli guruhlar uchun alohida inventar fayllarga ega bo'lish. Yoki sizda turli xil xostlar bo'lsa, ikkita yondashuvni birlashtira olasiz.

Nginx-ni sozlashga qaytaylik. Konfiguratsiya fayllarini nusxalashdan so'ng, biz sites_available dan my_app.conf ga sitest_enabled ilovasida simli havola yaratishimiz kerak. Va nginx-ni qayta ishga tushiring.

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

Bu erda hamma narsa oddiy - yana standart sintaksisga ega bo'lgan qulay modullar. Lekin bir nuqta bor. Har safar nginx-ni qayta ishga tushirishning ma'nosi yo'q. E'tibor berganmisiz, biz "bunday qiling" kabi buyruqlarni yozmaymiz, sintaksis ko'proq "bu shunday holatga ega bo'lishi kerak" kabi ko'rinadi. Va ko'pincha bu ansible qanday ishlaydi. Agar guruh allaqachon mavjud bo'lsa yoki tizim paketi allaqachon o'rnatilgan bo'lsa, ansible buni tekshiradi va vazifani o'tkazib yuboradi. Bundan tashqari, agar ular serverda mavjud bo'lgan narsalarga to'liq mos keladigan bo'lsa, fayllar nusxalanmaydi. Biz bundan foydalanishimiz va faqat konfiguratsiya fayllari o'zgartirilgan bo'lsa, nginx-ni qayta ishga tushirishimiz mumkin. Buning uchun ro'yxatga olish direktivasi mavjud:

# 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

Agar konfiguratsiya fayllaridan biri o'zgartirilsa, nusxa ko'chiriladi va o'zgaruvchi ro'yxatga olinadi restart_nginx. Va faqat bu o'zgaruvchi ro'yxatga olingan bo'lsa, xizmat qayta ishga tushiriladi.

Va, albatta, asosiy o'yin kitobiga nginx rolini qo'shishingiz kerak.

Postgresql-ni sozlash

Biz postgresql-ni systemd-dan foydalanib, xuddi nginx-da bo'lgani kabi yoqishimiz kerak, shuningdek, ma'lumotlar bazasi va ma'lumotlar bazasiga kirish uchun foydalanadigan foydalanuvchini yaratishimiz kerak.
Keling, rol yarataylik /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 }}"

Men o'zgaruvchilarni inventarizatsiyaga qanday qo'shishni tasvirlamayman, bu allaqachon ko'p marta qilingan, shuningdek postgresql_db va postgresql_user modullarining sintaksisi. Qo'shimcha ma'lumotni hujjatlarda topishingiz mumkin. Bu erda eng qiziqarli ko'rsatma become_user: postgres. Gap shundaki, sukut bo'yicha faqat postgres foydalanuvchisi postgresql ma'lumotlar bazasiga va faqat mahalliy sifatida kirish huquqiga ega. Ushbu direktiv bizga ushbu foydalanuvchi nomidan buyruqlarni bajarishga imkon beradi (agar bizda kirish imkoni bo'lsa, albatta).
Shuningdek, yangi foydalanuvchining ma'lumotlar bazasiga kirishiga ruxsat berish uchun pg_hba.conf ga qator qo'shishingiz kerak bo'lishi mumkin. Bu nginx konfiguratsiyasini o'zgartirganimiz kabi amalga oshirilishi mumkin.

Va, albatta, asosiy o'yin kitobiga postgresql rolini qo'shishingiz kerak.

Rbenv orqali ruby ​​o'rnatish

Ansible-da rbenv bilan ishlash uchun modullar yo'q, lekin u git omborini klonlash orqali o'rnatiladi. Shuning uchun bu muammo eng nostandart muammoga aylanadi. Keling, unga rol yarataylik /ansible/roles/ruby_rbenv/main.yml va uni to'ldirishni boshlaylik:

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

Ushbu maqsadlar uchun yaratgan foydalanuvchi ostida ishlash uchun biz yana become_user direktivasidan foydalanamiz. Rbenv global miqyosda emas, balki uy katalogiga o'rnatilganligi sababli. Shuningdek, biz repo va maqsadni belgilab, omborni klonlash uchun git modulidan foydalanamiz.

Keyinchalik, bashrc-da rbenv init-ni ro'yxatdan o'tkazishimiz va u erda PATH-ga rbenv-ni qo'shishimiz kerak. Buning uchun bizda lineinfile moduli mavjud:

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

Keyin ruby_build ni o'rnatishingiz kerak:

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

Va nihoyat ruby-ni o'rnating. Bu rbenv orqali, ya'ni oddiygina bash buyrug'i bilan amalga oshiriladi:

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

Qaysi buyruq va nima bilan bajarilishini aytamiz. Biroq, bu erda biz ansible buyruqlarni ishga tushirishdan oldin bashrc tarkibidagi kodni ishga tushirmasligiga duch kelamiz. Bu shuni anglatadiki, rbenv to'g'ridan-to'g'ri bir xil skriptda aniqlanishi kerak.

Keyingi muammo qobiq buyrug'ining oqilona nuqtai nazardan holatiga ega emasligi bilan bog'liq. Ya'ni, Ruby-ning ushbu versiyasi o'rnatilgan yoki o'rnatilmaganligini avtomatik tekshirish bo'lmaydi. Buni o'zimiz qilishimiz mumkin:

- 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

Qolgan narsa bundlerni o'rnatishdir:

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

Va yana, asosiy o'yin kitobiga ruby_rbenv rolimizni qo'shing.

Umumiy fayllar.

Umuman olganda, sozlash bu erda tugallanishi mumkin. Keyinchalik, faqat capistrano-ni ishga tushirish qoladi va u kodni o'zi nusxalaydi, kerakli kataloglarni yaratadi va dasturni ishga tushiradi (agar hamma narsa to'g'ri sozlangan bo'lsa). Biroq, capistrano ko'pincha qo'shimcha konfiguratsiya fayllarini talab qiladi, masalan database.yml yoki .env Ular xuddi nginx uchun fayllar va shablonlar kabi ko'chirilishi mumkin. Faqat bitta noziklik bor. Fayllarni nusxalashdan oldin ular uchun katalog tuzilishini yaratishingiz kerak, masalan:

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

biz faqat bitta katalogni belgilaymiz va agar kerak bo'lsa, ansible avtomatik ravishda ota-onalarni yaratadi.

Ansible Vault

Biz allaqachon o'zgaruvchilar foydalanuvchi paroli kabi maxfiy ma'lumotlarni o'z ichiga olishi mumkinligiga duch keldik. Agar siz yaratgan bo'lsangiz .env ilova uchun fayl va database.yml unda bunday muhim ma'lumotlar bundan ham ko'proq bo'lishi kerak. Ularni qiziquvchan ko'zlardan yashirish yaxshi bo'lardi. Shu maqsadda u ishlatiladi foydali ombor.

O'zgaruvchilar uchun fayl yarataylik /ansible/vars/all.yml (bu yerda siz inventar faylidagi kabi turli xostlar guruhlari uchun turli xil fayllarni yaratishingiz mumkin: production.yml, staging.yml va boshqalar).
Shifrlanishi kerak bo'lgan barcha o'zgaruvchilar standart yml sintaksisi yordamida ushbu faylga o'tkazilishi kerak:

# 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

Shundan so'ng ushbu faylni buyruq bilan shifrlash mumkin:

ansible-vault encrypt ./vars/all.yml

Tabiiyki, shifrlashda siz parolni hal qilish uchun parol o'rnatishingiz kerak bo'ladi. Ushbu buyruqni chaqirganingizdan so'ng fayl ichida nima bo'lishini ko'rishingiz mumkin.

Yordamida ansible-vault decrypt faylni shifrlash, o'zgartirish va keyin yana shifrlash mumkin.

Ishlash uchun faylning shifrini ochishingiz shart emas. Siz uni shifrlangan holda saqlaysiz va o'yin kitobini argument bilan boshqarasiz --ask-vault-pass. Ansible parolni so'raydi, o'zgaruvchilarni oladi va vazifalarni bajaradi. Barcha maʼlumotlar shifrlangan boʻlib qoladi.

Bir nechta xostlar guruhlari va foydali ombor uchun to'liq buyruq quyidagicha ko'rinadi:

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

Lekin men sizga o'yin kitoblari va rollarning to'liq matnini bermayman, uni o'zingiz yozing. Chunki ansible shunday - agar siz nima qilish kerakligini tushunmasangiz, u siz uchun buni qilmaydi.

Manba: www.habr.com

a Izoh qo'shish