Ոչ վաղ անցյալում ես պետք է գրեի մի քանի Ansible գրքույկ՝ սերվերը Rails հավելվածը տեղակայելու համար պատրաստելու համար: Եվ, զարմանալիորեն, ես չգտա պարզ քայլ առ քայլ ձեռնարկ: Ես չէի ուզում պատճենել ուրիշի խաղագիրքը՝ չհասկանալով, թե ինչ է կատարվում, և վերջում ստիպված էի կարդալ փաստաթղթերը՝ ինքս հավաքելով ամեն ինչ: Միգուցե ես կարող եմ օգնել ինչ-որ մեկին արագացնել այս գործընթացը այս հոդվածի օգնությամբ:
Առաջին բանը, որ պետք է հասկանալ, այն է, որ ansible-ն ապահովում է ձեզ հարմար ինտերֆեյս՝ SSH-ի միջոցով հեռավոր սերվերի (սերվերների) վրա գործողությունների նախապես սահմանված ցուցակը կատարելու համար: Այստեղ ոչ մի կախարդանք չկա, դուք չեք կարող տեղադրել պլագին և ստանալ ձեր հավելվածի զրոյական պարապուրդի տեղակայումը դոկերի, մոնիտորինգի և այլ բարիքների միջոցով: Խաղագիրք գրելու համար դուք պետք է իմանաք, թե կոնկրետ ինչ եք ուզում անել և ինչպես դա անել: Ահա թե ինչու ես չեմ բավարարվում GitHub-ի պատրաստի գրքույկներով կամ այնպիսի հոդվածներով, ինչպիսիք են՝ «Պատճենիր և գործարկիր, այն կաշխատի»:
Ի՞նչ է մեզ պետք։
Ինչպես արդեն ասացի, խաղագիրք գրելու համար պետք է իմանալ, թե ինչ ես ուզում անել և ինչպես դա անել: Եկեք որոշենք, թե ինչ է մեզ անհրաժեշտ: Rails հավելվածի համար մեզ անհրաժեշտ կլինեն մի քանի համակարգային փաթեթներ՝ nginx, postgresql (redis և այլն): Բացի այդ, մեզ անհրաժեշտ է ռուբինի կոնկրետ տարբերակ: Ավելի լավ է այն տեղադրել rbenv-ի միջոցով (rvm, asdf...): Այս ամենը որպես root օգտագործող գործարկելը միշտ էլ վատ գաղափար է, այնպես որ դուք պետք է ստեղծեք առանձին օգտվող և կարգավորեք նրա իրավունքները: Դրանից հետո դուք պետք է վերբեռնեք մեր կոդը սերվերում, պատճենեք nginx-ի, postgres-ի և այլնի կոնֆիգուրացիաները և գործարկեք այս բոլոր ծառայությունները:
Արդյունքում, գործողությունների հաջորդականությունը հետևյալն է.
- Մուտք գործեք որպես արմատ
- տեղադրել համակարգի փաթեթներ
- ստեղծել նոր օգտվող, կարգավորել իրավունքները, ssh ստեղնը
- կարգավորել համակարգի փաթեթները (nginx և այլն) և գործարկել դրանք
- Մենք օգտատեր ենք ստեղծում տվյալների բազայում (դուք կարող եք անմիջապես ստեղծել տվյալների բազա)
- Մուտք գործեք որպես նոր օգտվող
- Տեղադրեք rbenv և ruby
- Փաթեթի տեղադրում
- Դիմումի կոդը բեռնվում է
- Puma սերվերի գործարկում
Ավելին, վերջին փուլերը կարող են իրականացվել capistrano-ի միջոցով, համենայն դեպս, այն կարող է պատճենել կոդը թողարկման գրացուցակներում, հաջող տեղակայման դեպքում փոխել թողարկումը symlink-ով, պատճենել կոնֆիգուրացիաները ընդհանուր գրացուցակից, վերագործարկել puma և այլն: Այս ամենը կարելի է անել Ansible-ի միջոցով, բայց ինչո՞ւ:
Ֆայլի կառուցվածքը
Ansible-ն ունի խիստ
Պարզ խաղագիրք
Playbook-ը yml ֆայլ է, որը, օգտագործելով հատուկ շարահյուսություն, նկարագրում է, թե ինչ և ինչպես պետք է անի Ansible-ը: Եկեք ստեղծենք առաջին խաղագիրքը, որը ոչինչ չի անում.
---
- name: Simple playbook
hosts: all
Այստեղ մենք պարզապես ասում ենք, որ մեր խաղագիրքը կոչվում է Simple Playbook
և որ դրա բովանդակությունը պետք է կատարվի բոլոր հոսթերի համար: Մենք կարող ենք այն պահել անունով /ansible գրացուցակում playbook.yml
և փորձիր վազել.
ansible-playbook ./playbook.yml
PLAY [Simple Playbook] ************************************************************************************************************************************
skipping: no hosts matched
Ansible-ն ասում է, որ չգիտի որևէ հաղորդավար, որը համապատասխանում է բոլոր ցանկին: Նրանք պետք է նշված լինեն հատուկ
Եկեք ստեղծենք այն նույն ansible գրացուցակում.
123.123.123.123
Ահա թե ինչպես մենք պարզապես նշում ենք հյուրընկալողը (իդեալականում մեր VPS-ի հյուրընկալողը թեստավորման համար, կամ դուք կարող եք գրանցել localhost) և պահպանել այն անվան տակ: inventory
.
Դուք կարող եք փորձել գործարկել ansible-ը գույքագրման ֆայլով.
ansible-playbook ./playbook.yml -i inventory
PLAY [Simple Playbook] ************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************
PLAY RECAP ************************************************************************************************************************************
Եթե դուք ունեք ssh մուտք դեպի նշված հոսթ, ապա ansible-ը կմիանա և կհավաքի տեղեկատվություն հեռավոր համակարգի մասին: (լռելյայն ԱՌԱՋԱԴՐԱՆՔ [Փաստերի հավաքում]), որից հետո այն կարճ հաշվետվություն կտա կատարման մասին (PLAY RECAP):
Լռելյայնորեն, կապն օգտագործում է օգտվողի անունը, որով դուք մուտք եք գործել համակարգ: Այն, ամենայն հավանականությամբ, չի լինի հաղորդավարի վրա: Playbook ֆայլում կարող եք նշել, թե որ օգտվողին միանալու համար օգտագործելով remote_user հրահանգը: Բացի այդ, հեռավոր համակարգի մասին տեղեկատվությունը հաճախ կարող է ձեզ համար անհարկի լինել, և դուք չպետք է ժամանակ վատնեք դրանք հավաքելու համար: Այս առաջադրանքը կարող է նաև անջատվել.
---
- name: Simple playbook
hosts: all
remote_user: root
become: true
gather_facts: no
Փորձեք նորից գործարկել խաղագիրքը և համոզվեք, որ կապն աշխատում է: (Եթե դուք նշել եք արմատային օգտվողին, ապա դուք նույնպես պետք է նշեք դառնալ: ճշմարիտ հրահանգը բարձրացված իրավունքներ ձեռք բերելու համար: Ինչպես գրված է փաստաթղթերում. become set to ‘true’/’yes’ to activate privilege escalation.
թեև լիովին պարզ չէ, թե ինչու):
Միգուցե դուք ստանաք սխալ, որը պայմանավորված է նրանով, որ ansible-ը չի կարող որոշել Python թարգմանիչը, ապա կարող եք ձեռքով նշել այն.
ansible_python_interpreter: /usr/bin/python3
Դուք կարող եք պարզել, թե որտեղ ունեք python հրամանով whereis python
.
Համակարգային փաթեթների տեղադրում
Ansible-ի ստանդարտ բաշխումը ներառում է բազմաթիվ մոդուլներ համակարգային տարբեր փաթեթների հետ աշխատելու համար, այնպես որ մենք ստիպված չենք լինի որևէ պատճառով գրել bash սցենարներ: Այժմ մեզ անհրաժեշտ է այս մոդուլներից մեկը՝ համակարգը թարմացնելու և համակարգի փաթեթները տեղադրելու համար: Ես ունեմ Ubuntu Linux իմ VPS-ում, ուստի փաթեթներ տեղադրելու համար ես օգտագործում եմ 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-ն ունի նաև մոդուլ՝ օգտատեր։ Ավելացնենք ևս մեկ առաջադրանք (ես մեկնաբանությունների հետևում թաքցրել եմ գրքույկի արդեն հայտնի հատվածները, որպեսզի ամեն անգամ ամբողջությամբ չպատճենեմ այն).
---
- 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
ֆայլ. Դրա համար մենք ունենք համակարգային մոդուլ.
# 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-ի տեղադրմանը: Կազմաձևման ֆայլերը պատճենելուց հետո մենք պետք է ստեղծենք symlink sites_enabled-ում my_app.conf-ին sites_available-ից: Եվ վերագործարկեք 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-ի կարգավորում
Մենք պետք է միացնենք postgresql-ն՝ օգտագործելով systemd-ը նույն կերպ, ինչպես արեցինք nginx-ի դեպքում, ինչպես նաև ստեղծենք օգտատեր, որը մենք կօգտագործենք տվյալների բազա և հենց տվյալների բազա մուտք գործելու համար:
Եկեք դեր ստեղծենք /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 դերը հիմնական խաղատախտակի մեջ:
Ruby-ի տեղադրում rbenv-ի միջոցով
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
Մենք կրկին օգտագործում ենք be_user հրահանգը՝ այս նպատակների համար մեր ստեղծած օգտատիրոջ ներքո աշխատելու համար: Քանի որ rbenv-ը տեղադրված է իր հիմնական գրացուցակում, և ոչ թե գլոբալ: Եվ մենք նաև օգտագործում ենք git մոդուլը պահեստը կլոնավորելու համար՝ նշելով repo-ն և dest-ը:
Հաջորդը, մենք պետք է գրանցենք rbenv init-ը bashrc-ում և այնտեղ ավելացնենք rbenv PATH-ին: Դրա համար մենք ունենք 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-ը պետք է ուղղակիորեն սահմանվի նույն սցենարով:
Հաջորդ խնդիրը պայմանավորված է նրանով, որ shell-ի հրամանը հասկանալի տեսանկյունից չունի վիճակ։ Այսինքն՝ ավտոմատ ստուգում չի լինի՝ արդյոք 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-playbook -i inventory ./playbook.yml -l "staging" --ask-vault-pass
Բայց ես ձեզ չեմ տա խաղային գրքերի և դերերի ամբողջական տեքստը, գրեք ինքներդ: Որովհետև ansible-ն այդպիսին է. եթե դուք չեք հասկանում, թե ինչ է պետք անել, ապա դա ձեզ չի անի:
Source: www.habr.com