Легко і невимушено деплоім програми на Tarantool Cartridge (частина 1)

Легко і невимушено деплоім програми на Tarantool Cartridge (частина 1)

Ми вже розповідали про Tarantool Cartridge, який дозволяє розробляти розподілені програми та пакувати їх. Залишилося всього нічого: навчитися деплоїти ці додатки та керувати ними. Не турбуйтеся, ми все передбачили! Ми зібрали разом усі best practices по роботі з Tarantool Cartridge та написали ansible-роль, яка розкладе пакет на сервери, стартане інстанси, об'єднає їх у кластер, налаштує авторизацію, забуде в vhard, включить автоматичний failover і пропатчить кластерний конфіг.

Цікаво? Тоді прошу під кат, все розповімо та покажемо.

Почнемо з прикладу

Ми розглянемо лише частину функціональності нашої ролі. Повний опис всіх її можливостей та вхідних параметрів ви завжди можете знайти у документації. Але краще один раз спробувати, ніж сто разів побачити, тому давайте задеплоїмо невелику програму.

У Tarantool Cartridge є туторіал зі створення невеликого Cartridge-додатка, яке зберігає інформацію про клієнтів банку та їх рахунки, а також надає API для керування даними через HTTP. Для цього в додатку описуються дві можливі ролі: api и storage, які можуть бути призначені інстансам.

Сам Cartridge нічого не говорить про те, як запускати процеси, він лише надає можливість налаштувати вже запущені інстанси. Решта користувач повинен зробити сам: розкласти файли конфігурації, запустити сервіси і налаштувати топологію. Але ми не будемо цим займатися, за нас це зробить Ansible.

Від слів до справи

Отже, задеплоєм наш додаток на дві віртуалки і налаштуємо просту топологію:

  • Реплікасет app-1 реалізовуватиме роль apiяка включає в себе роль vshard-router. Тут буде лише одна інстанс.
  • Реплікасет storage-1 реалізує роль storage (і одночасно vshard-storage), сюди додамо дві інстанси з різних машин.

Легко і невимушено деплоім програми на Tarantool Cartridge (частина 1)

Для запуску прикладу нам знадобляться Бродяга и Неможливо (версії 2.8 чи старше).

Сама роль знаходиться в Галактика Ансібль. Це таке сховище, яке дозволяє ділитися своїми напрацюваннями та використовувати готові ролі.

Схиляємо репозиторій із прикладом:

$ git clone https://github.com/dokshina/deploy-tarantool-cartridge-app.git
$ cd deploy-tarantool-cartridge-app && git checkout 1.0.0

Піднімаємо віртуалки:

$ vagrant up

Встановлюємо ansible роль Tarantool Cartridge:

$ ansible-galaxy install tarantool.cartridge,1.0.1

Запускаємо встановлену роль:

$ ansible-playbook -i hosts.yml playbook.yml

Чекаємо на закінчення виконання плейбука, переходимо на http://localhost:8181/admin/cluster/dashboard і насолоджуємося результатом:

Легко і невимушено деплоім програми на Tarantool Cartridge (частина 1)

Дані можна лити. Круто, правда?

А тепер давайте розберемося, як із цим працювати, і заразом додамо ще один реплікасет у топологію.

Починаємо розбиратися

Отже, що ж сталося?

Ми підняли дві віртуальні машини та запустили ansible-плейбук, який налаштував наш кластер. Давайте подивимося на вміст файлу playbook.yml:

---
- name: Deploy my Tarantool Cartridge app
  hosts: all
  become: true
  become_user: root
  tasks:
  - name: Import Tarantool Cartridge role
    import_role:
      name: tarantool.cartridge

Тут нічого цікавого не відбувається, запускаємо ansible-роль, яка називається tarantool.cartridge.

Все найважливіше (зокрема, конфігурація кластера) перебуває у інвентаризація-файлі hosts.yml:

---
all:
  vars:
    # common cluster variables
    cartridge_app_name: getting-started-app
    cartridge_package_path: ./getting-started-app-1.0.0-0.rpm  # path to package

    cartridge_cluster_cookie: app-default-cookie  # cluster cookie

    # common ssh options
    ansible_ssh_private_key_file: ~/.vagrant.d/insecure_private_key
    ansible_ssh_common_args: '-o IdentitiesOnly=yes -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'

  # INSTANCES
  hosts:
    storage-1:
      config:
        advertise_uri: '172.19.0.2:3301'
        http_port: 8181

    app-1:
      config:
        advertise_uri: '172.19.0.3:3301'
        http_port: 8182

    storage-1-replica:
      config:
        advertise_uri: '172.19.0.3:3302'
        http_port: 8183

  children:
    # GROUP INSTANCES BY MACHINES
    host1:
      vars:
        # first machine connection options
        ansible_host: 172.19.0.2
        ansible_user: vagrant

      hosts:  # instances to be started on the first machine
        storage-1:

    host2:
      vars:
        # second machine connection options
        ansible_host: 172.19.0.3
        ansible_user: vagrant

      hosts:  # instances to be started on the second machine
        app-1:
        storage-1-replica:

    # GROUP INSTANCES BY REPLICA SETS
    replicaset_app_1:
      vars:  # replica set configuration
        replicaset_alias: app-1
        failover_priority:
          - app-1  # leader
        roles:
          - 'api'

      hosts:  # replica set instances
        app-1:

    replicaset_storage_1:
      vars:  # replica set configuration
        replicaset_alias: storage-1
        weight: 3
        failover_priority:
          - storage-1  # leader
          - storage-1-replica
        roles:
          - 'storage'

      hosts:   # replica set instances
        storage-1:
        storage-1-replica:

