Привет.
Расскажу, как мы решили проблему с переносом релизов из Test в Prod в Qlik Sense. Сначала немного истории. Выбор архитектуры с изолированными средами Test и Prod для нас был обусловлен следующими преимуществами:
-
Производственная среда высокой степени готовности, надежности за счет исключения влияния разработки, ситуации с нештатными и штатными перезагрузками системы и сервисов минимизированы. Все пользователи имеют одинаковый профиль нагрузки, использования (load pattern, usage pattern), линейная зависимость утилизации ресурсов от количества пользователей, управляемая модель планирования роста производительности и масштабирования системы. Все пользователи, аналитики и разработчики имеют права «только чтение», вероятность ошибочных изменений объектов в системе исключена. В Prod обеспечивается подключение к источникам данных только продуктивного контура в соответствии с правилами информационной безопасности.
-
Среда разработки и тестирования Test, в силу решаемых задач, предусматривает менее строгие требования к доступности и надежности системы. Таким образом, не создают неудобства для основного бизнеса и допускаются ошибки при разработке, приводящие к неработоспособности системы, узлов, сервисов или деградации производительности, например, в силу разной квалификации разработчиков. Для команд внутренней разработки Компании и подрядных организаций обеспечивается возможность изолирования проектов и ресурсов на уровне групп ActiveDirectory и сетевого доступа. В Test источниками данных для Qlik являются, соответственно, КХД и другие АС в тестовом контуре. Это позволяет командам разработчиков QS и БД вести совместные разработку в соответствии с правилами сетевой связанности и информационной безопасности. Также могут решаться задачи обучения разработчиков и аналитиков на временных площадках SandBox и SelfSense.
При весомых преимуществах данной архитектуры есть один «маленький» недостаток – придется поднимать не один, а N кластеров, плюс интеграция, транспорт между средами и настройка кластеров под особенности каждой среды. Таким образом, объем работ по сопровождению увеличивается, грубо в N раз + N/2 на транспорт между кластерами + N раз на интеграцию с инфраструктурными системами. Из них какие-то задачи разовые, другие придется выполнять постоянно в процессе эксплуатации.
Чтобы понимать проблематику, рассмотрим более детально окружение и назначение Qlik Sense в Компании. На платформе Qlik развернуты 4 кластера, Test, Prod, SandBox и SelfSense. Test используется для разработки, тестирования и приемки. Если быть точным, его основное назначение разработка, название Test пришло из тендерной документации на закупку оборудования), да так и осталось. Prod, собственно, предназначен только для работы пользователей. SandBox используется для RnD, тестирования QS updates, интеграций, нагрузочных тестов. SelfSense, это выделенный кластер для self-service. В силу правил информационной безопасности в Компании между Test и Prod отсутствуют сетевое проходы, также для разработчиков закрыт файловый доступ на ноды. То есть, ни файловый, никакой другой трафик напрямую между Test и Prod невозможен.
Частота выхода релизов после внедрения в среднем была 1 в 2-3 дня, сейчас увеличилась, в среднем 1 каждый день и в пике 2-4 в день. В общем, получается для поддержки процессов разработки и сопровождения Qlik было два решения, либо нужна команда неутомимых, отказоустойчивых админов, либо идем в DevOps и автоматизируем все, что можно.
Автоматизация — это дело такое, только начни, потом уже трудно остановиться! Очевидно, кандидатом номер один стал процесс транспорта и деплоя артефактов разработки в Qlik между средами Test и Prod. В Devops нам сказали, это называется непрерывная поставка (CD, continues delivery). Из CI взяли немного, в силу специфики разработки в Qlik. Как мы это делали, пропущу и далее расскажу, как работает сейчас непрерывная поставка релизов Qlik в Компании. Формат изложения постараюсь воспроизвести, как roadmap процесса выполнения от начала до конца.
По требованиям и компетенциям
Кратко перечислю компетенции и опыт, необходимые для разработки скриптов и настройки окружения: разработка в Qlik особенно скриптов загрузки, администрирование Qlik, использование QRS API, Qlik Web Connector, PowerShell, CMD, протоколы REST, HTTPS, базовые знания инструментов DevOps — TeamCity(Jenkins), Nexus, Git.
Непосредственно в процессе развертывания участвуют два человека, разработчик QS и админ QS. Задача первого подготовить сценарий обновления с описанием того, что должно войти в поставку. Сценарий формируется на основе шаблона в формате Excel с описанием операций и действий, которые необходимо выполнить на Prod. Задача второго, используя подготовленный сценарий, выполнить сборку пакета обновления в Test и задеплоить пакет в Prod.
Роли разработчика и админа достаточно условны, это могут быть два разработчика. Единственное условие, у второго должна быть роль RootAdmin и удаленный доступ к ЦН кластера, чтобы при деплое мог вручную исправить ошибки сценария или другие коллизии непосредственно в QMC или на ЦН.
Подготовка и сборка пакета обновления
Что может входить в поставку пакета обновления? В нашем случае это архив артефактов и сценарий обновления с описанием действий, которые необходимо выполнить в процессе развертывания на Prod. Исходя из набора артефактов и действий, в основном будет понятно, какие возможности заложены в процесс непрерывной поставки, поэтому опишу достаточно подробно.
Типы артефактов:
-
Приложения в формате QVF. Действия при деплое — NEW, UPDATE, DELETE, RENAME, MOVE, REPLACE.
-
Content library, новые или измененные файлы допустимых форматов. Действия при деплое — NEW, UPDATE.
-
Extensions, themes в формате zip. Действия при деплое — NEW, UPDATE.
-
Tasks в виде таблицы, где описаны все необходимые параметры и цепочки заданий. Действия при деплое — NEW, UPDATE, DELETE.
-
Файлы скриптов QVS, данных QVD и другие. Действия при деплое — NEW, UPDATE, DELETE.
-
Список tasks, которые необходимо запустить после развертывания.
-
Сценарий обновления в формате XLS. Включает номер релиза, версию сборки, IP источника и целевого хоста, список артефактов и действий с ними и другие.
Концептуальный вопрос, как происходит идентификация(mapping) приложений, заданий и других объектов в сценарии и целевой системе. Приложения идентифицируются по полям Название + Поток, таски по Названию + Приложение + Поток, библиотеки и файлы контента по Названию, расширения по Названию, файлы произвольного формата — путь и имя файла. Как оказалось, использование в сценарии ID объектов для этой цели не дает никаких плюсов. Все‑таки, человеку намного проще работать с названиями, чем с ID объектов. По ключевым полям можно точно идентифицировать объекты в целевой системе, а после идентификации операции уже выполняются с идентификаторами.
Сценарий обновления подготовлен, переходим к непосредственно сборке BuildExportPackage в TeamCity на Test. В параметрах сборки необходимо указать номер релиза и запустить выполнение. В консоли лог выполнения на верхнем уровне выглядит таким образом:
... Establishing SSH Tunnels Step 1/3: Run ExportDeployPackage (PowerShell) (5m:33s) Step 2/3: PushPackage2NexusCD (Command Line) (21s) Step 3/3: PushVersion2Git (Command Line) (2s) Terminating SSH Tunnels ...
На каждом шаге можно провалиться до детальных сообщений о ходе выполнения сценария. Детальные сообщения формируются в скриптах и передаются в стандартный поток вывода stdout.
Сборка или билд BuildExportPackage включает шаги:
-
Сбор артефактов реализован в скрипте ExportDeployPackage.ps1. При этом выполняется ряд проверок — соответствие IP сервера в сценарии и подключении, каталоги файлов проходят проверку на соответствие перечню допустимых, входящих только в SharedFolders.
-
На шаге PushPackage2NexusCD сформированный zip архив с артефактами сохраняется в Nexus и устанавливается tag для его идентификации в репозитории.
-
Номер релиза является ключом для процесса Deployment на целевом хосте. Номер релиза передается двумя путями для перекрестной проверки на Prod — в файле сценария и в Git. На шаге PushVersion2Git выполняется сохранение номера релиза в Git.
Для контроля процесса сборки в реальном времени в консоли TeamCity(далее TC) на шаге ExportDeployPackage необходимо выполнить подключение к удаленному хосту через сервис WinRM (WS‑Management protocol). Дело в том, что другие типы подключений: ansible, выполнение ExportDeployPackage.ps1 на агенте TC не позволяют отображать вывод команд PS в консоль TeamCity в реальном времени, так как все сообщения в консоли отображаются только после завершения скрипта PS. Подробнее подключение WinRM описано в конце статьи.
Сборка пакета с точки зрения логики процесса достаточно проста, нет всевозможных проверок на ошибки сценария и системы, анализа соответствия объектов в Test и Prod и т. д. Выполняется только экспорт артефактов и ключевых полей для их идентификации в целевой системе.
После выполнения сборки получаем следующие результаты:
-
Артефакты подготовлены и сохранены в хранилище Nexus,
-
В Git сохранен номер текущей версии релиза.
Следующий этап непосредственно развертывание пакета обновления в целевой системе.
Деплой пакета обновления в целевой системе
Основная задача по развертыванию релиза выполняется в скрипте QS. В процессе импорта объектов‑артефактов сразу происходит изменение целевых объектов в системе, то есть точка отката не существует и не сохраняется в виде какого‑то состояния системы. Развертывание может выполняться несколько раз, например, повторный запуск после исправления ошибок, поэтому какие‑то объекты могут быть уже обновлены или созданы на предыдущих запусках. Таким образом, перед каждым этапом изменений необходимо выполнить массу проверок на ошибки (список не полный) и убедиться:
-
Объект существует в системе,
-
Приложение для задания существует или будет создано,
-
Предшествующее в цепочке задание существует или будет создано,
-
Приложение для предшествующего в цепочке задания существует или будет создано,
-
Какие объекты уже обновлены, созданы, удалены на предыдущих запусках,
-
Наличие дублей объектов по ключевым полям,
-
Приложение уже существует в потоке при RENAME и MOVE,
-
Неверно указано или пустое ключевое поле для идентификации,
-
Некорректные параметры для заданий
Есть ряд операций при импорте объектов в целевую систему, которые не могут быть реализованы в скрипте QS. Например, методы PUT и POST, где в BODY передается содержимое бинарного файла, не работают в стандартном REST коннекторе. Такие операции лучше реализовать в скрипте PowerShell. К ним относятся upload extensions и content library.
Таким образом, первая часть задачи, где выполняются публикация приложений, tasks и выполнения tasks, реализовано в среде Qlik в скрипте загрузки. Вторая часть для публикации extensions, themes и content library выполняется в среде PowerShell. И хорошо, что не наоборот! Как было написано выше, самая сложная логика именно при публикации приложений и tasks. Примерный список Sub функций, команд, которые реализованы для деплоя объектов в скриптах QS и PowerShell, описан в конце статьи.
Непосредственно процесс развертывания выполняется в сборке DeployPackage в TeamCity на Prod. В консоли лог выполнения на верхнем уровне выглядит следующим образом:
... Establishing SSH Tunnels Step 1/3: Staging (Command Line) (27s) Step 2/3: CopyArtifact2TargetHost (Command Line) (4m:46s) Step 3/3: Deploy package (PowerShell) (29m:09s) Terminating SSH Tunnels ...
Сборка DeployPackage включает шаги:
-
Staging. Выполняется staging архива артефактов в репозитории Nexus из области qlk‑raw‑test в qlk‑raw‑prod.
-
CopyArtifact2TargetHost. Скачивание файла архива и копирование на целевой хост.
-
Deploy package. Выполняется извлечение из архива и публикация объектов в системе. Включает следующие этапы:
— Проверки на соответствие IP сервера в сценарии и подключении, совпадение версии релиза в сценарии и в Git, первый запуск или повторный, каталоги файлов соответствуют перечню допустимых.
— Копирование, удаление файлов.
— Публикация extensions, themes и contentLibrary.
— Запуск задания DeployAppsTasks в среде QS, где выполняется публикация приложения и заданий, выполнение заданий по сценарию.
После завершения сборки получаем следующие результаты: приложения, задания, библиотеки и расширения опубликованы, файлы скриптов и другие файлы скопированы, приложения и задания из сценария обновлены.
Для контроля процесса сборки в реальном времени в консоли TeamCity также применяется подключение через сервис WinRM. Для контроля выполнения сценария в QS информация выводится сначала в текстовый файл, затем в скрипте PS передается в поток stdout и далее выводится в консоль. Статусы выполнения tasks также передаются в консоль. Таким образом, вся информация о ходе выполнения сценария, в том числе и ошибки, отображается в реальном времени в консоли TeamCity.
В случае возникновения ошибок на всех этапах выводится подробная информация, где произошла ошибка, по какой причине и рекомендации по устранению. В этом случае администратор QS может оперативно устранить ошибку и запустить сборку повторно. Стоит заметить, что на первоначальном этапе внедрения и освоения процесса поставки ошибок, в том числе в сценарии, было достаточно много. Поэтому более чем оправдан был выбранный подход с множеством проверок на ошибки непосредственно перед внесением изменений в систему.
Для полного завершения поставки необходимо выполнить еще несколько важных шагов. После выполнения сборки происходит автоматическая рассылка информация по эл.почте на конкретных специалистов, которые должны протестировать приложения на работоспособность в Prod среде, часть приложений проходит приемочное тестирование. После завершения тестирования и приемки также выполняется автоматическая рассылка по эл. почте. На этом процесс поставки завершается.
С начала внедрения поставки релизов в DevOps прошло около 5 лет. За это время вышло 10 только мажорных версий программного кода, выпущено около 800 релизов. Кардинально изменялся сам процесс поставки, например, было разделение процесса деплоя на два этапа, сначала тестинг приложений по типу UAT, затем публикация в целевые потоки. При интенсивной разработке и частых релизах такой способ оказался не эффективным и нашли более оптимальное решение.
В перспективе есть планы дальнейшей оптимизация, включая «более» непрерывную поставку релизов. Идея в том, чтобы за один заход выполнить в Test все необходимые проверки с учетом текущего состояния объектов на Prod, собрать пакет релиза c артефактами и корректным без ошибок сценарием и задеплоить его на Prod. В этом случае один человек может подготовить релиз от нескольких разработчиков или команд и поставить его на Prod без участия админа.
На этом автоматизация не заканчивается, сделано уже достаточно много всего и в среде DevOps, и в Qlik Sense. Из интересных решений, это интеграция с Системой Поддержки пользователей для заявок на предоставление доступа в QS, совместная разработка QS в BitBucket, установка обнов QS и кастомных настроек, обратный прокси с балансировкой на информационную страницу‑заглушку в случае недоступности, отказа QS.
Подключение к удаленному хосту через сервис WinRM
Подключение к удаленному хосту через сервис WinRM выполняется на windows агенте TeamCity. Такое же подключение можно настроить на linux агенте.

