Ansible ашиглан Rails програмыг байрлуулах серверийг тохируулж байна

Саяхан би Rails програмыг ашиглахад серверийг бэлтгэхийн тулд хэд хэдэн Ansible тоглоомын ном бичих шаардлагатай болсон. Гайхалтай нь би энгийн алхам алхмаар гарын авлагыг олсонгүй. Би юу болж байгааг ойлгохгүйгээр хэн нэгний тоглоомын номыг хуулахыг хүсээгүй бөгөөд эцэст нь би бүх зүйлийг өөрөө цуглуулж, баримт бичгийг унших шаардлагатай болсон. Магадгүй би энэ нийтлэлийн тусламжтайгаар хэн нэгэнд энэ үйл явцыг хурдасгахад тусалж болох юм.

Хамгийн түрүүнд ойлгох ёстой зүйл бол ansible нь SSH-ээр дамжуулан алсын сервер(үүд) дээр урьдчилан тодорхойлсон үйлдлийн жагсаалтыг гүйцэтгэх тохиромжтой интерфэйсээр хангадаг. Энд ямар ч ид шид байхгүй тул та залгаасыг суулгаж, докер, мониторинг болон бусад сайн зүйлсийг ашиглан өөрийн аппликешныг ашиглах боломжгүй. Тоглоомын ном бичихийн тулд та яг юу хийхийг хүсч байгаагаа, яаж хийхээ мэддэг байх ёстой. Тийм ч учраас би GitHub-ийн бэлэн тоглоомын номууд эсвэл "Хуулж, ажиллуул, энэ нь ажиллах болно" гэх мэт нийтлэлүүдэд сэтгэл хангалуун бус байна.

Бидэнд юу хэрэгтэй вэ?

Би аль хэдийн хэлсэнчлэн, тоглоомын ном бичихийн тулд та юу хийхийг хүсч байгаагаа, яаж хийхээ мэдэх хэрэгтэй. Бидэнд юу хэрэгтэйг шийдье. Rails програмын хувьд бидэнд nginx, postgresql (redis гэх мэт) хэд хэдэн системийн багц хэрэгтэй болно. Үүнээс гадна бидэнд бадмаарагын тодорхой хувилбар хэрэгтэй. Үүнийг rbenv (rvm, asdf...)-ээр суулгасан нь дээр. Энэ бүгдийг root хэрэглэгчээр ажиллуулах нь үргэлж муу санаа байдаг тул та тусдаа хэрэглэгч үүсгэж, эрхийг нь тохируулах хэрэгтэй. Үүний дараа та манай кодыг серверт байршуулж, nginx, postgres гэх мэт тохиргоог хуулж, эдгээр бүх үйлчилгээг эхлүүлэх хэрэгтэй.

Үүний үр дүнд үйлдлийн дараалал дараах байдалтай байна.

  1. Root нэрээр нэвтэрнэ үү
  2. системийн багцуудыг суулгах
  3. шинэ хэрэглэгч үүсгэх, эрхийг тохируулах, ssh түлхүүр
  4. системийн багцуудыг (nginx гэх мэт) тохируулж, ажиллуулна уу
  5. Бид мэдээллийн санд хэрэглэгч үүсгэдэг (та нэн даруй мэдээллийн сан үүсгэж болно)
  6. Шинэ хэрэглэгчээр нэвтэрнэ үү
  7. Rbenv болон ruby-г суулгана уу
  8. Багцыг суулгаж байна
  9. Програмын кодыг байршуулж байна
  10. Puma серверийг ажиллуулж байна

Түүнчлэн, сүүлийн үе шатуудыг capistrano-г ашиглан хийж болно, ядаж хайрцагнаас гарахдаа кодыг хувилбарын лавлах руу хуулж, амжилттай байршуулсны дараа хувилбарыг тэмдэгтийн холбоосоор сольж, хуваалцсан лавлахаас тохиргоог хуулж, puma-г дахин эхлүүлж болно. Энэ бүгдийг Ansible ашиглан хийж болно, гэхдээ яагаад?

