جوابي استعمال ڪندي ريل ايپليڪيشن کي ترتيب ڏيڻ لاءِ سرور کي ترتيب ڏيڻ

ڪجهه وقت اڳ مون کي ريل ايپليڪيشن کي ترتيب ڏيڻ لاءِ سرور تيار ڪرڻ لاءِ ڪيترائي جوابي پلي بڪ لکڻ جي ضرورت هئي. ۽، حيرت انگيز طور تي، مون کي هڪ سادي قدم قدم دستياب نه مليو. مان نه ٿي چاهيان ته ڪنهن ٻئي جي پلي بڪ کي نقل ڪرڻ کان سواءِ سمجھان ته ڇا ٿي رهيو آهي، ۽ آخر ۾ مون کي دستاويز پڙهڻو پيو، سڀ ڪجهه پاڻ گڏ ڪري. شايد مان هن مضمون جي مدد سان هن عمل کي تيز ڪرڻ ۾ ڪنهن جي مدد ڪري سگهان ٿو.

سمجھڻ جي پهرين شيء اها آهي ته جوابي توهان کي هڪ آسان انٽرفيس فراهم ڪري ٿو جيڪو SSH ذريعي ريموٽ سرور (ن) تي عملن جي اڳئين بيان ڪيل فهرست کي انجام ڏيڻ لاء. هتي ڪو به جادو ناهي، توهان هڪ پلگ ان انسٽال نٿا ڪري سگهو ۽ ڊاکر، مانيٽرنگ ۽ دٻي مان ٻاهر جي ٻين شين سان توهان جي ايپليڪيشن جي صفر ڊائون ٽائم ڊيپلائيمينٽ حاصل ڪري سگهو ٿا. پلي بڪ لکڻ لاءِ، توهان کي ضرور ڄاڻڻ گهرجي ته توهان ڇا ڪرڻ چاهيو ٿا ۽ اهو ڪيئن ڪجي. ان ڪري مان مطمئن نه آهيان GitHub مان تيار ڪيل پلے بڪ، يا مضمونن جهڙوڪ: “ڪاپي ڪريو ۽ هلايو، اهو ڪم ڪندو.”

اسان کي ڇا گهرجي؟

جيئن ته مون اڳ ۾ ئي چيو آهي، هڪ راند ڪتاب لکڻ لاء توهان کي ڄاڻڻ جي ضرورت آهي ته توهان ڇا ڪرڻ چاهيو ٿا ۽ اهو ڪيئن ڪجي. اچو ته فيصلو ڪريون ته اسان کي ڪهڙي ضرورت آهي. ريل ايپليڪيشن لاءِ اسان کي ڪيترن ئي سسٽم پيڪيجز جي ضرورت پوندي: nginx، postgresql (redis، وغيره). ان کان سواء، اسان کي روبي جي هڪ مخصوص نسخي جي ضرورت آهي. اهو بهترين آهي ان کي انسٽال ڪرڻ لاءِ rbenv (rvm, asdf...). روٽ استعمال ڪندڙ جي طور تي هي سڀ هلائڻ هميشه هڪ خراب خيال آهي، تنهنڪري توهان کي هڪ الڳ صارف ٺاهڻ ۽ ان جي حقن کي ترتيب ڏيڻ جي ضرورت آهي. ان کان پوء، توهان کي سرور تي اسان جو ڪوڊ اپلوڊ ڪرڻ جي ضرورت آهي، nginx، postgres، وغيره لاء ترتيبن کي نقل ڪريو ۽ اهي سڀئي خدمتون شروع ڪريو.