Подробнее, как настроить подключение, можно посмотреть по ссылкам.
-
Выполнить настройку сервиса WinRM на удаленном хосте вручную https://docs.ansible.com/ansible/latest/os_guide/windows_winrm.html или PS скриптом https://github.com/ansible/ansible/blob/stable-2.12/examples/scripts/ConfigureRemotingForAnsible.ps1
-
Заменить self‑signed сертификат, созданный в ConfigureRemotingForAnsible.ps1, на CA сертификат. Скопировать thumbprint из CA сертификата, удалить пробелы, непечатаемые символы в начале и конце строки, вставить вместо XX:
winrm set winrm/config/Listener?Address=*+Transport=HTTPS '@{CertificateThumbprint="XX"}'
, также см. ссылку https://stackoverflow.com/questions/73 367 298/how‑to‑use‑powershell‑to‑update‑the‑https‑cert‑used‑by‑winrm -
Параметры и примеры подключений
https://ss64.com/nt/winrs.html
https://learn.microsoft.com/en‑us/windows‑server/administration/windows‑commands/winrs
Список реализованных Sub функций
По названию и параметрам можно примерно определить, для чего используется функция.
Sub GetSessionID (/*out*/ pCookies)
Sub Encode (vEncodeMe, /*out*/ pEncoded)
Sub GetImportFolder (/*out*/ pFolder)
Sub ImportApp (vAppFile, vAppName, /*out*/ pAppGUID, /*out*/ pModifiedDate)
Sub PublishApp (vAppGUID, vAppName, vAppStreamGUID)
Sub ReplaceApp (vAppGUID, vAppReplacedGUID, /*out*/ pModifiedDate, /*out*/pName)
Sub RenameApp (vAppReplacedGUID, vAppName, /*out*/ pModifiedDate)
Sub ChangeOwnerApp (vtmpGUIDimp, vAppOwnerGIID, /*out*/ pModifiedDate)
Sub ReloadApp (vAppGUID)
Sub DeleteApp (vAppGUID)
Sub MoveApp (vAppGUID, vAppStreamGUID, /*out*/ pModifiedDate)
Sub GetAppModifiedDate (vApp.GUID, /*out*/pModifiedDate, /*out*/pcurrName)
Sub GetSameAppInSream (vAppName, vStreamName, /*out*/ pOut)
Sub ActualAppStreamTable
Sub GetGUIDStream (vStreamName, /*out*/ pGUIDStream)
Sub GetGUIDTag (vNameTag, /*out*/ GUIDTag)
Sub GetAppAppGUID (vTaskApp, vTaskAppStream, /*out*/ pTaskAppGUIDout)
Sub GetAppTaskGUID (vAppGUID, /*out*/ pTaskGUIDout, /*out*/ pTaskNameout)
Sub GetGUIDTask (vTaskName, /*out*/ pTaskGUID, /*out*/ pModifiedDateout, /*out*/ pTagGUID)
Sub CreateTaskSched (vTaskName, vTaskTriggerTime, vTaskTriggerEnd, vTaskSchedule, vTaskExecution, vAppGUID, vTaskCondition0, vTag)
Sub CreateTaskEvent (vTaskName, vTaskExecution, vTaskTimeConstraint, vPrevTaskStatus, vAppGUID, vTag)
Sub CreateTask (vTaskName, vAppGUID, /*out*/ poutTaskGIUD)
Sub UpdateTaskSched (vTaskGUID, vTaskName, vTaskTriggerTime, vTaskTriggerEnd, vTaskSchedule, vTaskExecution, vAppGUID, /*in,out*/ pModifiedDate, vTaskCondition0,vTag)
Sub UpdateTaskEvent (vTaskGUID, vTaskName, vTaskExecution, vTaskTimeConstraint, vPrevTaskStatus, vAppGUID, /*in,out*/ pModifiedDate, vTag)
Sub DeleteTask (vTaskGUID)
Sub GetSchemaEventDelete (vTaskGUID, vArrGUID)
Sub GetCompositEventDelete (vTaskGUID, vArrGUID)
Sub SetTriggersEnable (vGUID, /*in,out*/ pmodifiedDT, vTypeEvent, vEnable)
Sub GetStatusTasksTable (v_step, vStartTime)
Sub PushMessageBuild (vMessage)
Sub Save4FirstLoad
Sub GetStatusTableAfterFaileLoad
Sub SetSuccess (vClass, vHash)
Sub CheckFirstRun (vIsFirstRun)
Sub CheckApps
Sub CheckRunTasks
Sub CheckTasks
Sub PublishApps
Sub GetPrevTaskStatusTbl (/*out*/ pPrevTaskStatus, /*out*/pBreak)
Sub UserTriggersDisable
Sub CheckStatus (vStep, pAll, pInCheckList, pStarted, pEnded, pMis, pFail, pNoStatus, pQueued, pTriggered)
Sub ReloadRunTasks (/*out*/ pResult)
Sub TriggersEnabled
Для PowerShell реализованы следующие команды:
function Pull-Message
{
param (
[string]$DirMessage, # Каталог для сообщений из тасков
[ref]$inum_mess, #Нумерация шагов
[int] $iTimer
)
}
function Run-AppTask
{
param (
[string]$FQDNHost,
[string]$AppName,
[string]$UserName,
$Cert
)
}
function Show-ResultTask
{
param (
[object]$Result
)
}
function Publish-Ext
{
param (
[string]$FQDNHost,
[string]$PathFile,
[string]$UserName,
$Cert
)
}
function Publish-Libs
{
param (
[string]$FQDNHost,
[string]$PathFile,
[string]$UserName,
[string]$LibName,
$Cert
)
}
ссылка на оригинал статьи https://habr.com/ru/articles/895668/
Добавить комментарий