Файлын бүтэц

Ansible хатуу чанга байдаг файлын бүтэц таны бүх файлд зориулагдсан тул бүгдийг нь тусдаа санд хадгалах нь дээр. Түүгээр ч барахгүй энэ нь төмөр замд өөрөө эсвэл тусад нь байх нь тийм ч чухал биш юм. Та тусдаа git репозитор файлуудыг хадгалах боломжтой. Би хувьдаа rails програмын /config лавлах санд ansible лавлах үүсгэж, бүх зүйлийг нэг репозиторид хадгалах нь хамгийн тохиромжтой санагдсан.

Энгийн тоглоомын ном

Playbook бол тусгай синтакс ашиглан Ansible юу хийх, хэрхэн хийхийг тайлбарладаг yml файл юм. Юу ч хийдэггүй анхны тоглоомын номыг бүтээцгээе:

---
- name: Simple playbook
  hosts: all

Энд бид зүгээр л бидний тоглоомын ном гэж нэрлэгддэг гэж хэлж байна Simple Playbook мөн түүний агуулгыг бүх хостуудад гүйцэтгэх ёстой. Бид үүнийг /ansible санд нэрээр нь хадгалах боломжтой playbook.yml мөн гүйхийг оролдоорой:

ansible-playbook ./playbook.yml

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

Ansible бүх жагсаалтад тохирох ямар ч хостыг мэдэхгүй гэж мэдэгдэв. Тэд тусгай жагсаалтад орсон байх ёстой бараа материалын файл.

Үүнийг ижил мэдээллийн санд үүсгэцгээе:

123.123.123.123

Ингэж бид зүгээр л хостыг (манай VPS-ийн хостыг турших, эсвэл та localhost-д бүртгүүлж болно) зааж өгөөд нэрээр нь хадгална. inventory.
Та бараа материалын файлтай ажиллахыг оролдож болно:

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

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

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

Хэрэв танд заасан хост руу ssh хандалт байгаа бол ansible нь холбогдож, алсын системийн талаарх мэдээллийг цуглуулах болно. (өгөгдмөл ДААЛГАВАР [Баримт цуглуулах]) дараа нь гүйцэтгэлийн талаар товч тайлан өгөх болно (RECAP PLAY).

Анхдагч байдлаар, холболт нь таны системд нэвтэрсэн хэрэглэгчийн нэрийг ашигладаг. Энэ нь хост дээр байхгүй байх магадлалтай. Playbook файлд та remote_user зааврыг ашиглан аль хэрэглэгчийг холбохыг зааж өгч болно. Түүнчлэн, алсын системийн талаарх мэдээлэл танд ихэвчлэн хэрэггүй байж болох тул та үүнийг цуглуулахад цаг алдах ёсгүй. Энэ ажлыг мөн идэвхгүй болгож болно:

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

Тоглоомын дэвтрийг дахин ажиллуулаад холболт ажиллаж байгаа эсэхийг шалгана уу. (Хэрэв та үндсэн хэрэглэгчийг зааж өгсөн бол өндөр эрх олж авахын тулд, мөн become: true удирдамжийг зааж өгөх хэрэгтэй. Баримт бичигт бичсэнээр: become set to ‘true’/’yes’ to activate privilege escalation. яагаад гэдэг нь бүрэн тодорхойгүй байгаа ч).

Магадгүй та ansible нь Python орчуулагчийг тодорхойлж чадахгүй байгаатай холбоотой алдаа хүлээн авах бөгөөд та үүнийг гараар зааж өгч болно:

ansible_python_interpreter: /usr/bin/python3 

Та командын тусламжтайгаар python хаана байгааг олж мэдэх боломжтой whereis python.

Системийн багцуудыг суулгаж байна