نتيجي طور، عملن جو سلسلو ھيٺ ڏنل آھي:

  1. روٽ طور لاگ ان ڪريو
  2. سسٽم پيڪيجز کي انسٽال ڪريو
  3. نئون استعمال ڪندڙ ٺاھيو، حقن کي ترتيب ڏيو، ssh key
  4. سسٽم پيڪيجز کي ترتيب ڏيو (nginx وغيره) ۽ انهن کي هلائڻ
  5. اسان ڊيٽابيس ۾ هڪ صارف ٺاهيو (توهان فوري طور تي ڊيٽابيس ٺاهي سگهو ٿا)
  6. نئون استعمال ڪندڙ طور لاگ ان ٿيو
  7. انسٽال ڪريو rbenv ۽ ruby
  8. بنڊل انسٽال ڪرڻ
  9. اپليڪيشن ڪوڊ اپ لوڊ ڪندي
  10. پوما سرور کي لانچ ڪرڻ

ان کان علاوه، آخري مرحلا ڪيپسٽرانو استعمال ڪندي ڪري سگھجن ٿا، گھٽ ۾ گھٽ دٻي کان ٻاهر اھو ڪوڊ ڪاپي ڪري سگھي ٿو رليز ڊاريڪٽريز ۾، رليز کي مٽائي سِم لنڪ سان ڪامياب ڊولپمينٽ تي، ڪاپي ڪنفيگرز کي شيئر ڊاريڪٽري مان نقل ڪريو، پوما وري شروع ڪريو، وغيره. اهو سڀ ڪجهه جوابي استعمال ڪندي ڪري سگهجي ٿو، پر ڇو؟

فائل جي جوڙجڪ

جواب سخت آهي فائل جي جوڙجڪ توھان جي سڀني فائلن لاءِ، تنھنڪري اھو بھتر آھي ته انھن سڀني کي الڳ ڊاريڪٽري ۾ رکيو وڃي. ان کان سواء، اهو ضروري ناهي ته ڇا اهو ريل ايپليڪيشن ۾ هوندو، يا الڳ الڳ. توھان فائلن کي ذخيرو ڪري سگھو ٿا الڳ گٽ مخزن ۾. ذاتي طور تي، مون کي ريل ايپليڪيشن جي /config ڊاريڪٽري ۾ هڪ جوابي ڊاريڪٽري ٺاهڻ ۽ هر شي کي هڪ مخزن ۾ ذخيرو ڪرڻ تمام آسان محسوس ڪيو.

سادي Playbook

Playbook هڪ yml فائل آهي، جيڪا خاص نحو استعمال ڪندي، بيان ڪري ٿي ته جوابي کي ڇا ڪرڻ گهرجي ۽ ڪيئن. اچو ته پهريون پلے بڪ ٺاهيو جيڪو ڪجھ به نه ٿو ڪري:

---
- name: Simple playbook
  hosts: all

هتي اسان کي رڳو اسان جي playbook سڏيو ويندو آهي Simple Playbook ۽ اهو ته ان جو مواد سڀني ميزبانن لاءِ عمل ڪيو وڃي. اسان ان کي محفوظ ڪري سگھون ٿا /ansible ڊاريڪٽري ۾ نالي سان playbook.yml ۽ هلائڻ جي ڪوشش ڪريو:

ansible-playbook ./playbook.yml

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

جواب ڏيڻ وارو چوي ٿو اهو ڪنهن به ميزبان کي نٿو ڄاڻي جيڪا سڀني لسٽ سان ملن. انهن کي هڪ خاص ۾ درج ڪيو وڃي inventory فائل.

اچو ته ان کي ساڳي جوابي ڊاريڪٽري ۾ ٺاهيو:

123.123.123.123

ھي آھي اسان صرف ھوسٽ جي وضاحت ڪريون ٿا (مثالي طور تي اسان جي وي پي ايس جو ميزبان ٽيسٽ لاءِ، يا توھان رجسٽر ڪري سگھو ٿا لوڪل ھوسٽ) ۽ ان کي نالي سان محفوظ ڪريو inventory.
توھان ڪوشش ڪري سگھوٿا ھڪڙي انوٽري فائل سان جوابي ھلائڻ جي:

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

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

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

