Гісторыя выкаткі, якая закранала ўсё

Гісторыя выкаткі, якая закранала ўсё
Enemies of Reality by 12f-2

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

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

Перадгісторыя + што ж гэта за такая функцыянальнасць

Мы будуем хмарную платформу Mail.ru Cloud Solutions (MCS), дзе я працую тэхнічным дырэктарам. І вось - прыйшоў час прымайстраваць да нашай платформе IAM (Identity and Access Management), які забяспечвае адзінае кіраванне ўсімі карыстацкімі акаўнтамі, карыстальнікамі, паролямі, ролямі, сэрвісамі і іншым. Навошта ён патрэбен у воблаку - пытанне відавочнае: у ім захоўваецца ўся карыстацкая інфармацыя.

Звычайна такія рэчы пачынаюць будаваць на этапе самых стартаў любых праектаў. Але ў MCS гістарычна склалася крыху па-іншаму. MCS будаваўся дзвюма часткамі:

  • Openstack з уласным модулем аўтарызацыі Keystone,
  • Hotbox (S3-сховішча) на базе праекта Воблака Mail.ru,

вакол якіх потым з'явіліся новыя сэрвісы.

Па сутнасці, гэта было два розныя тыпы аўтарызацыі. Плюс мы выкарыстоўвалі некаторыя асобныя распрацоўкі Mail.ru, напрыклад – агульнае сховішча пароляў Mail.ru, а таксама самапісны openid-канектар, дзякуючы якому забяспечвалася SSO (скразная аўтарызацыя) у панэлі Horizon віртуальных машын (натыўны UI OpenStack).

Зрабіць IAM для нас значыла спалучыць гэта ўсё ў адзіную сістэму, цалкам сваю. Пры гэтым не страціць ніякага функцыяналу па дарозе, стварыць задзел на будучыню, які дазволіць нам празрыста яго дапрацоўваць без рэфактарынгу, маштабаваць па функцыянальнасці. Таксама на старце ў карыстальнікаў з'явілася ролевая мадэль доступу да сэрвісаў (цэнтральны RBAC, role-based access control) і некаторыя іншыя дробязі.

Задача аказалася нетрывіяльнай: python і perl, некалькі бэкендаў, незалежна напісаныя сэрвісы, некалькі каманд распрацоўкі і адмінаў. І галоўнае - тысячы жывых карыстальнікаў на баявой прадакшэн-сістэме. Усё гэта трэба было напісаць і, галоўнае, - выкаціць без ахвяр.

Што мы сабраліся выкаціць

Калі вельмі груба, недзе за 4 месяцы мы падрыхтавалі такое:

  • Зрабілі некалькі новых дэманаў, якія агрэгавалі функцыі, якія раней працавалі ў розных кутках інфраструктуры. Астатнім сэрвісам прапісалі новы бэкенд у выглядзе гэтых дэманаў.
  • Напісалі сваё цэнтральнае сховішча пароляў і ключоў, даступнае для ўсіх нашых сэрвісаў, якое можна вольна мадыфікаваць, як нам трэба.
  • Напісалі з нуля 4 новых бэкенда для Keystone (карыстальнікі, праекты, ролі, role assignments), якія, у сутнасці, замянілі яго базу, і зараз выступае адзіным сховішчам нашых карыстацкіх пароляў.
  • Навучылі ўсе нашы сэрвісы Openstack хадзіць за сваімі палітыкамі ў іншы сэрвіс палітык замест таго, каб чытаць гэтыя палітыкі лакальна з кожнага сервера (так-так, па-змаўчанні Openstack так і працуе!)

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

Як выкочваць такія змены і не аблажацца? Спачатку мы вырашылі крыху зазірнуць у будучыню.

Стратэгія выкаткі

  • Можна было б зрабіць выкатку ў некалькі этапаў, але гэта павялічыла б тэрмін распрацоўкі разы ў тры. Акрамя таго, на нейкі час у нас была б поўная рассінхранізацыя дадзеных у базах. Прыйшлося б пісаць свае прылады сінхранізацыі і доўга жыць з некалькімі сховішчамі дадзеных. А гэта стварае самыя розныя рызыкі.
  • Усё, што маглі падрыхтаваць празрыста для карыстальніка, зрабілі загадзя. На гэта спатрэбілася 2 месяцы.
  • Мы дазволілі сабе даунтайм на працягу некалькіх гадзін - толькі на аперацыі карыстальнікаў па стварэнні і змене рэсурсаў.
  • Для працы ўсіх ужо створаных рэсурсаў даунтайм быў недапушчальны. Мы запланавалі, што пры выкаце рэсурсы павінны працаваць без даунтайма і афекту для кліентаў.
  • Каб знізіць уплыў на нашых заказчыкаў, калі нешта пойдзе не так, мы вырашылі выкочвацца ўвечары ў нядзелю. Уначы менш замоўцаў займаецца кіраваннем віртуальнымі машынамі.
  • Усіх нашых кліентаў мы папярэдзілі аб тым, што ў абраны для выкаткі перыяд кіраванне сэрвісамі будзе недаступна.