Все, що нам потрібно, це навчитися керувати інстансами і реплікасетами, змінюючи вміст цього файлу. Далі ми додаватимемо до нього нові секції. Щоб не заплутатися, куди їх додавати, можете підглядати у фінальну версію цього файлу, hosts.updated.yml, що знаходиться в репозиторії з прикладом.

Управління інстансами

У термінах Ansible кожен інстанс — це хост (не плутати із залізним сервером), тобто. вузол інфраструктури, яким Ansible керуватиме. Для кожного хоста ми можемо вказати параметри з'єднання (такі як ansible_host и ansible_user), і навіть конфігурацію инстанса. Опис інстансів знаходиться в секції hosts.

Розглянемо конфігурацію інстансу storage-1:

all:
  vars:
    ...

  # INSTANCES
  hosts:
    storage-1:
      config:
        advertise_uri: '172.19.0.2:3301'
        http_port: 8181

  ...

У змінній config ми вказали параметри інстансу advertise URI и HTTP port.
Нижче знаходяться параметри інстансів app-1 и storage-1-replica.

Ми повинні повідомити Ansible параметри з'єднання для кожного інстансу. Здається логічним об'єднати інстанси у групи з віртуальних машин. Для цього інстанси об'єднані у групи host1 и host2, і в кожній групі у секції vars вказані значення ansible_host и ansible_user для однієї віртуалки. А у секції hosts - хости (вони ж інстанси), які входять до цієї групи:

all:
  vars:
    ...
  hosts:
    ...
  children:
    # GROUP INSTANCES BY MACHINES
    host1:
      vars:
        # first machine connection options
        ansible_host: 172.19.0.2
        ansible_user: vagrant
       hosts:  # instances to be started on the first machine
        storage-1:

     host2:
      vars:
        # second machine connection options
        ansible_host: 172.19.0.3
        ansible_user: vagrant
       hosts:  # instances to be started on the second machine
        app-1:
        storage-1-replica:

Починаємо змінювати hosts.yml. Додамо ще два інстанси, storage-2-replica на першій віртуалці та storage-2 на другий:

all:
  vars:
    ...

  # INSTANCES
  hosts:
    ...
    storage-2:  # <==
      config:
        advertise_uri: '172.19.0.3:3303'
        http_port: 8184

    storage-2-replica:  # <==
      config:
        advertise_uri: '172.19.0.2:3302'
        http_port: 8185

  children:
    # GROUP INSTANCES BY MACHINES
    host1:
      vars:
        ...
      hosts:  # instances to be started on the first machine
        storage-1:
        storage-2-replica:  # <==

    host2:
      vars:
        ...
      hosts:  # instances to be started on the second machine
        app-1:
        storage-1-replica:
        storage-2:  # <==
  ...

Запускаємо ansible-плейбук:

$ ansible-playbook -i hosts.yml 
                   --limit storage-2,storage-2-replica 
                   playbook.yml

Зверніть увагу на опцію --limit. Оскільки кожен інстанс кластера є хостом у термінах Ansible, ми можемо явно вказувати, які інстанси мають бути налаштовані під час виконання плейбука.

Знову заходимо у Web UI http://localhost:8181/admin/cluster/dashboard і спостерігаємо наші нові інстанси:

Легко і невимушено деплоім програми на Tarantool Cartridge (частина 1)

Не будемо зупинятись на досягнутому та освоїмо управління топологією.

Управління топологією

Об'єднаємо наші нові інстанси у реплікасет storage-2. Додамо нову групу replicaset_storage_2 і опишемо в її змінних параметри реплікасета за аналогією до replicaset_storage_1. У секції hosts вкажемо, які інстанси входитимуть до цієї групи (тобто наш реплікасет):

---
all:
  vars:
    ...
  hosts:
    ...
  children:
    ...
    # GROUP INSTANCES BY REPLICA SETS
    ...
    replicaset_storage_2:  # <==
      vars:  # replicaset configuration
        replicaset_alias: storage-2
        weight: 2
        failover_priority:
          - storage-2
          - storage-2-replica
        roles:
          - 'storage'

      hosts:   # replicaset instances
        storage-2:
        storage-2-replica:

Знову запускаємо плейбук:

$ ansible-playbook -i hosts.yml 
                   --limit replicaset_storage_2 
                   --tags cartridge-replicasets 
                   playbook.yml

У параметр --limit цього разу ми передали ім'я групи, яка відповідає нашому реплікасету.

Розглянемо опцію tags.

Наша роль послідовно виконує різні завдання, які позначені наступними тегами:

  • cartridge-instances: управління інстансами (налаштування, підключення до membership);
  • cartridge-replicasets: управління топологією (управління реплікасетами та безповоротне видалення (expel) інстансів з кластера);
  • cartridge-config: керування іншими параметрами кластера (vshard bootstrapping, режим автоматичного failover-а, параметри авторизації та конфігурація програми).

Ми можемо явно вказати, яку частину роботи хочемо зробити, тоді роль пропустить виконання інших завдань. У нашому випадку ми хочемо працювати тільки з топологією, тож вказали cartridge-replicasets.

Давайте оцінимо результат наших старань. Знаходимо новий реплікасет на http://localhost:8181/admin/cluster/dashboard.

Легко і невимушено деплоім програми на Tarantool Cartridge (частина 1)

Ура!

Поекспериментуйте зі зміною конфігурації інстансів та реплікасетів та подивіться, як змінюється топологія кластера. Ви можете випробувати різні експлуатаційні сценарії, наприклад, rolling update або збільшення memtx_memory. Роль спробує зробити це без рестарту інстансу, щоб скоротити можливий даунтайм вашої програми.

Не забудьте запустити vagrant halt, щоб зупинити віртуалки, коли закінчите працювати з ними.

А що під капотом?

Тут я розповім докладніше про те, що відбувалося під капотом ansible-ролі під час наших експериментів.

Розглянемо кроки деплой Cartridge-додатки.

Встановлення пакету та старт інстансів

Спочатку потрібно доставити пакет на сервер та встановити його. Нині роль вміє працювати з RPM- та DEB-пакетами.

Далі запускаємо інстанси. Тут все дуже просто: кожен інстанс це окремий systemd-Сервіс. Розповідаю на прикладі:

$ systemctl start myapp@storage-1

Ця команда запустить інстанс storage-1 додатки myapp. Запущений інстанс шукатиме свою конфігурацію в /etc/tarantool/conf.d/. Логи інстансу можна буде подивитися за допомогою journald.

Unit-файл /etc/systemd/system/[email protected] для systemd-сервісу буде доставлено разом із пакетом.

У Ansible є вбудовані модулі для встановлення пакетів та управління systemd-сервісами, тут ми нічого нового не винайшли.

Налаштування топології кластера

А ось тут починається найцікавіше. Погодьтеся, було б дивно морочитися зі спеціальною ansible-роллю для встановлення пакетів та запуску systemd-Сервис.

Налаштувати кластер можна вручну:

  • Перший варіант: відкриваємо Web UI та натискаємо на кнопочки. Для разового старту кількох інстансів цілком підійде.
  • Другий варіант: можна використовувати GraphQl API. Тут уже можна щось автоматизувати, наприклад, написати скрипт на Python.
  • Третій варіант (для сильних духом): заходимо на сервер, коннектимося до одного з інстансів за допомогою tarantoolctl connect і робимо всі необхідні маніпуляції з Lua-модулем cartridge.

Основне завдання нашого винаходу – зробити за вас саме цю, найскладнішу частину роботи.

Ansible дозволяє написати свій модуль та використовувати його в ролі. Наша роль використовує такі модулі для керування різними компонентами кластера.

Як це працює? Ви описуєте бажаний стан кластера в декларативному конфізі, а роль подає на вхід кожному модулю його секцію конфігурації. Модуль отримує поточний стан кластера і порівнює його з тим, що надійшло на вхід. Далі через сокет однієї з інстансів запускається код, що призводить кластер до потрібного стану.

Підсумки

Сьогодні ми розповіли і показали, як задеплоїти вашу програму на Tarantool Cartridge і налаштувати просту топологію. Для цього ми використовували Ansible – потужний інструмент, який відрізняється простотою у використанні та дозволяє одночасно налаштовувати безліч вузлів інфраструктури (у нашому випадку це інстанси кластера).

Вище ми розібралися з одним із безлічі методів опису зміни кластера засобами Ansible. Як тільки ви зрозумієте, що готові йти далі, вивчіть передового досвіду з написання плейбуків. Можливо, вам буде зручніше керувати топологією за допомогою group_vars и host_vars.

Незабаром ми розповімо, як безповоротно видаляти (expel) інстанси з топології, бутстрапить vshard, керувати режимом автоматичного failover-а, налаштовувати авторизацію і патчити кластерний конфіг. А поки що ви можете самостійно вивчати документацію та експериментувати зі зміною параметрів кластера.

Якщо щось не працює, обов'язково повідомте нам про проблему. Ми оперативно все розрулимо!

Джерело: habr.com

Додати коментар або відгук