جيڪڏهن توهان وٽ مخصوص ميزبان تائين ssh رسائي آهي، ته پوءِ جوابي رابطو ڪندو ۽ ريموٽ سسٽم بابت معلومات گڏ ڪندو. (ڊفالٽ TASK [حقيقتن کي گڏ ڪرڻ]) جنهن کان پوءِ اهو عمل تي مختصر رپورٽ ڏيندو (PLAY RECAP).

ڊفالٽ طور، ڪنيڪشن صارف جو نالو استعمال ڪري ٿو جنهن جي تحت توهان سسٽم ۾ لاگ ان ٿيل آهيو. اهو گهڻو ڪري ميزبان تي نه هوندو. پلے بڪ فائل ۾، توھان وضاحت ڪري سگھو ٿا ته ڪھڙو صارف استعمال ڪرڻ لاءِ استعمال ڪري ڳنڍڻ لاءِ remote_user directive. انهي سان گڏ، ريموٽ سسٽم بابت معلومات اڪثر ڪري توهان لاء غير ضروري ٿي سگهي ٿي ۽ توهان کي ان کي گڏ ڪرڻ ۾ وقت ضايع نه ڪرڻ گهرجي. هن ڪم کي به بند ڪري سگهجي ٿو:

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

پلے بڪ کي ٻيهر هلائڻ جي ڪوشش ڪريو ۽ پڪ ڪريو ته ڪنيڪشن ڪم ڪري رهيو آهي. (جيڪڏهن توهان روٽ استعمال ڪندڙ جي وضاحت ڪئي آهي، ته پوءِ توهان کي به بيان ڪرڻ جي ضرورت آهي بن: سچي هدايت اعليٰ حق حاصل ڪرڻ لاءِ. جيئن دستاويز ۾ لکيل آهي: become set to ‘true’/’yes’ to activate privilege escalation. جيتوڻيڪ اهو مڪمل طور تي واضح ناهي ڇو).

ٿي سگهي ٿو توهان کي هڪ غلطي ملي ويندي جيڪا حقيقت جي ڪري ٿي ته جوابي پٿون مترجم جو تعين نٿو ڪري سگهي، پوءِ توهان ان کي دستي طور بيان ڪري سگهو ٿا:

ansible_python_interpreter: /usr/bin/python3 

توھان ڳولي سگھوٿا جتي توھان وٽ پٿون آھي حڪم سان whereis python.

سسٽم پيڪيجز کي انسٽال ڪرڻ

جوابي جي معياري تقسيم ۾ مختلف سسٽم پيڪيجز سان ڪم ڪرڻ لاء ڪيترائي ماڊل شامل آهن، تنهنڪري اسان کي ڪنهن به سبب لاء بش اسڪرپٽ لکڻ جي ضرورت ناهي. ھاڻي اسان کي ضرورت آھي انھن مان ھڪڙو ماڊل سسٽم کي اپڊيٽ ڪرڻ ۽ سسٽم پيڪيجز کي انسٽال ڪرڻ لاءِ. مون وٽ 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

ٽاسڪ بلڪل اھو ڪم آھي جيڪو جواب ڏيندو ريموٽ سرورز تي. اسان ڪم کي هڪ نالو ڏيون ٿا ته جيئن اسان لاگ ان جي عمل کي ٽريڪ ڪري سگهون. ۽ اسان بيان ڪريون ٿا، هڪ مخصوص ماڊل جي نحو کي استعمال ڪندي، ان کي ڇا ڪرڻ جي ضرورت آهي. هن معاملي ۾ apt: update_cache=yes - چوي ٿو اپ ڊيٽ ماڊل استعمال ڪندي سسٽم پيڪيجز کي اپڊيٽ ڪرڻ. ٻيو حڪم ٿورو وڌيڪ پيچيده آهي. اسان پيڪيجز جي هڪ فهرست کي Apt ماڊل ڏانهن منتقل ڪريون ٿا ۽ چون ٿا ته اهي آهن state ٿيڻ گهرجي present، اهو آهي، اسان چئون ٿا انهن پيڪيجز کي انسٽال ڪريو. ساڳئي طرح، اسان انهن کي چئي سگھون ٿا ته انهن کي حذف ڪريو، يا انهن کي تبديل ڪندي تازه ڪاري ڪريو state. مهرباني ڪري نوٽ ڪريو ته ريل لاءِ postgresql سان ڪم ڪرڻ لاءِ اسان کي postgresql-contrib پيڪيج جي ضرورت آهي، جنهن کي اسان هاڻي انسٽال ڪري رهيا آهيون. ٻيهر، توهان کي ڄاڻڻ ۽ اهو ڪرڻ جي ضرورت آهي؛ جواب ڏيڻ وارو پنهنجو پاڻ تي اهو نه ڪندو.