Ansible-ийн стандарт түгээлт нь янз бүрийн системийн багцуудтай ажиллах олон модулийг агуулдаг тул бид ямар нэг шалтгаанаар bash скрипт бичих шаардлагагүй болно. Одоо бидэнд системийг шинэчлэх, системийн багцуудыг суулгахын тулд эдгээр модулиудын аль нэг нь хэрэгтэй байна. Миний VPS дээр Ubuntu Linux байгаа тул багцуудыг суулгахын тулд ашигладаг apt-get и түүнд зориулсан модуль. Хэрэв та өөр үйлдлийн систем ашиглаж байгаа бол танд өөр модуль хэрэгтэй байж магадгүй юм (бид юу хийх, яаж хийхээ урьдчилан мэдэх хэрэгтэй гэдгийг би эхэндээ хэлсэн гэдгийг санаарай). Гэсэн хэдий ч синтакс нь ижил төстэй байх магадлалтай.

Тоглоомын дэвтэрээ эхний даалгавруудаар нэмж оруулцгаая:

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

Даалгавар бол Ansible-ийн алсын сервер дээр гүйцэтгэх ажил юм. Бид даалгаварт нэр өгдөг бөгөөд ингэснээр түүний гүйцэтгэлийг бүртгэлд хянах боломжтой. Мөн бид тодорхой модулийн синтаксийг ашиглан юу хийх ёстойг тайлбарладаг. Энэ тохиолдолд apt: update_cache=yes - apt модулийг ашиглан системийн багцуудыг шинэчлэхийг хэлдэг. Хоёрдахь тушаал нь арай илүү төвөгтэй юм. Бид багцуудын жагсаалтыг apt модульд дамжуулж, тэдгээр нь байгаа гэж хэлдэг state болох ёстой present, өөрөөр хэлбэл бид эдгээр багцуудыг суулгана гэж хэлдэг. Үүнтэй адилаар бид тэднийг устгах эсвэл зүгээр л өөрчлөх замаар шинэчлэхийг хэлж болно state. Райлуудыг postgresql-тэй ажиллахын тулд бидэнд одоо суулгаж байгаа postgresql-contrib багц хэрэгтэй гэдгийг анхаарна уу. Дахин хэлэхэд, та үүнийг мэдэж, хийх хэрэгтэй; ansible өөрөө үүнийг хийхгүй.

Тоглоомын дэвтрийг дахин ажиллуулж, багцуудыг суулгасан эсэхийг шалгана уу.

Шинэ хэрэглэгчдийг бий болгох.

Хэрэглэгчидтэй ажиллахын тулд Ansible нь хэрэглэгч модультай. Дахиад нэг даалгавар нэмье (би тэр болгоныг бүхэлд нь хуулахгүйн тулд тоглоомын номын аль хэдийн мэддэг хэсгүүдийг тайлбарын ард нуусан):

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

Бид шинэ хэрэглэгч үүсгэж, түүнд зориулсан схем, нууц үгийг тохируулдаг. Тэгээд бид хэд хэдэн асуудалтай тулгардаг. Хэрэглэгчийн нэр өөр өөр хостуудад өөр байх шаардлагатай бол яах вэ? Нууц үгээ тоглоомын дэвтэрт тодорхой текстээр хадгалах нь маш муу санаа юм. Эхлээд хэрэглэгчийн нэр, нууц үгээ хувьсагчид оруулъя, өгүүллийн төгсгөлд би нууц үгийг хэрхэн шифрлэхийг харуулах болно.

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

Хувьсагчдыг тоглоомын дэвтэрт давхар буржгар хаалт ашиглан тохируулдаг.

Бид бараа материалын файл дахь хувьсагчдын утгыг зааж өгнө.

123.123.123.123

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

Зааврыг анхаарна уу [all:vars] - энэ нь текстийн дараагийн блок нь хувьсагч (vars) бөгөөд тэдгээр нь бүх хостуудад (бүгд) хамааралтай гэж хэлдэг.