Адступленне: што ёсць выкатка?

<асцярожна, філасофія>

Кожны айцішнік лёгка адкажа, што такое выкатка. Ставіш CI/CD, і аўтаматычна ўсё дастаўляецца на прад. 🙂

Вядома, гэта дакладна. Але складанасць у тым, што пры сучасных інструментах аўтаматызацыі дастаўкі кода губляецца разуменне самай выкаткі. Як забываеш аб эпічнасці вынаходства кола, гледзячы на ​​сучасны транспарт. Усё так аўтаматызавана, што выкатку часта праводзяць без усведамлення ўсёй карціны.

А ўся карцінка такая. Выкатка складаецца з чатырох вялікіх аспектаў:

  1. Дастаўка кода, уключаючы змяненне даных. Напрыклад, іх міграцыі.
  2. Адкат кода - магчымасць вярнуцца, калі нешта пойдзе не так. Напрыклад, праз стварэнне бэкапаў.
  3. Час кожнай аперацыі выкаткі / адкату. Трэба разумець таймінг любой аперацыі першых двух пунктаў.
  4. Закрануты функцыянал. Трэба абавязкова ацаніць як чаканы пазітыўны, так і магчымы негатыўны эфект.

Усе гэтыя аспекты неабходна ўлічыць для паспяховай выкаткі. Звычайна ацэньваюць толькі першы, у лепшым выпадку другі пункт, і тады выкатка лічыцца паспяховай. Але трэці і чацвёрты нават важнейшыя. Якому карыстальніку спадабаецца, калі выкатка зойме 3 гадзіны замест хвіліны? Або калі на выкатцы зааффектіцца нешта лішняе? Ці даунтайм аднаго сэрвісу прывядзе да непрадказальных наступстваў?

Акт 1..n, падрыхтоўка да рэлізу

Спачатку я думаў коратка апісаць нашы сустрэчы: усёй камандай, яе часткамі, кучы абмеркаванняў у каве поінтах, спрэчак, тэстаў, брэйнштармаў. Пасля падумаў, што гэта будзе лішнім. Чатыры месяцы распрацоўкі заўсёды складаюцца з такога, асабліва калі пішаш не тое, што можна дастаўляць увесь час, а адну вялікую фічу на жывую сістэму. Якая закранае ўсе сэрвісы, але ў карыстачоў нічога не павінна памяняцца, акрамя "адной кнопкі ў вэб-інтэрфейсе".

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

Калі ў аднаго з нас з'явіліся сумневы, што выкатка можа закрануць даступнасць нашых віртуальных машын, мы выдаткавалі тыдзень для правядзення тэстаў, эксперыментаў, разбору кода і атрымалі дакладнае разуменне, што такога не будзе на нашым прадакшэне, і нават самыя якія сумняваюцца людзі з гэтым пагадзіліся.

Тым часам хлопцы з тэхсапорта правялі свае незалежныя эксперыменты, каб напісаць кліентам інструкцыю па спосабах падключэння, якія павінны былі памяняцца пасля выкаткі. Яны прапрацавалі карыстацкі UX, падрыхтавалі інструкцыі і аказвалі асабістыя кансультацыі.

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

І вось ...

Акт фінальны, перад выкаткай

… надышоў час выкочвацца.

Як гаворыцца, твор мастацтва немагчыма завяршыць, толькі скончыць над ім працаваць. Трэба зрабіць валявое намаганне, разумеючы, што ўсяго не знойдзеш, але верачы, што зрабіў усе разумныя здагадкі, прадугледзеў усе магчымыя выпадкі, закрыў усе крытычныя багі, і ўсе ўдзельнікі зрабілі ўсё, што маглі. Чым больш кода выкочваеш, тым складаней пераканаць сябе ў гэтым (да таго ж любы разумее, што прадугледзець усё немагчыма).

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

  1. Афекту (свяшчэннай для нас, найкаштоўнейшай) карыстацкай інфраструктуры,
  2. Функцыянальнасцяў: выкарыстанне нашага сэрвісу пасля выкаткі павінна быць такім жа, як і да яе.

Выкатка

Гісторыя выкаткі, якая закранала ўсё
Двое коцяць, 8 не перашкаджаюць