پلے بڪ کي ٻيهر هلائڻ جي ڪوشش ڪريو ۽ چيڪ ڪريو ته پيڪيجز انسٽال ٿيل آهن.

نوان استعمال ڪندڙ ٺاهڻ.

صارفين سان ڪم ڪرڻ لاء، جوابي پڻ ھڪڙو ماڊل آھي - صارف. اچو ته هڪ وڌيڪ ڪم شامل ڪريون (مون تبصرن جي پويان پلي بڪ جا اڳ ۾ ئي سڃاتل حصا لڪائي ڇڏيا آهن ته جيئن هر دفعي ان کي مڪمل طور تي نقل نه ڪجي):

---
- 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') }}". شيء اها آهي ته جوابي صارف ذريعي انسٽال نٿو ڪري 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/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

هاڻي اسان کي فائلون ۽ ٽيمپليٽ جي ضرورت آهي. انهن جي وچ ۾ فرق اهو آهي ته جوابي فائلن کي سڌو نقل ڪري ٿو، جيئن آهي. ۽ ٽيمپليٽس کي لازمي طور تي j2 ايڪسٽينشن هجڻ گهرجي ۽ اهي ساڳيا ڊبل ڪرلي برائسز استعمال ڪندي متغير قدر استعمال ڪري سگهن ٿا.

اچو ته nginx کي فعال ڪريون main.yml فائل. ان لاءِ اسان وٽ آھي سسٽم ماڊل:

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

هتي اسان نه رڳو اهو چئون ٿا ته نينڪس شروع ٿيڻ گهرجي (اهو آهي، اسان ان کي لانچ ڪيو)، پر اسان فوري طور تي چئون ٿا ته ان کي فعال ڪيو وڃي.
هاڻي اچو ته ڪنفيگريشن فائلن کي نقل ڪريون:

# 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

جيڪڏهن اسان هاڻي اسان جي راند جو ڪتاب شروع ڪيو، اهو ٻنهي ميزبانن لاء مخصوص ڪم انجام ڏيندو. پر ساڳئي وقت، هڪ اسٽيجنگ ميزبان لاء، متغير پيداوار وارن کان مختلف هوندا، ۽ نه رڳو ڪردار ۽ راند بڪ ۾، پر نينڪس ترتيبن ۾ پڻ. {{ inventory_hostname }} انوینٽري فائل ۾ بيان ڪرڻ جي ضرورت ناهي - هي خاص جوابي variable ۽ ميزبان جنهن لاءِ پلي بڪ في الحال هلي رهيو آهي اتي ذخيرو ٿيل آهي.
جيڪڏھن توھان چاھيو ٿا ھڪڙي انوینٽري فائل ڪيترن ئي ھوسٽن لاءِ، پر صرف ھڪڙي گروپ لاءِ ھلايو، اھو ھيٺ ڏنل حڪم سان ڪري سگھجي ٿو:

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

ٻيو اختيار آهي مختلف گروپن لاءِ الڳ انوینٽري فائلون. يا توهان ٻن طريقن کي گڏ ڪري سگهو ٿا جيڪڏهن توهان وٽ ڪيترائي مختلف ميزبان آهن.