Дизайн нь бас сонирхолтой юм "{{ user_password | password_hash('sha512') }}". Гол нь ansible нь хэрэглэгчийг дамжуулан суулгадаггүй user_add Та үүнийг гараар хийх шиг. Мөн энэ нь бүх өгөгдлийг шууд хадгалдаг тул бид нууц үгийг урьдчилан хэш болгон хувиргах ёстой бөгөөд энэ тушаал нь үүнийг хийдэг.

Хэрэглэгчээ sudo бүлэгт нэмье. Гэсэн хэдий ч, үүнээс өмнө бид ийм бүлэг байгаа эсэхийг шалгах хэрэгтэй, учир нь хэн ч бидний өмнөөс үүнийг хийхгүй.

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

Бүх зүйл маш энгийн, бид бас бүлэг үүсгэх бүлгийн модультай бөгөөд синтакс нь apt-тай маш төстэй. Дараа нь энэ бүлгийг хэрэглэгчдэд бүртгүүлэхэд хангалттай (groups: "sudo").
Энэ хэрэглэгчдэд ssh түлхүүр нэмэх нь бас ашигтай бөгөөд ингэснээр бид нууц үггүйгээр нэвтэрч болно.

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

Энэ тохиолдолд дизайн нь сонирхолтой юм "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" — энэ нь id_rsa.pub файлын агуулгыг (таны нэр өөр байж болно), өөрөөр хэлбэл ssh түлхүүрийн нийтийн хэсгийг хуулж, сервер дээрх хэрэглэгчийн зөвшөөрөгдсөн түлхүүрүүдийн жагсаалтад байршуулна.

Үүрэг

Хэрэглээг бий болгох гурван даалгаврыг нэг бүлэг даалгаварт хялбархан ангилж болох бөгөөд энэ бүлгийг хэт том болгохгүйн тулд үндсэн тоглоомын номноос тусад нь хадгалах нь зүйтэй юм. Энэ зорилгоор Ansible дүрүүд.
Хамгийн эхэнд заасан файлын бүтцийн дагуу дүрүүдийг тусдаа үүргийн санд байрлуулах ёстой бөгөөд үүрэг тус бүрт ижил нэртэй тусдаа директор байдаг, даалгавар, файл, загвар гэх мэт сан дотор.
Файлын бүтцийг үүсгэцгээе: ./ansible/roles/user/tasks/main.yml (гол нь тоглоомын дэвтэрт үүрэг холбогдсон үед ачаалагдах, гүйцэтгэх үндсэн файл; бусад дүрийн файлуудыг түүнтэй холбож болно). Одоо та хэрэглэгчтэй холбоотой бүх ажлыг энэ файл руу шилжүүлж болно:

# 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

Үндсэн тоглоомын дэвтэрт та хэрэглэгчийн дүрийг ашиглахын тулд зааж өгөх ёстой:

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

Түүнчлэн, бусад бүх ажлуудаас өмнө системийг шинэчлэх нь утга учиртай байж болох бөгөөд үүнийг хийхийн тулд та блокийн нэрийг өөрчилж болно tasks Үүнд тэдгээр нь тодорхойлогддог pre_tasks.

Nginx-г тохируулж байна

Бид аль хэдийн Nginx суулгасан байх ёстой, бид үүнийг тохируулж, ажиллуулах хэрэгтэй. Үүнийг дүрд нь шууд хийцгээе. Файлын бүтцийг үүсгэцгээе:

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

Одоо бидэнд файл, загвар хэрэгтэй байна. Тэдний хоорондох ялгаа нь ansible нь файлуудыг байгаагаар нь шууд хуулдаг. Загварууд нь j2 өргөтгөлтэй байх ёстой бөгөөд тэдгээр нь ижил давхар буржгар хаалт ашиглан хувьсах утгыг ашиглаж болно.

Nginx-г идэвхжүүлье main.yml файл. Үүний тулд бидэнд systemd модуль байна:

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