Бярэм даунтайм на ўсе запыты ад карыстальнікаў на працягу 7 гадзін. На гэты час у нас ёсць як план выкаткі, так і план адкату.

  • Сама выкатка займае прыкладна 3 гадзіны.
  • 2 гадзіны - на тэсціраванне.
  • 2 гадзіны - запас на магчымы адкат змен.

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

Гісторыя выкаткі, якая закранала ўсё
Кавалачак дыяграмы Ганта выкаткі, адна з ранніх версій (без пералельнага выканання). Найкаштоўнейшая прылада сінхранізацыі

Ва ўсіх, хто ўдзельнічае, вызначана іх роля ў выкатцы, якія задачы робяць, за што адказваюць. Імкнемся давесці кожны этап да аўтаматызму, выкаціць адкаціць, сабраць фідбэк і каціць зноў.

хроніка падзей

Такім чынам, 15 чалавек прыехалі на працу ў нядзелю 29 красавіка, а 10-й вечара. Апроч ключавых удзельнікаў, некаторыя прыехалі проста на падтрымку каманды, завошта ім асобнае дзякуй.

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

00:00. Стоп
Спыняем карыстацкія запыты, вешаем шыльдзік, маўляў, тэхнічныя працы. Маніторынг лямантуе, але ўсё штатна. Правяраем, што нічога не ўпала, акрамя таго, што павінна было. І пачынаем працы па міграцыі.

Ва ўсіх ёсць раздрукаваны план выкаткі па пунктах, усё ведаюць, хто што робіць і ў які момант. Пасля кожнага дзеяння спраўджваемся з таймінгамі, што не перавышаем іх, і ўсё ідзе па плане. Тыя, хто не ўдзельнічае ў выкатцы непасрэдна на бягучым этапе, рыхтуюцца, запусціўшы анлайн-цацку (Xonotic, тыпу 3 квак), каб не замінаць калегам. 🙂

02:00. Выкацілі
Прыемны сюрпрыз - заканчваем выкатку на гадзіну раней, за кошт аптымізацыі нашых баз і скрыптоў міграцыі. Усеагульны кліч, «выкацілі!» Усе новыя функцыі ў продзе, але ў інтэрфейсе пакуль бачым толькі мы. Усе пераходзяць у рэжым тэсціравання, разбіраюцца на купкі, і пачынаюць глядзець, што ў выніку атрымалася.

Атрымалася не вельмі, гэта разумеем хвілін праз 10, калі ў праектах удзельнікаў каманды нічога не падключана і не працуе. Хуткі сынк, агучваем нашы праблемы, расстаўляем прыярытэты, разбіваемся на каманды і сыходзім у дэбаг.

02:30. Дзве вялікія праблемы vs чатыры вочы
Выяўляем дзве вялікія праблемы. Зразумелі, што заказчыкі не ўбачаць некаторыя падлучаныя сэрвісы, і ўзнікнуць праблемы з акаўнтамі партнёраў. Абедзве звязаны з недасканаласцю скрыптоў міграцыі для некаторых краявых выпадках. Трэба фіксаваць зараз.

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

03:00. -2 праблемы +2 праблемы
Дзве папярэднія вялікія праблемы пафікшаны, амаль усе дробныя таксама. Усе незанятыя ў фіксах актыўна працуюць у сваіх акаўнтах і рэпартуюць, што знаходзяць. Прыярытэзуем, размяркоўваем па камандах, некрытычнае пакідаем на раніцу.

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

03:20. Экстранны сынк
Адна новая праблема выпраўлена. Для другой мы ўладкоўваем экстраны синк. Разумеем, што адбываецца: папярэдні фікс адрамантаваў адну праблему, але стварыў іншую. Бярэм паўзу, каб разабрацца як зрабіць правільна і без наступстваў.

03:30. Шэсць вачэй
Усведамляем, які павінен быць выніковы стан базы, каб усё было добра ва ўсіх партнёраў. Пішам запыт у 6 вачэй, пракочваем на прадпродзе, тэстуем, які коціцца на прад.

04:00. Усё працуе
Усе тэсты прайшлі, крытычных праблем не бачна. Перыядычна ў камандзе ў кагосьці нешта не працуе, аператыўна рэагуем. Часцей за ўсё трывога ілжывая. Але часам нешта не даехала, недзе не працуе асобная старонка. Сядзім, фіксім, фіксім, фіксім. Асобная каманда запускае апошнюю вялікую фічу - білінг.

04:30. Кропка незвароту
Набліжаецца кропка невяртання, гэта значыць час, калі, калі пачнем адкочвацца, не ўкладземся ў выдадзены нам даунтайм. Ёсць праблемы з білінгам, які ўсё ведае і запісвае, але ўпарта не хоча спісваць грошы з кліентаў. Ёсць некалькі багаў на асобных старонках, дзеяннях, статутах. Асноўны функцыянал працуе, усе тэсты праходзяць паспяхова. Прымаем рашэнне, што выкатка адбылася, адкочвацца не будзем.