اچو ته واپس وڃو nginx ترتيب ڏيڻ لاءِ. ترتيب واري فائلن کي نقل ڪرڻ کان پوء، اسان کي sitest_enabled ۾ my_app.conf کان sites_available ۾ هڪ symlink ٺاهڻو پوندو. ۽ 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 کي ٻيهر شروع ڪرڻ جو ڪو به مطلب ناهي. ڇا توهان محسوس ڪيو آهي ته اسان حڪم نه ٿا لکون جهڙوڪ: "هي هن طرح ڪريو"، نحو وڌيڪ ڏسڻ ۾ اچي ٿو "هي حالت هجڻ گهرجي". ۽ اڪثر ڪري اهو ئي آهي ته ڪيئن جوابي ڪم ڪندو آهي. جيڪڏهن گروپ اڳ ۾ ئي موجود آهي، يا سسٽم پيڪيج اڳ ۾ ئي نصب ٿيل آهي، پوء جواب ڏيڻ وارو هن جي جانچ ڪندو ۽ ڪم کي ڇڏي ڏيندو. انهي سان گڏ، فائلن کي نقل نه ڪيو ويندو جيڪڏهن اهي مڪمل طور تي ملن ٿيون جيڪي اڳ ۾ ئي سرور تي آهن. اسان هن جو فائدو وٺي سگهون ٿا ۽ 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 کي فعال ڪرڻ جي ضرورت آهي جيئن اسان 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 }}"

مان وضاحت نه ڪندس ته ڪيئن انوینٽري ۾ متغير شامل ڪرڻ، اهو اڳ ۾ ئي ڪيترائي ڀيرا ڪيو ويو آهي، انهي سان گڏ پوسٽ گريسql_db ۽ postgresql_user ماڊلز جي نحو. وڌيڪ معلومات ملي ڪري سگهجي ٿو دستاويز ۾. هتي سڀ کان وڌيڪ دلچسپ هدايت آهي become_user: postgres. حقيقت اها آهي ته ڊفالٽ طور، صرف پوسٽ گريس استعمال ڪندڙ کي رسائي آهي پوسٽ گريسيڪل ڊيٽابيس تائين ۽ صرف مقامي طور تي. هي هدايت اسان کي اجازت ڏئي ٿي ته هن صارف جي طرفان حڪمن تي عمل ڪريون (جيڪڏهن اسان وٽ رسائي آهي، يقينا).
انهي سان گڏ، توهان کي شايد pg_hba.conf ۾ هڪ لائن شامل ڪرڻي پوندي ته جيئن ڊيٽابيس تائين نئين صارف جي رسائي جي اجازت ڏني وڃي. اهو ساڳيو طريقي سان ٿي سگهي ٿو جيئن اسان nginx ترتيب کي تبديل ڪيو.

۽ يقينا، توهان کي شامل ڪرڻ جي ضرورت آهي postgresql ڪردار مکيه راند ڪتاب ۾.

rbenv ذريعي روبي کي انسٽال ڪرڻ

جوابي ۾ rbenv سان ڪم ڪرڻ لاء ماڊل نه آهن، پر اهو هڪ گٽ مخزن کي ڪلون ڪندي نصب ڪيو ويو آهي. تنهن ڪري، هي مسئلو سڀ کان غير معياري بڻجي ويندو آهي. اچو ته هن لاء هڪ ڪردار ٺاهيو /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 ان جي گهر ڊاريڪٽري ۾ نصب ٿيل آهي، ۽ عالمي طور تي نه. ۽ اسان پڻ استعمال ڪريون ٿا گيٽ ماڊل مخزن کي ڪلون ڪرڻ لاءِ، وضاحت ڪندي ريپو ۽ منزل.