Энд бид зөвхөн nginx-ийг эхлүүлэх ёстой гэж хэлээд зогсохгүй (өөрөөр хэлбэл бид үүнийг эхлүүлнэ), гэхдээ үүнийг идэвхжүүлэх ёстой гэж шууд хэлдэг.
Одоо тохиргооны файлуудыг хуулж авцгаая:

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

Бид үндсэн nginx тохиргооны файлыг үүсгэдэг (та үүнийг серверээс шууд авах эсвэл өөрөө бичих боломжтой). Мөн манай програмын тохиргооны файлыг sites_available лавлах (энэ нь шаардлагагүй, гэхдээ хэрэгтэй). Эхний тохиолдолд бид файл хуулахын тулд хуулбарлах модулийг ашигладаг (файл дотор байх ёстой /ansible/roles/nginx/files/nginx.conf). Хоёрдугаарт, бид загвараа хуулж, хувьсагчийн утгыг орлуулна. Загвар нь дотор байх ёстой /ansible/roles/nginx/templates/my_app.j2). Мөн энэ нь иймэрхүү харагдах болно:

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

Оруулгад анхаарлаа хандуулаарай {{ app_name }}, {{ app_path }}, {{ server_name }}, {{ inventory_hostname }} - эдгээр нь хуулбарлахын өмнө Ansible утгыг загварт орлуулах бүх хувьсагч юм. Хэрэв та өөр өөр бүлгийн хостуудад зориулсан тоглоомын ном ашигладаг бол энэ нь ашигтай. Жишээлбэл, бид бараа материалын файлаа нэмж болно:

[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

Хэрэв бид одоо тоглоомын дэвтэрээ ажиллуулбал энэ нь хоёр хостын заасан даалгавруудыг гүйцэтгэх болно. Гэхдээ үүнтэй зэрэгцэн, тайзны хостын хувьд хувьсагч нь үйлдвэрлэлийнхээс ялгаатай бөгөөд зөвхөн дүр, тоглоомын номонд төдийгүй nginx тохиргоонд ч өөр байх болно. {{ inventory_hostname }} бараа материалын файлд зааж өгөх шаардлагагүй - энэ тусгай хувьсагч мөн тоглоомын номыг ажиллуулж байгаа хост тэнд хадгалагдана.
Хэрэв та хэд хэдэн хостын бараа материалын файлтай байхыг хүсч байгаа ч зөвхөн нэг бүлэгт зориулж ажиллуулахыг хүсвэл дараах тушаалыг ашиглан үүнийг хийж болно.

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

Өөр нэг сонголт бол өөр өөр бүлгүүдэд зориулсан бараа материалын тусдаа файлтай байх явдал юм. Эсвэл та олон өөр хосттой бол хоёр аргыг хослуулж болно.

nginx-ийн тохиргоо руу буцаж орцгооё. Тохиргооны файлуудыг хуулж авсны дараа бид sitest_enabled дотроос sites_available-аас my_app.conf руу сим холбоос үүсгэх хэрэгтэй. Мөн nginx-г дахин эхлүүлнэ үү.

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

Энд бүх зүйл энгийн байдаг - нэлээд стандарт синтакс бүхий дахин боломжтой модулиуд. Гэхдээ нэг зүйл бий. Тэр болгонд nginx-г дахин эхлүүлэх нь утгагүй юм. Бид "үүнийг ингэж хий" гэх мэт команд бичдэггүйг та анзаарсан уу, синтакс нь "энэ нь ийм төлөвтэй байх ёстой" гэх мэт харагдаж байна. Ихэнх тохиолдолд ansible яг ийм байдлаар ажилладаг. Хэрэв бүлэг аль хэдийн байгаа эсвэл системийн багц суулгасан бол ansible үүнийг шалгаж, даалгаврыг алгасах болно. Мөн сервер дээр байгаа файлуудтай бүрэн таарч байвал файл хуулахгүй. Бид үүнийг ашиглаж, тохиргооны файлуудыг өөрчилсөн тохиолдолд л nginx-ийг дахин эхлүүлэх боломжтой. Үүнд зориулсан бүртгэлийн заавар байдаг:

# 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

Хэрэв тохиргооны файлуудын аль нэг нь өөрчлөгдвөл хуулбарыг хийж, хувьсагчийг бүртгэнэ restart_nginx. Зөвхөн энэ хувьсагч бүртгэгдсэн тохиолдолд үйлчилгээг дахин эхлүүлэх болно.

Мэдээжийн хэрэг та үндсэн тоглоомын дэвтэрт nginx дүрийг нэмэх хэрэгтэй.

Postgresql-г тохируулж байна

Бид nginx-тэй адил systemd-г ашиглан postgresql-г идэвхжүүлж, мэдээллийн сан болон өгөгдлийн санд хандахад ашиглах хэрэглэгчийг үүсгэх хэрэгтэй.
Дүр бүтээцгээе /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 }}"

