Два года назад мы уже рассказывали вам, что такое Cartridge и как с его помощью разрабатывать распределенные приложения. Это полноценный фреймворк, в который входит CLI-интерфейс, который сильно упрощает разработку и эксплуатацию приложений на Tarantool Cartridge.
Я расскажу вам, как можно использовать Cartridge CLI для эффективного использования ваших локальных приложений, и об интересных фичах самого CLI. Статья больше ориентирована на тех, кто уже использует Cartridge или хочет начать им пользоваться. Поехали!
Какие проблемы решает Cartridge CLI?
У нас есть Tarantool Cartridge, который решает проблемы взаимодействия и масштабирования нескольких микросервисов в рамках одного приложения. Поговорим о трудностях, которые возникают в процессе разработки.
С чего начать?
Вы захотели использовать Cartridge. Первая мысль, которая возникает в вашей голове: «Как мне запустить мое приложение?» Как минимум, вам нужно реализовать точку входа. Но при этом вы решите лишь часть проблемы — дальше нужно будет понять, как вообще запускать приложение.
Cartridge CLI содержит готовый шаблон приложения. В этом шаблоне есть все необходимые файлы (и не только) для того, чтобы запустить и сконфигурировать ваш кластер. Вам не нужно думать, какие файлы создать в проекте, что они должны из себя представлять и так далее. Кроме того, в стандартный шаблон легко вносить изменения в соответствии с вашими нуждами.
Сборка, запуск и настройка приложения
Приложение нужно собрать: как минимум — поставить сам Cartridge (он устанавливается как отдельный Lua-пакет), а как максимум — еще десяток зависимостей в виде Lua-пакетов (и не только), которые используются в вашем приложении. Конечно, вы можете написать свой скрипт, который будет собирать приложение за вас, и использовать его в каждом вашем приложении. Но зачем всякий раз придумывать велосипед?
Допустим, приложение вы успешно собрали. Теперь вы хотите локально запустить экземпляры и сконфигурировать приложение: создать наборы реплик, выставить им роли и так далее… В Cartridge CLI есть всего три команды, с помощью которых можно выполнить вышеуказанные действия в одну строчку: собрать, запустить и настроить ваше приложение.
Настройка набора реплик и failover
Да, управление через GUI нельзя называть проблемой. Для кого-то, может быть, это будет плюсом. Но я всё равно решил выделить как отдельное преимущество Cartridge CLI, и сейчас объясню почему:
- Для того, чтобы сконфигурировать кластер через GUI, нужно зайти в браузер и сделать N кликов. Чтобы сделать то же самое с помощью CLI, достаточно ввести одну команду. Как минимум, это экономия времени.
- Если вы решите сбросить конфигурацию кластера в GUI и заново настроить его, то всё придется повторить — сделать еще N кликов вместо вызова одной команды.
- Вы можете однажды собрать минимальную конфигурацию кластера, сохранить её в файл и закоммитить в репозиторий. После этого кто угодно (в том числе и вы при каждом перезапуске кластера) сможет поднимать настроенный кластер одной командой.
- Может быть, вам просто совсем не нравится пользоваться GUI.
Упаковка приложения
Представьте, что вы написали приложение и хотите отправить его клиенту в формате rpm-пакета. Сначала вам нужно будет описать файл .spec, установить (например) утилиту rpmbuild, и только после этого начать сборку пакета. Утомительно, не правда ли?
В Cartridge CLI процесс упаковки приложения унифицирован, содержит основные формы упаковки приложения (deb, rpm, tgz и Docker image) и много упрощающих этот процесс опций. Всё это позволяет не думать об упаковке в принципе, а просто вызвать одну команду с удобным интерфейсом.
Создаем и запускаем первое приложение
Для начала нам потребуется установить Cartridge CLI.
Установка на Debian или Ubuntu:
curl -L https://tarantool.io/IMYxqhi/release/2.7/installer.sh | bash sudo apt install cartridge-cli
Установка на CentOS, Fedora или ALT Linux:
curl -L https://tarantool.io/IMYxqhi/release/2.7/installer.sh | bash sudo yum install cartridge-cli
Установка на MacOS:
brew install cartridge-cli
Чтобы убедиться в успешной установке введите команду:
cartridge version
В случае, если всё прошло успешно, вы увидите следующее сообщение:
Не обращайте внимание на предупреждение, ведь проект мы еще не создали (и, соответственно, не установили сам Cartridge).
Команда cartridge create
создает приложение с использованием стандартного шаблона приложения на Cartridge:
cartridge create --name myapp && cd myapp
Стандартный шаблон приложения содержит файлы:
### Файлы приложения ├── README.md ├── init.lua ├── stateboard.init.lua ├── myapp-scm-1.rockspec ├── app │ ├── admin.lua │ └── roles ### Сборка и упаковка ├── cartridge.pre-build ├── cartridge.post-build ├── Dockerfile.build.cartridge ├── Dockerfile.cartridge ├── package-deps.txt ├── systemd-unit-params.yml ### Локальный запуск приложения ├── instances.yml ├── replicasets.yml ├── failover.yml ├── .cartridge.yml ├── tmp ### Тестирование ├── deps.sh ├── test │ ├── helper.lua │ ├── integration │ └── unit
Если вам не нравится стандартный шаблон приложения, то можете создать свой шаблон и использовать его:
cartridge create --from mytemplate --name mycustomapp && cd mycustomapp
В корне проекта сразу инициализируется локальный Git-репозиторий, который уже содержит первый коммит:
Чтобы запустить экземпляры, соберем наше приложение:
cartridge build
Сборка выполняется с помощью утилиты tarantoolctl: она устанавливает все необходимые зависимости, в том числе Cartridge. Зависимости описаны в файле myapp-scm-1.rockspec. Если в вашем проекте понадобилась еще какая-либо зависимость, отредактируйте файл .rockspec, поместив зависимость туда, и введите команду cartridge build
.
Проект содержит файл cartridge.pre-build: он запускается перед установкой зависимостей. Например, вы можете установить нестандартные модули rocks с помощью той же tarantoolctl:
#!/bin/sh tarantoolctl rocks make --chdir ./third_party/my-custom-rock-module
Проверим, что проект был успешно собран и все зависимости установлены:
На экране появилась информация о версии Cartridge и список rocks проекта — информация о них выводится на экран, если указан флаг --rocks
.
В файле instances.yml можно сконфигурировать ваши экземпляры (имя, порт и так далее). Описание должно быть в формате <имя-приложения>.<имя экземпляра>
. Стандартый шаблон приложения уже содержит этот файл:
myapp.router: advertise_uri: localhost:3301 http_port: 8081 myapp.s1-master: advertise_uri: localhost:3302 http_port: 8082 myapp.s1-replica: advertise_uri: localhost:3303 http_port: 8083 myapp.s2-master: advertise_uri: localhost:3304 http_port: 8084 myapp.s2-replica: advertise_uri: localhost:3305 http_port: 8085
Чтобы запустить описанные в этом файле экземпляры, используйте команду cartridge start
:
cartridge start -d # убедимся, что все инстансы приложения были успешно запущены cartridge status
Не обязательно запускать сразу все экземпляры. Можно, например, запустить лишь один s1-master
:
cartridge start s1-master -d cartridge status s1-master
Точкой входа в наше приложение является файл с именем init.lua. Именно он под капотом запускает cartridge start
.
Стандартный шаблон приложения в своём корне содержит папку tmp.
- tmp/run — директория, хранящая PID процессов-экземпляров и socket-файлы;
- tmp/data — директория, хранящая данные экземпляров;
- tmp/log — директория, хранящая логи экземпляров.
Вы можете изменить стандартные пути к вышеописанным директориям, указав новые пути в файле .cartridge.yml или с помощью флагов команды cartridge start
. Чтобы запустить экземпляры в фоновом режиме, используйте флаг -d
. В таком случае логи будут сохраняться в файл и мы сможем их посмотреть с помощью команды cartridge log
:
С помощью флага --stateboard
или настройки stateboard: true
в файле конфигурации .cartridge.yml вы можете также запустить изолированный экземпляр Tarantool, который можно будет использовать в качестве поставщика состояний для failover. Я предлагаю всегда запускать экземпляр stateboard (в дальнейшем его можно использовать для настройки failover), поэтому стандартный шаблон приложения уже содержит флаг stateboard: true
. При необходимости вы можете безболезненно убрать этот флаг из файла конфигурации.
Настраиваем топологию
Команда cartridge replicasets
позволяет выполнять различные действия по изменению топологии кластера (например, из конфигурационного файла) и сохранять конфигурацию кластера в файл. Созданный командой cartridge create
шаблон приложения содержит файл replicasets.yml, с помощью которого мы можем сконфигурировать базовую топологию нашего кластера:
cartridge replicasets setup --bootstrap-vshard # убедимся, что топология была успешно настроена cartridge replicasets list
Всё! Одной командой мы настроили топологию, а также включили шардирование. Круто, не правда ли? Рассмотрим файл replicasets.yml подробнее:
router: instances: - router roles: - failover-coordinator - vshard-router - app.roles.custom all_rw: false s-1: instances: - s1-master - s1-replica roles: - vshard-storage weight: 1 all_rw: false vshard_group: default s-2: instances: - s2-master - s2-replica roles: - vshard-storage weight: 1 all_rw: false vshard_group: default
В нем содержится три набора реплик с именами router, s-1 и s-2.
instances
— в этом блоке описаны экземпляры, которые содержит каждый из набора реплик. Имена экземпляров должны совпадать с именами, которые описаны в instances.yml.- В блоке
roles
описаны роли для каждого набора реплик; weight
— vshard-вес набора реплик.all_rw
— флаг, указывающий, что все экземпляры в наборе реплик должны быть доступны как для чтения, так и для записи.vshard_group
— имя группы vshard, к которой принадлежит набор реплик.
Если вдруг вам захотелось настроить всё это в ручную (без использования конфига replicasets.yml), то можете воспользоваться другими опциями cartridge replicasets
:
# объединим экземпляры s1-master и s1-replica в набор реплик s-1: cartridge replicasets join --replicaset s-1 s1-master s1-replica # добавим реплику router: cartridge replicasets join --replicaset router router # посмотрим текущие доступные роли и выберем из них подходящие для каждой из реплик: cartridge replicasets list-roles # добавим роль vshard-storage для набора реплик s-1: cartridge replicasets add-roles --replicaset s-1 vshard-storage # также добавим роли для реплики router: cartridge replicasets add-roles \ --replicaset router \ vshard-router app.roles.custom failover-coordinator metrics # и наконец забутстрапим vshard: cartridge replicasets bootstrap-vshard # посмотрим конфигурацию набора реплик: cartridge replicasets list
Сбросить заданную конфигурацию кластера можно с помощью следующих команд:
cartridge stop cartridge clean
Настраиваем failover
После конфигурации топологии кластера, можно настроить failover:
cartridge failover setup # посмотрим состояние failover cartridge failover status
Команда cartridge failover setup
использует конфигурацию, описанную в файле failover.yml, который находится в корне созданного приложения.
mode: stateful state_provider: stateboard stateboard_params: uri: localhost:4401 password: passwd
У failover может быть три состояния: eventual, stateful и disabled:
- eventual и disabled не требуют никаких дополнительных настроек;
- stateful требует указания поставщика состояний (поле
state_provider
) и указания параметров для этого поставщика. На данный момент поддерживаются поставщики stateboard и etcd2.
Подробнее об архитектуре failover вы можете прочитать здесь. А здесь вы можете прочитать о всех параметрах, которые вы можете указать при его конфигурации. Вы также можете использовать команду cartridge failover set
для ввода настроек failover прямо в командной строке:
cartridge failover set stateful \ --state-provider etcd2 \ --provider-params '{"lock_delay": 15}'
Для отключения failover используйте следующие команды:
cartridge failover disable # или cartridge failover set disabled
Подключаемся к экземплярам
Вам вдруг понадобилось подключиться экземпляру и ввести там интересующие вас команды, например, выполнить cartridge.reload_roles()? Легко!
С помощью cartridge enter
вы можете подключиться к экземпляру через консольный сокет, размещенный в run-dir. Никаких дополнительных параметров не нужно, достаточно ввести имя экземпляра, указанного в instances.yml
:
cartridge enter instance-name
Вы также можете использовать cartridge connect
для подключения к интересующему вас экземпляру. Отличие этого подхода в том, что вы можете указать адрес экземпляра или путь к UNIX-сокету.
cartridge connect localhost:3301 \ --username admin \ --password secret-cluster-cookie # либо cartridge connect admin:secret-cluster-cookie@localhost:3301
Упаковываем приложение
Для упаковки приложения есть команда cartridge pack <tуpe>
. На данный момент поддерживается четыре варианта упаковки:
deb
— deb-пакет;rpm
— rpm-пакет;tgz
— tgz-архив;docker
— Docker-образ.
Например, для упаковки вашего приложения в tgz-архив используйте следующую команду:
cartridge pack tgz
Хотите собрать rpm- или deb-пакет, но при этом используете MacOS? Вы не можете сделать это просто так: в упакованном приложении будут rocks и исполняемые файлы, которые нельзя использовать в Linux. Специально для такого случая существует флаг --use-docker
, который собирает в Docker:
cartridge pack deb --use-docker
Помимо --use-docker
, команда cartridge pack
имеет множество других полезных опций. Рассмотрим самые интересные из них.
Добавляем зависимости в пакет
Добавим в наш rpm- или deb-пакет какую-нибудь зависимость. Например, unzip:
cartridge pack deb --deps unzip>=6.0
Либо вы можете описать зависимости для вашего пакета в файле package-deps.txt, который уже находится в корне созданного приложения:
unzip==6.0 neofetch>=6,<7 gcc>8
Теперь, упаковав приложение с помощью команды cartridge pack deb
, ваш пакет будет содержать зависимости unzip, neofetch и gcc. Вы можете использовать файл с другим именем для указания ваших зависимостей с помощью флага --deps-file
:
cartridge pack rpm --deps-file=path-to-deps-file
Добавляем сборочные сценарии до (и после)
А что если во время упаковки вам нужно создать файл, папку, поставить какую-либо утилиту — то есть внести какие-либо изменения в сценарий упаковки приложения? Для этого используются файлы preinst.sh и postinst.sh.
Все пути к исполняемым файлам в сценариях до и после установки должны быть абсолютными. Либо используйте /bin/sh -c ''
:
/bin/sh -c 'touch file-path' /bin/sh -c 'mkdir dir-path'
С помощью флагов --preinst
и --postinst
вы можете использовать файлы с любым именем:
cartridge pack rpm \ --preinst=path-to-preinst-script \ --posints=path-to-posinst-script
Сценарии работают только для сборки rpm- и deb-пакетов.
Кешируем пути
При каждом запуске упаковки приложение собирается с нуля. Например, сборка всех зависимостей (т.е. rocks) начинается заново. Чтобы этого избежать (и уменьшить время переупаковки приложения), существует опция кеширования путей и файл pack-cache-config.yml:
- path: '.rocks': key-path: 'myapp-scm-1.rockspec' - path: 'node_modules': always-cache: true - path: 'third_party/custom_module': key: 'simple-hash-key'
Рассмотрим подробнее параметры конфигурационного файла:
path
— путь от корня проекта до кешируемого пути;key-path
— путь до файла, содержимое которого будет ключом кеширования. В примере выше для пути .rocks ключом кеширования является файл myapp-scm-1.rockspec — если изменить его, то cache hit не произойдет и все rocks приложения будут собираться заново;always-cache
— кеширование указанного пути всегда, независимо от каких-либо ключей;key
— простой ключ кеширования в виде строки.
В стандартном шаблоне приложения уже содержится один кешируемый путь:
- path: '.rocks' key-path: myapp-scm-1.rockspec
Я предлагаю всегда кешировать содержимое папки .rocks опираясь на содержимое файла .rockspec. Для одного пути может быть только один кеш. Например, у вас в кеше находится папка .rocks, вы меняете ключ и запускаете упаковку приложения. В этот момент старый кеш .rocks удаляется и заменяется новым на основе нового ключа.
Чтобы отключить кеширование путей, используйте флаг --no-cache
. С полным списком опций команды cartridge pack
вы можете ознакомиться здесь.
Подробнее о процессе упаковки
Команда cartridge pack
помимо упаковки приложения в пакет ещё и собирает его (аналогично команде cartridge build
). По умолчанию сборка выполняется во временной директории ~/.cartridge/tmp. Вы можете изменить её на свою, установив значение переменной окружения CARTRIDGE_TEMPDIR
:
- Если эта директория не существует, она будет создана и использована для сборки приложения, а затем удалена.
- В противном случае сборка будет выполнена в директории
CARTRIDGE_TEMPDIR/cartridge.tmp
.
Создание временной директории (в которой будет выполняться сборка) с исходными файлами вашего приложения происходит в три этапа:
- Копирование файлов во временную директорию и её очистка. Папка с приложением копируется во временную директорию, выполняется команда
git clean -X -d -f
для удаления неотслеживаемых файлов и удаляются папки .rocks и .git. - Сборка приложения в очищенной директории.
- Запуск скрипта cartridge.post-build (если он существует).
В корне проекта находится файл cartridge.post-build. Это скрипт, основная цель которого — удаление артефактов сборки из результирующего пакета. После сборки приложения во временной директории генерируются специальные файлы, такие как VERSION и VERSION.lua, которые содержат версию приложения. В случае сборки в rpm и deb инициализируются директории systemd и tmpfiles. Далее приложение упаковывается.
Подробнее о структуре и дальнейшей работе с полученными rpm- и deb-пакетами вы можете прочитать здесь. А здесь — про работу с Docker-образами.
Итоги
Cartridge CLI содержит удобный и унифицированный интерфейс для управления приложением и позволяет не придумывать велосипед. В этой статье я рассказал о том, как можно из командной строки максимально эффективно и удобно управлять вашим локальным приложением, написанным на Tarantool Cartridge: запускать, настраивать топологию и failover, упаковывать приложение и подключаться к его экземплярам.
Cartridge CLI имеет еще одну команду, о которой я не рассказал в этой статье. Команда cartridge admin
призвана упростить разработчикам написание и поддержку эксплуатационных кейсов, повысить переиспользование операций, оптимизировать поставку в эксплуатацию. Почитать подробнее об этом вы можете в этой статье.
Если у вас что-то вдруг пошло не так, или вы знаете, как можно улучшить продукт, то всегда можете завести тикет в нашем GitHub-репозитории. Мы всегда поможем с решением вашей проблемы и будем рады интересным предложениям!
ссылка на оригинал статьи https://habr.com/ru/articles/571936/
Добавить комментарий