اڳيون، اسان کي رجسٽر ڪرڻ جي ضرورت آهي rbenv init bashrc ۾ ۽ rbenv کي PATH ۾ شامل ڪريو. ان لاءِ اسان وٽ آهي lineinfile module:

- 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

۽ آخرڪار روبي انسٽال ڪريو. اهو rbenv ذريعي ڪيو ويندو آهي، اهو آهي، بس بش حڪم سان:

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

اسان چئون ٿا ته ڪهڙي حڪم تي عمل ڪجي ۽ ڪهڙي سان. بهرحال، هتي اسان کي حقيقت نظر اچي ٿي ته جوابي ڪمن کي هلائڻ کان اڳ bashrc ۾ موجود ڪوڊ کي نه هلندو آهي. هن جو مطلب اهو آهي ته rbenv کي سڌو سنئون ساڳئي اسڪرپٽ ۾ بيان ڪرڻو پوندو.

ايندڙ مسئلو ان حقيقت جي ڪري آهي ته شيل ڪمانڊ وٽ ڪا به حالت نه آهي هڪ جوابي نقطي نظر کان. اهو آهي، ڪو به خودڪار چيڪ نه ٿيندو ته روبي جو هي نسخو نصب ٿيل آهي يا نه. اسان اهو پاڻ ڪري سگهون ٿا:

- 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 کي مکيه راند ڪتاب ۾.

حصيداري فائلون.

عام طور تي، سيٽ اپ مڪمل ٿي سگهي ٿو هتي. اڳيون، اهو سڀ ڪجهه باقي رهي ٿو ڪئپسٽريانو کي هلائڻ ۽ اهو ڪوڊ پاڻ کي نقل ڪندو، ضروري ڊائريڪٽري ٺاهي ۽ ايپليڪيشن کي لانچ ڪندو (جيڪڏهن هر شيء صحيح ترتيب ڏنل آهي). جڏهن ته، ڪئپسٽريانو اڪثر ڪري اضافي ترتيبن جي فائلن جي ضرورت هوندي آهي، جهڙوڪ database.yml يا .env اهي نقل ڪري سگھجن ٿيون جهڙوڪ فائلون ۽ ٽيمپليٽ nginx لاءِ. اتي رڳو هڪ subtlety آهي. فائلن کي نقل ڪرڻ کان پهريان، توهان کي انهن لاء ڊاريڪٽري جي جوڙجڪ ٺاهڻ جي ضرورت آهي، ڪجهه هن طرح:

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

اسان صرف هڪ ڊاريڪٽري جي وضاحت ڪريون ٿا ۽ جيڪڏهن ضروري هجي ته جوابي خودڪار طور تي والدين ٺاهي سگهندا.

جوابي والٽ

اسان اڳ ۾ ئي حقيقت ۾ اچي چڪا آهيون ته متغير ڳجهي ڊيٽا تي مشتمل هوندا جهڙوڪ صارف جو پاسورڊ. جيڪڏھن توھان ٺاھيو آھي .env اپليڪيشن لاء فائل، ۽ database.yml پوء اتي اڃا به وڌيڪ اهڙي نازڪ ڊيٽا هجڻ ضروري آهي. اهو سٺو ٿيندو ته انهن کي لڪائڻ جي اکين کان لڪائي. هن مقصد لاء استعمال ڪيو ويندو آهي قابل جواب خزانو.

اچو ته variables لاءِ فائل ٺاھيون /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-playbook -i inventory ./playbook.yml -l "staging" --ask-vault-pass

پر مان توهان کي ڊرامي بڪ ۽ ڪردارن جو پورو متن نه ڏيندس، پاڻ لکندس. ڇاڪاڻ ته جواب ڏيڻ جهڙو آهي - جيڪڏهن توهان نٿا سمجهو ته ڇا ڪرڻ جي ضرورت آهي، پوءِ اهو توهان لاءِ نه ڪندو.

جو ذريعو: www.habr.com

تبصرو شامل ڪريو