Хувьсагчдыг бараа материалд хэрхэн нэмэх талаар би тайлбарлахгүй, үүнийг олон удаа хийж байсан, мөн postgresql_db болон postgresql_user модулиудын синтакс. Дэлгэрэнгүй мэдээллийг баримтаас авах боломжтой. Энд байгаа хамгийн сонирхолтой заавар become_user: postgres. Баримт нь анхдагчаар зөвхөн postgres хэрэглэгч postgresql мэдээллийн санд хандах эрхтэй бөгөөд зөвхөн дотоодод л байдаг. Энэхүү заавар нь бидэнд энэ хэрэглэгчийн нэрийн өмнөөс командуудыг гүйцэтгэх боломжийг олгодог (хэрэв бидэнд хандалт байгаа бол мэдээж хэрэг).
Мөн та pg_hba.conf-д шинэ хэрэглэгчдэд мэдээллийн санд хандах боломжийг олгохын тулд мөр нэмэх шаардлагатай байж магадгүй юм. Үүнийг бид nginx тохиргоог өөрчилсөнтэй ижил аргаар хийж болно.

Мэдээжийн хэрэг, та үндсэн тоглоомын номонд postgresql үүргийг нэмэх хэрэгтэй.

Rbenv-ээр дамжуулан ruby-г суулгаж байна

Ansible-д rbenv-тэй ажиллах модуль байхгүй ч git репозиторыг клончлох замаар суулгадаг. Тиймээс энэ асуудал хамгийн стандарт бус асуудал болж хувирдаг. Түүнд зориулж дүр бүтээцгээе /ansible/roles/ruby_rbenv/main.yml тэгээд бөглөж эхэлцгээе:

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

Эдгээр зорилгоор үүсгэсэн хэрэглэгчийн доор ажиллахын тулд бид дахин become_user зааврыг ашигладаг. Учир нь rbenv нь дэлхий даяар биш, өөрийн үндсэн лавлахад суулгасан байдаг. Мөн бид репозиторыг хувилахдаа git модулийг ашиглан репо болон dest-ийг зааж өгдөг.

Дараа нь бид bashrc-д rbenv init-г бүртгүүлээд тэнд PATH-д rbenv нэмэх хэрэгтэй. Үүний тулд бидэнд lineinfile модуль байна:

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

Дараа нь та ruby_build-г суулгах хэрэгтэй:

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

Эцэст нь ruby ​​суулгана уу. Үүнийг rbenv, өөрөөр хэлбэл bash командын тусламжтайгаар хийдэг.

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

Бид ямар тушаалыг юугаар гүйцэтгэхийг хэлдэг. Гэсэн хэдий ч, энд бид ansible нь командуудыг ажиллуулахын өмнө bashrc-д агуулагдах кодыг ажиллуулдаггүй болохыг олж мэдэв. Энэ нь rbenv-ийг нэг скрипт дээр шууд тодорхойлох шаардлагатай гэсэн үг юм.

