Я хочу поделиться с вами историей, как мы строили CI/CD-процессы для ПО, написанного для нестандартной платформы, которую многие считают «динозавром» — IBM System i aka AS/400.


AS/400 используется многими крупными российскими банками, и все они потихоньку движутся в направлении CI/CD. Райффайзенбанк стал одними из первых (если не первым), кто применил эти практики для установки ПО на платформе AS/400 в промышленной эксплуатации.

Почему мы к этому пришли


К автоматизации установок мы шли давно, нас к этому подталкивали разные причины:

  • Длительность установки. Из-за этого продукт долго бывает недоступен для клиентов банка, а на дежурных сотрудников ночной смены ложится дополнительная нагрузка, хотя они и так заняты регламентными работами.
  • Качество установки.При ручном переносе подготовленных к установке объектов может что-то «внезапно» пропасть, или, наоборот, появиться. Бекап изменяемых объектов — полностью на совести дежурных, и они нечаянно могут установить новую версию одного из объектов пакета, не сохранив старую. К чему это приводит, мы все прекрасно знаем.

После нескольких неудачных установок мы решили включать в любую установку на AS/400 специальную программу-установщик. Для каждой конкретной поставки разработчики готовили CL-скрипт. Он проверял полноту поставки, наличие бекапа изменяемых объектов и установку правильной авторизации на объекты, а также сам устанавливал ПО и обрабатывал нештатные ситуации.

Новый подход нравился службе поддержки и бизнесу, потому что стабильность установок улучшилась. Но разработчикам стало труднее, ведь вместо простенькой инструкции вроде «взять объект ххх, переместить в другую среду, положить в yyy, добавить стандартную авторизацию», пришлось писать под каждую установку дополнительную программу.

Некоторые проблемы так и остались нерешенными. Протестированное ПО не всегда соответствовало тому, что ставили в продуктив. Разработчик всегда мог в последний момент что-то поменять в подготовленной программе, руководствуюсь своим видением правильности работы системы. Это могло привести к катастрофам в среде промышленной эксплуатации.

Кроме того, у нас всегда уходило много времени при переходах поставки от стадии к стадии. После написания кода разработчик спрашивал тестировщика: «Куда ставить-то?»; тестировщик через некоторое время отвечал и переводил задачу на разработчика; тот устанавливал и отправлял задачу обратно. Потом начинались «перекидывания мяча» при исправлении найденных дефектов, при подготовке поставки к выходу в бой. В лучшем случае, на каждый такой переход тратилось несколько минут, в худшем — дни.

Службе поддержки было крайне важно понять, по какой-же задаче менялись продуктивные объекты в последний раз, как откатить систему на предыдущую версию, в каких непромышленных средах установлено изменение и в чём оно заключалось.

Новые инструменты AS/400


С возникновением в нашем банке движений CI/CD и DevOps, мы получили новые инструменты и сразу начали их осваивать.

Исходный код переместился в соответствующее хранилище — Git (Bitbucket), собранные поставки — в Artifactory, а процесс сборки, установки и тестирования — в Bamboo.

Если исходные коды RPG/C/CL более-менее гладко легли в хранилище кода, ведь это просто текст, то с оркестратором сборок и установок (Bamboo) пришлось повозиться, потому что стандартных плагинов Bamboo для AS/400 в данный момент не существует.

Мы начали пробовать различные варианты установок. Концепции были абсолютно противоположными, начиная с «давайте всю логику установки и сборки хранить в Bamboo в виде ftp/ssh-скриптов, без какого-либо дополнительного кода», заканчивая, «а давайте сделаем универсальный установщик на AS/400».

В итоге у нас получился процесс, который практически ничем не отличается от процессов CI/CD для любой другой платформы:


Центральное звено процесса — Jira, в ней собирается вся информация о требованиях, документации, коммитах, сборках и установках.


Все требования у нас появляются в виде Jira-задач и попадают в работу к аналитикам, которые выясняют и описывают требования и сценарии использования ПО, после чего задачу вытягивают на себя разработчики.

Разработчики пишут код и публикуют его в Bitbucket. Идентификатор коммита и ссылка на него автоматически появляется в Jira-задаче.
Коммит в Bitbucket автоматически запускает сборку приложения в Bamboo и публикацию собранной поставки в Artifactory.

Когда сборка успешно завершается, она запускает план установки ПО в «песочницу» разработчиков, где они могут проверить то, что у них получилось. Также после успешной установки запускается набор автотестов, информирующий разработчика о качестве новой поставки. Информация о статусе установок сразу же отражается и в Jira-задаче, и в Bitbucket.

Если дефектов нет, то разработчик может приступать к следующей задаче.

Затем в процесс включается тестировщик, который сам решает, куда установить ПО для тестирования, и ставит его нажатием кнопочки.

После окончания тестирования создается «запрос на изменение» для специалистов поддержки, которые валидируют и согласуют изменение. После этого дежурные в нужный момент жмут кнопку для установки в Bamboo.

Кстати, в одной из предыдущих статей мы писали про наше приложение, чувствительное к длительной недоступности и обрабатывающее миллионы запросов в день. Оно выходит в промышленную среду только по описанному выше процессу.

Теперь предлагаю немного погрузится в подробности сборки и установки на AS/400.

Сборка


К сожалению, на *nix- или Windows-машинах нельзя компилировать RPG/CL-программы, поэтому нам пришлось немного усложнить стандартную схему сборки ПО:

Для себя мы сразу выделили «эталонную» среду AS/400, на которой агенты Bamboo делают удаленную компиляцию.

Разработчик, создавая новое ПО, заранее заботится о том, как оно в дальнейшем будет собираться и устанавливаться. Для этого у каждого ПО в Bamboo есть свои Build- и Deploy-скрипты.


После коммита автоматически запускается план сборки приложения в Bamboo, настроенный на конкретный репозиторий.


Исходный код выкачивается и размещается на сборочном агенте, а потом по FTP кладётся во временную сборочную библиотеку на AS/400. Затем по ssh компилируется и вызывается программа-сборщик приложения. Задача сборщика — скомпилировать все программы и установщик, а потом поместить их в один пакет, готовый к развертыванию в любой среде.

Типичный пакет ПО, готовый к установке:


Затем готовый пакет по FTP переносится с AS/400 на сборочный агент.

Тут надо отметить, что изменение программ — только одна часть изменения, а вторая — это скрипты по изменению БД. Они перемещаются из Bitbucket на сборочный агент, и присоединяются как еще один артефакт к уже собранному пакету AS/400-программ.

После окончания сборки артефакты публикуются в Bamboo и Artifactory.

Сборочные планы в Bamboo составлены так, чтобы их можно было применить для любого ПО под AS/400, написанного в банке. Для добавления нового плана нам требуется 15 минут — здесь учтено клонирование любого другого плана и изменение значений некоторых переменных.

Установка


Одно из главных достоинств нашего процесса установки — он повторяем и одинаков для любой среды, будь то среда промышленной эксплуатации или среда разработки. Мы начинаем тестирование установки в продуктив уже на этапе установки в среду разработки.

В общих чертах установка выглядит так:


По триггеру или нажатию кнопки запускается план развёртывания в Bamboo для указанной среды. Первым делом из Artifactory на установочный агент выкачиваются наши артефакты — это Liquibase-скрипты и установочный пакет программ (save-файл).

Затем объекты save-файла по FTP перемещаются и распаковываются во временную библиотеку на AS/400, в среде, куда будут устанавливаться программы. Далее запускается утилита Liquibase, которая с помощью библиотеки jt400 подключается к AS/400 и выполняет скрипт обновления БД, занося соответствующие записи в лог изменений.

Наконец, Bamboo по ssh вызывает программу-установщик, которая бэкапит изменяемые объекты, проверяет содержимое поставки, ставит изменение и корректирует авторизацию.

Результат установки отправляется всем подписанным на рассылку членам команды:


Мы добавили маленькую полезную функцию: у обновленной версии ПО на уровне программ проставляется номер задачи, в рамках которой сделано последнее изменение, и ID комитта в Bitbucket:


Это помогает быстрее найти последнее изменение и посмотреть изменения в коде. В экстренных ситуациях даже служба поддержки может внести небольшие изменения в код и отправить исправление в продуктив, не обладая ценными знаниями о компиляции, сборке и установке ПО.

Сейчас мы проводим около 150 установок в AS/400 среды в день. Мы постоянно улучшаем процесс, он не выбит в камне и не зафиксирован в стандартах и процедурах — он живет и развивается. Разработчики всё больше входят во вкус, у них появляются новые идеи, они предлагают новые улучшения. Поддержка пытается воплотить эти идеи в жизнь, попутно предлагая свои изменения. Эти инструменты и процессы помогают нам не только в поддержке и быстрой поставке ПО в продуктив, но и объединяют нас как DevOps-команду.

Комментарии (9)


  1. 3ARLL
    09.11.2017 07:40

    Это прекрасно. Особенно на фоне того как сама IBM, своим маркетингом, убивает замечательную платформу.


    1. ShashkovS
      09.11.2017 11:50

      Ага. Чего только стоит журналирование во встроенной БД, и вообще все возможные системные логирования. И командная строка — просто огонь.


      1. 3ARLL
        10.11.2017 11:17

        Раньше адоптед авторити не работала только для библиотек сервис програм (ну и не беда), потом яву из ядра выпили, а разработчики начали ее активно юзать, потом еще что-то из под адоптед авторити выпало и такая красивая схема наследования прав в итоге полетела в тартарары ((


  1. G1yyK
    09.11.2017 08:51

    Новый подход нравился службе поддержки и бизнесу
    — потому что все легло на плечи разработчиков, а где же devops?

    Некоторые проблемы так и остались нерешенными. Протестированное ПО не всегда соответствовало тому, что ставили в продуктив. Разработчик всегда мог в последний момент что-то поменять в подготовленной программе, руководствуюсь своим видением правильности работы системы
    — а как насчет ставить протестированные сборки?

    В экстренных ситуациях даже служба поддержки может внести небольшие изменения в код и отправить исправление в продуктив, не обладая ценными знаниями о компиляции, сборке и установке ПО.
    — а как же кровавый ынтэрпрайз! служба поддержки вносит изменения, а эти изменения нигде не отраженны в документации и тп, а потом гадай зачем это сделали и возникают старые проблемы — Протестированное ПО не всегда соответствовало тому, что ставили в продуктив


    1. Rampage Автор
      09.11.2017 09:58

      спасибо за коммент :)

      потому что все легло на плечи разработчиков, а где же devops?

      Давным давно Некоторое время назад цели у поддержки и разработки могли отличаться. Кому-то надо стабильно, а кому-то быстрее в продуктив.
      Но сознание и подходы меняются. Сейчас же работаем с общими целями. Поддержка помогает скорейшему выходу продукта в среду промышленной эксплуатации, а не ставит дополнительные излишние ограничения и усложнения, но и не забывает про качество.
      — а как насчет ставить протестированные сборки?

      Старались, но поставку для «боя», готовил разработчик только после тестирования и под конкретную среду. В этот момент и могли происходить чудесные изменения.

      Но теперь, как я уже писал в статье, сборка проходит все стадии и все среды. Внезапно изменить её после тестирования, практически невозможно.
      Намного проще и быстрее провести её через весь процесс. Это займет от пары минут до пары часов (в зависимости от сложности ПО и кол-ва тестов).
      служба поддержки вносит изменения, а эти изменения нигде не отраженны в документации и тп

      Мелкими изменения от поддержки, это чаще всего «хот-фиксы», если разработчик в данный момент недоступен. Изменения отражаются и в хранилище кода с соответствующими комментариями, и в Jira и в artifactory и т.д. Это скорее некоторое исключение из процесса, про которое всегда узнают и аналитики и разработчики.


  1. ShashkovS
    09.11.2017 11:45

    Мы вместо CL для установщиков в одном крупном банке использовали REXX — интерпретируемый встроенный язык. Сделали для себя стандартный почти всемогущий шаблон инсталлятора — и стало весьма хорошо.
    То есть админам оставалось взять подписанный savf, отресторить его и запустить REXX. Ну, кроме совсем уж сложных случаев.

    В другом крупном банке для сборки и деплоя частично прикрутили gradle при помощи кучи java и открытого toolbox'а. Но по моим ощущениям для разработчиков это не зверски удобно. Из того, что я видел, наша подготовка инсталлятора была проще подготовки скрипта для gradle. Но не знаю, сам не пробовал.


    1. Rampage Автор
      09.11.2017 19:55

      Да, gradle java и jt400 видели на imbi meetup в этом году. Довольно интересная идея, но однозначно поднимает порог вхождения для разработчиков.


    1. 3ARLL
      10.11.2017 11:24

      Я хотел написать инсталлятор на CL, но потом отошел от установки обновлений и как-то остыл.
      А вообще у мне для своих нужд очень много на CL и даже с вызовами системного API. Слава богу возможностей CL вполне хватает разобрать бинарные результаты и юзер спейсы. А когда IBM штатно добавил вызов SQL прямо из командной строки, так вообще открылся простор для скриптования.


      1. Rampage Автор
        10.11.2017 12:59

        Кстати, мы добавляем значения в User Defined Information с помощью вызова API (QLICOBJD) из CL сборщика.

        Если говорить про возможность вызова системного API, то IBM тут конечно очень сильно выступил и облегчил нам жизнь. У нас в Ops написано много вспомогательных тулов на SQL (функций и хранимок) с вызовами различных системных «апишек».