06:00. Адкрываем на ўсіх у UI
Багі пафікшаны. Нейкія, не афектныя карыстальнікаў, пакінуты на потым. Адкрываем інтэрфейс усім. Працягваем чараваць над білінгам, чакаем фідбэка карыстальнікаў і вынікаў маніторынгу.

07:00. Праблемы з нагрузкай на API
Становіцца ясна, што мы крыху няправільна распланавалі нагрузку на наша API і тэсціраванне гэтай нагрузкі, якое не змагло выявіць праблему. У выніку ≈5% запытаў фэйліцца. Мабілізуемся, шукаем прычыну.

Білінг упарты, таксама працаваць не жадае. Вырашаем яго адкласці на потым, каб правесці змены ў спакойным рэжыме. Гэта значыць, усе рэсурсы ў ім збіраюцца, але спісанні ў кліентаў не праходзяць. Вядома, гэта праблема, але ў параўнанні з агульнай выкаткай здаецца не прынцыповай.

08:00. Фікс API
Выкацілі фікс для нагрузкі, фэйлы сышлі. Пачынаем разыходзіцца па хатах.

10:00. Усё
Усё пафікшана. У маніторынгу і ў замоўцаў ціха, каманда паступова сыходзіць спаць. Застаўся білінг, яго будзем аднаўляць ужо заўтра.

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

Такім чынам, выкатка прайшла паспяхова! Магло б быць, вядома, і лепшым, але мы зрабілі высновы аб тым, чаго нам не хапіла, каб дасягнуць дасканаласці.

Разам

На працягу 2 месяцаў актыўнай падрыхтоўкі да моманту выкаткі выканана 43 задачы працягласцю ад пары гадзін да некалькіх дзён.

Падчас выкаткі:

  • новых і змененых дэманаў - 5 штук, якія замянілі 2 маналіта;
  • змен усярэдзіне баз дадзеных - усе 6 нашых баз з дадзенымі карыстачоў закранута, выкананы выгрузкі з трох старых баз у адну новую;
  • цалкам перароблены фронтэнд;
  • колькасць выпампаванага кода - 33 тысячы радкоў новага кода, ≈ 3 тысяч радкоў кода ў тэстах, ≈ 5 тысяч радкоў кода міграцыі;
  • усе дадзеныя цэлыя, ні адна віртуалка замоўца не папакутавала. 🙂

Добрыя практыкі для добрай выкаткі

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

  1. Першае, што трэба - зразумець, як выкатка можа паўплываць або паўплывае на карыстальнікаў. Ці будзе даунтайм? Калі будзе, то даунтайм чаго? Як гэта адаб'ецца на карыстальніках? Якія магчымы найлепшыя і найгоршыя сцэнары? І зачыняць рызыкі.
  2. Усё спланаваць. На кожным этапе трэба разумець усе аспекты выкаткі:
    • дастаўка кода;
    • адкат кода;
    • час кожнай аперацыі;
    • закрануты функцыянал.
  3. Прайграць сцэнары да таго часу, пакуль не стануць відавочныя ўсе этапы выкаткі, а таксама рызыкі на кожным з іх. Калі ў чымсьці ёсць сумневы, можна ўзяць паўзу і даследаваць сумнеўны этап асобна.
  4. Кожны этап можна і трэба палепшыць, калі гэта дапаможа нашым карыстальнікам. Напрыклад, паменшыць даунтайм або прыбярэ нейкія рызыкі.
  5. Тэставанне адкату значна важней, чым тэсціраванне дастаўкі кода. Трэба абавязкова праверыць, што ў выніку адкату сістэма вернецца ў першапачатковы стан, пацвердзіць гэта тэстамі.
  6. Усё, што можа быць аўтаматызавана, павінна быць аўтаматызавана. Усё, што не можа быць аўтаматызавана, павінна быць загадзя напісана на шпаргалцы.
  7. Зафіксаваць крытэрый паспяховасці. Які функцыянал павінен быць даступны і ў які час? Калі гэтага не адбываецца, запускайце план адкату.
  8. І самае галоўнае - людзі. Кожны павінен быць у курсе, што робіць, для чаго і што ад яго дзеянняў залежыць у працэсе выкаткі.

А калі адной фразай, то з добрым планаваннем і прапрацоўкай можна выкаціць без наступстваў для продажу ўсё што заўгодна. Нават тое, што афектыць усе вашыя сэрвісы ў продзе.

Крыніца: habr.com

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