Дараагийн асуудал нь бүрхүүлийн команд нь боломжийн үүднээс төлөвгүй байгаатай холбоотой юм. Өөрөөр хэлбэл, Ruby-ийн энэ хувилбар суулгасан эсэхийг автоматаар шалгахгүй. Үүнийг бид өөрсдөө хийж чадна:

- 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

Зөвхөн багцлагчийг суулгахад л үлддэг:

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

Дахин хэлэхэд ruby_rbenv бидний дүрийг үндсэн тоглоомын дэвтэрт нэмнэ үү.

Хуваалцсан файлууд.

Ерөнхийдөө энд тохиргоог хийж болно. Дараа нь зөвхөн capistrano-г ажиллуулахад л үлдэх бөгөөд кодыг өөрөө хуулж, шаардлагатай лавлахуудыг үүсгэж, програмыг ажиллуулна (хэрэв бүх зүйл зөв тохируулагдсан бол). Гэсэн хэдий ч capistrano нь ихэвчлэн нэмэлт тохиргооны файлуудыг шаарддаг database.yml буюу .env Тэдгээрийг nginx-д зориулсан файл, загвар шиг хуулж болно. Ганцхан нарийн зүйл бий. Файлуудыг хуулахын өмнө та тэдгээрийн лавлах бүтцийг үүсгэх хэрэгтэй.

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

Бид зөвхөн нэг лавлахыг зааж өгөх бөгөөд шаардлагатай бол ansible нь эцэг эхийг автоматаар үүсгэх болно.

Ansible Vault

Хувьсагч нь хэрэглэгчийн нууц үг гэх мэт нууц мэдээллийг агуулж болохыг бид аль хэдийн олж мэдсэн. Хэрэв та бүтээсэн бол .env програмын файл, болон database.yml тэгвэл бүр ч илүү ийм чухал тоо баримт байх ёстой. Тэднийг нүднээс далдлах нь сайн хэрэг. Энэ зорилгоор үүнийг ашигладаг найдвартай сав.

Хувьсагчдад зориулсан файл үүсгэцгээе /ansible/vars/all.yml (энд та бараа материалын файлын нэгэн адил өөр өөр бүлэг хостуудад зориулж өөр өөр файл үүсгэж болно: production.yml, staging.yml гэх мэт).
Шифрлэгдсэн байх ёстой бүх хувьсагчдыг стандарт yml синтакс ашиглан энэ файл руу шилжүүлэх ёстой.

# 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

Үүний дараа энэ файлыг дараах тушаалаар шифрлэж болно.

ansible-vault encrypt ./vars/all.yml

Мэдээжийн хэрэг, шифрлэхдээ шифрийг тайлах нууц үгийг тохируулах шаардлагатай болно. Энэ командыг дуудсаны дараа файл дотор юу байгааг харж болно.

Тусламжийн тусламжтайгаар ansible-vault decrypt файлыг тайлж, өөрчилж, дараа нь дахин шифрлэж болно.

Та ажиллахын тулд файлын шифрийг тайлах шаардлагагүй. Та үүнийг шифрлэгдсэн байдлаар хадгалж, аргументтай тоглоомын номыг ажиллуулна --ask-vault-pass. Ansible нууц үг асууж, хувьсагчдыг авч, даалгавруудыг гүйцэтгэнэ. Бүх өгөгдөл шифрлэгдсэн хэвээр байх болно.

Хэд хэдэн бүлэг хостууд болон ansible vault-д зориулсан бүрэн тушаал нь иймэрхүү харагдах болно:

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

Гэхдээ би танд тоглоомын ном, дүрүүдийг бүрэн эхээр нь өгөхгүй, өөрөө бичээрэй. Учир нь ansible нь ийм байдаг - хэрвээ та юу хийх ёстойгоо ойлгохгүй байгаа бол энэ нь таны өмнөөс үүнийг хийхгүй.

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх