Наша рэалізацыя Continuous Deployment на платформу заказчыка

Мы ў True Engineering наладзілі працэс бесперапыннай дастаўкі абнаўленняў на серверы замоўца і жадаем падзяліцца гэтым досведам.

Для пачатку мы распрацавалі анлайн сістэму для заказчыка і разгарнулі яе ва ўласным кластары Kubernetes. Цяпер наша высоканагружанае рашэнне пераехала на платформу замоўца, для чаго мы наладзілі цалкам аўтаматычны працэс Continuous Deployment. Дзякуючы гэтаму, мы паскорылі time-to-market - дастаўку змен у прадуктовае асяроддзе.

У гэтым артыкуле мы раскажам пра ўсе этапы працэсу Continuous Deployment (CD) або дастаўкі абнаўленняў на платформу заказчыка:

  1. як стартуе гэты працэс,
  2. сінхранізацыя з Git-рэпазітаром заказчыка,
  3. зборка бэкенда і фронтэнда,
  4. аўтаматычнае разгортванне прыкладання ў тэставым асяроддзі,
  5. аўтаматычнае разгортванне на Prod.

У працэсе падзелімся дэталямі наладкі.

Наша рэалізацыя Continuous Deployment на платформу заказчыка

1. Старт CD

Continuous Deployment пачынаецца з таго, што распрацоўшчык выкладвае змены ў рэлізную галінку нашага Git-рэпазітара.

Наша прыкладанне працуе на базе мікрасэрвіснай архітэктуры і ўсе яго кампаненты захоўваюцца ў адным рэпазітары. Дзякуючы гэтаму збіраюцца і ўсталёўваюцца ўсе мікрасэрвісы, нават калі змяніўся адзін з іх.

Мы арганізавалі працу праз адзін рэпазітар па некалькіх прычынах:

  • Выгода распрацоўкі - дадатак актыўна развіваецца, таму можна працаваць адразу з усім кодам.
  • Адзіны пайплайн CI/CD, які гарантуе, што дадатак як адзіная сістэма праходзіць усе тэсты і дастаўляецца ў prod-асяроддзе замоўца.
  • Выключаем блытаніну ў версіях - нам не даводзіцца захоўваць карту версій мікрасэрвісаў і апісваць для кожнага мікрасэрвісу сваю канфігурацыю ў скрыптах Helm.

2. Сінхранізацыя з Git-рэпазітаром зыходнага кода заказчыка

Зробленыя змены аўтаматычна сінхранізуюцца з Git-рэпазітаром заказчыка. Там настроена зборка прыкладання, якая запускаецца пасля абнаўлення галінкі, і дэплаймент у прад. Абодва працэсу адбываюцца ў іх асяроддзі з Git-рэпазітара.

Мы не можам працаваць з рэпазітаром заказчыка напрамую, паколькі нам патрэбны ўласныя асяроддзі для распрацоўкі і тэсціравання. Мы выкарыстоўваем для гэтых мэт свой Git-рэпазітар — ён сінхранізаваны з іх Git-рэпазітаром. Як толькі распрацоўшчык выкладвае змены ў адпаведную галінку нашага рэпазітара, GitLab адразу ж адпраўляе гэтыя змены заказчыку.

Наша рэалізацыя Continuous Deployment на платформу заказчыка

Пасля гэтага трэба зрабіць зборку. Яна складаецца з некалькіх этапаў: зборкі бэкенда і фронтэнда, тэсціравання і дастаўкі ў прад.

3. Зборка бэкенда і франтэнда

Зборка бэкенда і фронтэнда - гэта дзве паралельныя задачы, якія выконваюцца ў сістэме GitLab Runner. Яе канфігурацыя зыходнай зборкі ляжыць у гэтым жа рэпазітары.

Тутарыял для напісання YAML-скрыпта для зборкі ў GitLab.

GitLab Runner забірае код з патрэбнага рэпазітара, камандай зборкі Java-прыкладанні сабрае і адпраўляе яго ў Docker registry. Тут мы збіраем бэкенд і фронтэнд, атрымліваем Docker-вобразы, якія складаем у рэпазітар на баку заказчыка. Для кіравання Doker-вобразамі выкарыстоўваем убудова Gradle.

Мы сінхранізуем версіі нашых вобразаў з версіяй рэлізу, які будзе выкладзены ў Docker. Для гладкай працы мы ўнеслі некалькі налад:

1. Паміж тэставым асяроддзем і прадуктовым кантэйнеры не перазбіраюцца. Мы зрабілі параметрызацыі, каб адзін і той жа кантэйнер мог без перазборкі працаваць са ўсімі наладамі, зменнымі асяроддзямі і сэрвісамі як у тэставым асяроддзі, так і на продзе.

2. Для абнаўлення прыкладання праз Helm неабходна пазначыць яго версію. У нас зборка бэкенда, франтэнда і абнаўленне прыкладання – гэта тры розныя задачы, таму важна выкарыстоўваць усюды адну і тую ж версію прыкладання. Для гэтай задачы мы выкарыстоўваем дадзеныя з гісторыі Git, паколькі ў нас канфігурацыя K8S кластара і прыкладанні знаходзяцца ў адным Git-рэпазітары.

Версію прыкладання мы атрымліваем з вынікаў выканання каманды
git describe --tags --abbrev=7.

4. Аўтаматычнае разгортванне ўсіх змен у тэставым асяроддзі (UAT)

Наступным этапам у гэтым скрыпце зборкі выконваецца аўтаматычнае абнаўленне кластара K8S. Гэта адбываецца пры ўмове, што ўсё прыкладанне сабралася і ўсе артэфакты апублікаваны ў Docker Registry. Пасля гэтага запускаецца абнаўленне тэставага асяроддзя.

Абнаўленне кластара запускаецца з дапамогай Helm Update. Калі ў выніку нешта пайшло не па плане, то Helm аўтаматычна і самастойна адкоціць усе свае змены. Яго працу не трэба кантраляваць.

Мы пастаўляем разам са зборкай канфігурацыю кластара K8S. Таму наступным крокам абнаўляецца яна: configMaps, deployments, services, secrets і любыя іншыя канфігурацыі K8S, якія мы змянілі.

Пасля гэтага Helm запускае RollOut абнаўленне самога прыкладання ў тэставым асяроддзі. Да таго як прыкладанне будзе разгорнута на продзе. Гэта зроблена для таго, каб карыстачы ўручную праверылі бізнэс-фічы, якія мы выклалі ў тэставае асяроддзе.

5. Аўтаматычнае разгортванне ўсіх змен на Prod

Каб разгарнуць абнаўленне ў прадуктовае асяроддзе, застаецца толькі націснуць адну кнопку ў GitLab - і кантэйнеры адразу дастаўляюцца ў прадуктовае асяроддзе.

Адно і тое ж прыкладанне можа без перазборкі працаваць у розных асяродках - тэставым і продзе. Мы выкарыстоўваем адны і тыя ж артэфакты, не мяняючы нічога ў дадатку, а параметры задаём звонку.

Гнуткая параметрызацыя налад прыкладання залежыць ад таго асяроддзя, у якім гэта дадатак будзе выконвацца. Мы вынеслі ўсе налады акружэнняў па-за: усё параметрызуецца праз канфігурацыю K8S і параметры Helm. Калі Helm разгортвае зборку ў тэставае асяроддзе, да яе ўжываюцца тэставыя параметры, а прадуктовым асяроддзі - прадуктовыя параметры.

Самым складаным было параметрызаваць усе выкарыстоўваныя сэрвісы і зменныя, якія залежаць ад асяроддзя, і перавесці іх у зменныя асяроддзі і апісанне-канфігурацыі параметраў асяроддзя для Helm.

У параметрах прыкладання выкарыстоўваюцца зменныя асяроддзі. Іх значэння задаюцца ў кантэйнерах пры дапамозе K8S configmap, які шаналізуецца пры дапамозе Go-шаблонаў. Напрыклад, заданне зменнай акружэння на званне дамена можна зрабіць так:

APP_EXTERNAL_DOMAIN: {{ (pluck .Values.global.env .Values.app.properties.app_external_domain | first) }}

.Values.global.env - у гэтай зменнай захоўваецца назва асяроддзя (prod, stage, UAT).
.Values.app.properties.app_external_domain – у гэтай зменнай мы ў файле .Values.yaml задаем патрэбны дамен

Пры абнаўленні прыкладання Helm выконвае стварэнне са шаблонаў файла configmap.yaml і запаўняе значэнне APP_EXTERNAL_DOMAIN патрэбным значэннем у залежнасці ад асяроддзя, у якім стартуе абнаўленне прыкладання. Гэтая зменная прастаўляецца ўжо ў кантэйнеры. Доступ да яе ёсць з прыкладання, адпаведна, у кожным асяроддзі прыкладання будзе рознае значэнне гэтай зменнай.

Адносна нядаўна ў Spring Cloud з'явілася падтрымка K8S, у тым ліку праца з configMaps: Spring Cloud Kubernetes. Пакуль праект актыўна развіваецца і змяняецца кардынальна, мы не можам выкарыстоўваць яго ў продзе. Але актыўна маніторым яго стан і выкарыстоўваем яго ў DEV канфігурацыях. Як толькі ён стабілізуецца - будзем перамыкацца з выкарыстання зменных асяроддзі на яго.

Разам

Такім чынам, Continuous Deployment наладжаны і працуе. Усе абнаўленні адбываюцца па адным націску клавішы. Дастаўка змен у прадуктовае асяроддзе - аўтаматычная. І, што важна, абнаўленні не спыняюць працы сістэмы.

Наша рэалізацыя Continuous Deployment на платформу заказчыка

Планы на будучыню: аўтаматычная міграцыя базы

Мы задумаліся аб аб апгрэйдзе базы і магчымасці гэтыя змены адкаціць. Бо адначасова працуюць дзве розныя версіі прыкладання: старая працуе, а новая паднімаецца. І старую мы выключым толькі калі пераканаемся, што новая версія - працуе. Міграцыя базы павінна дазваляць працаваць з абедзвюма версіямі прыкладання.

Таму мы не можам проста так змяніць назву калонкі ці іншыя дадзеныя. Але мы можам стварыць новую калонку, скапіяваць у яе дадзеныя са старой калонкі і напісаць трыгеры, якія будуць пры абнаўленні дадзеных будуць адначасова капіяваць і абнаўляць іх у іншай калонцы. І пасля паспяховага дэплою новай версіі прыкладання, па сканчэнні перыяду post launch support, мы зможам выдаліць старую калонку і які стаў непатрэбным трыгер.

Калі новая версія прыкладання працуе некарэктна, мы можам адкаціцца да ранейшай версіі, у тым ліку і ранейшай версіі базы. Словам, нашы змены дазволяць працаваць адначасова з некалькімі версіямі дадатку.

Мы плануем зрабіць аўтаматызацыю міграцыі базы праз K8S job, убудаваўшы яе ў працэс CD. І абавязкова падзелімся гэтым досведам на Хабры.

Крыніца: habr.com

Дадаць каментар