Nuo scenarijų iki mūsų pačių platformos: kaip automatizavome kūrimą CIAN

Nuo scenarijų iki mūsų pačių platformos: kaip automatizavome kūrimą CIAN

„RIT 2019“ mūsų kolega Aleksandras Korotkovas padarė ataskaita apie kūrimo automatizavimą CIAN: norėdami supaprastinti gyvenimą ir darbą, naudojame savo Integro platformą. Jis seka užduočių gyvavimo ciklą, atleidžia kūrėjus nuo įprastų operacijų ir žymiai sumažina klaidų skaičių gamyboje. Šiame įraše papildysime Aleksandro ataskaitą ir papasakosime, kaip nuo paprastų scenarijų pereidavome prie atvirojo kodo produktų derinimo per savo platformą ir ką daro mūsų atskira automatizavimo komanda.
 

Nulinis lygis

„Nėra tokio dalyko kaip nulinis lygis, aš tokio dalyko nežinau“
Meistras Shifu iš filmo „Kung Fu Panda“

CIAN automatizavimas prasidėjo praėjus 14 metų nuo įmonės įkūrimo. Tuo metu kūrimo komandoje buvo 35 žmonės. Sunku patikėti, tiesa? Žinoma, automatizavimas tam tikra forma egzistavo, tačiau atskira kryptis nuolatiniam integravimui ir kodo pristatymui pradėjo formuotis 2015 m. 

Tuo metu mes turėjome didžiulį Python, C# ir PHP monolitą, įdiegtą Linux / Windows serveriuose. Norėdami įdiegti šį monstrą, turėjome scenarijų rinkinį, kurį paleidome rankiniu būdu. Taip pat buvo sumontuotas monolitas, kuris atnešė skausmą ir kančias dėl konfliktų sujungiant atšakas, taisant defektus ir atstatant „su kitokiomis užduotimis statyboje“. Supaprastintas procesas atrodė taip:

Nuo scenarijų iki mūsų pačių platformos: kaip automatizavome kūrimą CIAN

Mes nebuvome tuo patenkinti ir norėjome sukurti pakartojamą, automatizuotą ir valdomą kūrimo ir diegimo procesą. Tam mums reikėjo CI / CD sistemos ir pasirinkome nemokamą „Teamcity“ ir nemokamą „Jenkins“ versiją, nes dirbome su jais ir abi mums tiko pagal funkcijų rinkinį. Pasirinkome Teamcity kaip naujesnį produktą. Tuo metu dar nenaudojome mikro paslaugų architektūros ir nesitikėjome didelio užduočių ir projektų skaičiaus.

Mes priėjome prie savos sistemos idėjos

Įdiegus Teamcity buvo pašalinta tik dalis rankinio darbo: belieka sukurti „Pull Requests“, reklamuoti problemas pagal būseną „Jira“ ir atrinkti leidimus. „Teamcity“ sistema nebegalėjo su tuo susidoroti. Reikėjo pasirinkti tolesnės automatizavimo kelią. Apsvarstėme galimybes dirbti su scenarijais „Teamcity“ arba pereiti prie trečiųjų šalių automatizavimo sistemų. Tačiau galiausiai nusprendėme, kad mums reikia maksimalaus lankstumo, kurį gali suteikti tik mūsų pačių sprendimas. Taip atsirado pirmoji vidinės automatikos sistemos versija pavadinimu Integro.

„Teamcity“ užsiima automatizavimu kūrimo ir diegimo procesų paleidimo lygiu, o „Integro“ daugiausia dėmesio skyrė aukščiausio lygio kūrimo procesų automatizavimui. Darbą su „Jira“ problemomis reikėjo derinti su susijusio šaltinio kodo apdorojimu „Bitbucket“. Šiame etape „Integro“ pradėjo turėti savo darbo eigą, skirtą dirbti su įvairių tipų užduotimis. 

Didėjant verslo procesų automatizavimui, Teamcity projektų ir paleidimų skaičius išaugo. Taigi atsirado nauja problema: neužteko vieno nemokamo Teamcity egzemplioriaus (3 agentai ir 100 projektų), pridėjome dar vieną egzempliorių (dar 3 agentai ir 100 projektų), tada dar vieną. Dėl to mes sukūrėme kelių grupių sistemą, kurią buvo sunku valdyti:

Nuo scenarijų iki mūsų pačių platformos: kaip automatizavome kūrimą CIAN

Kai iškilo 4-osios instancijos klausimas, supratome, kad taip gyventi toliau nebegalime, nes bendros 4 instancijų išlaikymo išlaidos neberiboja. Iškilo klausimas dėl mokamo Teamcity įsigijimo ar nemokamo Jenkins pasirinkimo. Apskaičiavome egzempliorius ir automatizavimo planus ir nusprendėme, kad gyvensime „Jenkins“. Po poros savaičių perėjome prie „Jenkins“ ir pašalinome kai kuriuos galvos skausmus, susijusius su kelių „Teamcity“ egzempliorių palaikymu. Todėl galėjome sutelkti dėmesį į „Integro“ kūrimą ir „Jenkins“ pritaikymą sau.

Augant bazinei automatizacijai (automatinio Pull Requests kūrimo, kodo aprėpties rinkimo ir publikavimo bei kitų patikrinimų forma), kyla didelis noras kiek įmanoma atsisakyti rankinių leidimų ir šį darbą atiduoti robotams. Be to, įmonė pradėjo pereiti prie mikropaslaugų įmonės viduje, todėl reikėjo dažnai ir atskirai viena nuo kitos. Taip pamažu priėjome prie automatinių savo mikropaslaugų išleidimo (šiuo metu monolitą išleidžiame rankiniu būdu dėl proceso sudėtingumo). Tačiau, kaip dažniausiai atsitinka, atsirado naujas sudėtingumas. 

Automatizuojame testavimą

Nuo scenarijų iki mūsų pačių platformos: kaip automatizavome kūrimą CIAN

Dėl leidimų automatizavimo paspartėjo kūrimo procesai, iš dalies dėl kai kurių testavimo etapų praleidimo. Ir tai lėmė laikiną kokybės praradimą. Skamba banaliai, tačiau kartu su leidimų pagreitėjimu reikėjo keisti produkto kūrimo metodiką. Reikėjo pagalvoti apie testavimo automatizavimą, asmeninės atsakomybės (čia kalbame apie „idėjos priėmimą į galvą“, o ne pinigines baudas) kūrėjui už išleistą kodą ir jame esančias klaidas, taip pat sprendimą atleisti / neatleisti užduotį naudojant automatinį diegimą. 

Pašalindami kokybės problemas, priėjome prie dviejų svarbių sprendimų: pradėjome atlikti kanarėlių testavimą ir įdiegėme automatinį klaidų fono stebėjimą su automatiniu atsaku į jo perteklių. Pirmasis sprendimas leido aptikti akivaizdžias klaidas, kol kodas nebuvo visiškai išleistas į gamybą, antrasis sumažino reakcijos į gamybos problemas laiką. Klaidų, žinoma, pasitaiko, tačiau daugiausia laiko ir pastangų skiriame ne joms taisyti, o sumažinti. 

Automatikos komanda

Šiuo metu turime 130 kūrėjų ir dirbame toliau augti. Nuolatinio integravimo ir kodo pristatymo komanda (toliau – Deploy and Integration arba DI komanda) susideda iš 7 žmonių ir dirba 2 kryptimis: Integro automatizavimo platformos ir DevOps kūrimu. 

„DevOps“ yra atsakinga už CIAN svetainės „Dev/Beta“ aplinką, „Integro“ aplinką, padeda kūrėjams spręsti problemas ir kuria naujus aplinkos mastelio keitimo metodus. Integro kūrimo kryptis susijusi su pačiu Integro ir susijusiomis paslaugomis, pavyzdžiui, Jenkins, Jira, Confluence papildiniais, taip pat kuria pagalbines programas ir programas kūrimo komandoms. 

DI komanda bendradarbiauja su platformos komanda, kuri viduje kuria architektūrą, bibliotekas ir plėtros metodus. Tuo pačiu metu bet kuris CIAN kūrėjas gali prisidėti prie automatizavimo, pavyzdžiui, sukurti mikroautomatizaciją, kad ji atitiktų komandos poreikius, arba pasidalinti šaunia idėja, kaip automatizuoti dar geriau.

Sluoksnis automatizavimo pyragas CIAN

Nuo scenarijų iki mūsų pačių platformos: kaip automatizavome kūrimą CIAN

Visas automatizavimo sistemas galima suskirstyti į kelis sluoksnius:

  1. Išorinės sistemos (Jira, Bitbucket ir kt.). Su jais dirba vystymo komandos.
  2. Integro platforma. Dažniausiai kūrėjai su ja nedirba tiesiogiai, tačiau būtent tai užtikrina, kad visa automatika veiktų.
  3. Pristatymo, orkestravimo ir atradimų paslaugos (pavyzdžiui, Jeknins, Consul, Nomad). Jų pagalba mes įdiegiame kodą serveriuose ir užtikriname, kad paslaugos veiktų tarpusavyje.
  4. Fizinis sluoksnis (serveriai, OS, susijusi programinė įranga). Mūsų kodas veikia šiame lygyje. Tai gali būti fizinis arba virtualus serveris (LXC, KVM, Docker).

Remdamiesi šia koncepcija, mes suskirstome atsakomybės sritis DI komandoje. Pirmieji du lygiai yra Integro plėtros krypties atsakomybės sferoje, o paskutiniai du lygiai jau yra DevOps atsakomybės sferoje. Šis atskyrimas leidžia sutelkti dėmesį į užduotis ir netrukdo bendrauti, nes esame arti vienas kito ir nuolat keičiamės žiniomis ir patirtimi.

Nepažeistas

Sutelkime dėmesį į Integro ir pradėkime nuo technologijų krūvos:

  • CentOS 7
  • Docker + Nomad + Consula + Vault
  • „Java 11“ (senasis „Integro“ monolitas išliks „Java 8“)
  • Spring Boot 2.X + Spring Cloud Config
  • PostgreSql 11
  • TriušisMQ 
  • Apache Ignite
  • Camunda (įterpta)
  • Grafana + Grafitas + Prometėjas + Jėgeris + ELK
  • Žiniatinklio vartotojo sąsaja: „React“ (CSR) + „MobX“.
  • SSO: Keycloak

Mes laikomės mikropaslaugų kūrimo principo, nors turime palikimą kaip ankstyvos Integro versijos monolitą. Kiekviena mikro paslauga veikia savo Docker konteineryje, o paslaugos tarpusavyje bendrauja HTTP užklausomis ir RabbitMQ pranešimais. Mikropaslaugos randa viena kitą per Consul ir pateikia jai užklausą, perduodamos įgaliojimą per SSO (Keycloak, OAuth 2 / OpenID Connect).

Nuo scenarijų iki mūsų pačių platformos: kaip automatizavome kūrimą CIAN

Kaip realų pavyzdį apsvarstykite galimybę bendrauti su Jenkins, kurį sudaro šie veiksmai:

  1. Darbo eigos valdymo mikropaslauga (toliau vadinama „Flow“ mikropaslauga) nori paleisti „Jenkins“ versiją. Norėdami tai padaryti, jis naudoja „Consul“, kad surastų mikropaslaugos IP:PORT, skirtą integracijai su „Jenkins“ (toliau vadinama „Jenkins“ mikropaslauga), ir siunčia jai asinchroninį prašymą pradėti kūrimą „Jenkins“.
  2. Gavusi užklausą, Jenkins mikropaslauga sugeneruoja ir atsako pateikdama darbo ID, pagal kurį vėliau galima nustatyti darbo rezultatą. Tuo pačiu metu jis suaktyvina „Jenkins“ kūrimą per REST API iškvietimą.
  3. Jenkins atlieka kūrimą ir, baigęs, siunčia „webhook“ su vykdymo rezultatais „Jenkins“ mikroservisui.
  4. „Jenkins“ mikropaslauga, gavusi „webhook“, sugeneruoja pranešimą apie užklausos apdorojimo pabaigą ir prideda prie jo vykdymo rezultatus. Sugeneruotas pranešimas siunčiamas į RabbitMQ eilę.
  5. Per RabbitMQ paskelbtas pranešimas pasiekia „Flow“ mikropaslaugą, kuri sužino apie savo užduoties apdorojimo rezultatą suderindama užklausos ir gauto pranešimo užduoties ID.

Dabar turime apie 30 mikropaslaugų, kurias galima suskirstyti į kelias grupes:

  1. Konfigūracijos valdymas.
  2. Informacija ir sąveika su vartotojais (pasiuntėjai, paštas).
  3. Darbas su šaltinio kodu.
  4. Integracija su diegimo įrankiais (jenkins, nomad, consul ir kt.).
  5. Stebėjimas (išleidimai, klaidos ir kt.).
  6. Žiniatinklio paslaugos (NS, skirtas valdyti testavimo aplinkas, rinkti statistiką ir kt.).
  7. Integracija su užduočių sekimo priemonėmis ir panašiomis sistemomis.
  8. Darbo eigos valdymas įvairioms užduotims atlikti.

Darbo eigos užduotys

Integro automatizuoja veiklą, susijusią su užduoties gyvavimo ciklu. Supaprastintai, užduoties gyvavimo ciklas bus suprantamas kaip Jira užduoties darbo eiga. Mūsų kūrimo procesai turi keletą darbo eigos variantų, priklausomai nuo projekto, užduoties tipo ir konkrečioje užduotyje pasirinktų parinkčių. 

Pažvelkime į darbo eigą, kurią dažniausiai naudojame:

Nuo scenarijų iki mūsų pačių platformos: kaip automatizavome kūrimą CIAN

Diagramoje krumpliaratis rodo, kad „Integro“ automatiškai iškviečia perėjimą, o žmogaus figūra rodo, kad asmuo perėjimą iškviečia rankiniu būdu. Pažvelkime į kelis būdus, kuriais gali vykti užduotis atliekant šią darbo eigą.

Visiškai rankinis DEV+BETA testavimas be kanarėlių testų (paprastai taip išleidžiame monolitą):

Nuo scenarijų iki mūsų pačių platformos: kaip automatizavome kūrimą CIAN

Gali būti ir kitų perėjimų derinių. Kartais problemos sprendimas gali būti pasirinktas naudojant Jira parinktis.

Užduočių judėjimas

Pažvelkime į pagrindinius veiksmus, kurie atliekami, kai užduotis pereina per darbo eigą „DEV Testing + Canary Tests“:

1. Kūrėjas arba PM sukuria užduotį.

2. Kūrėjas imasi užduoties dirbti. Baigęs persijungia į PERŽIŪROS būseną.

3. Jira siunčia Webhook į Jira mikroservisą (atsakingą už integraciją su Jira).

4. Jira mikropaslauga siunčia užklausą Flow tarnybai (atsakingai už vidines darbo eigas, kuriose atliekamas darbas) pradėti darbo eigą.

5. „Inside the Flow“ paslauga:

  • Recenzentai yra priskirti užduočiai (Users mikro paslauga, kuri žino viską apie vartotojus + Jira mikropaslauga).
  • Per Source mikropaslaugą (ji žino apie saugyklas ir filialus, bet neveikia su pačiu kodu) atliekama saugyklų, kuriose yra mūsų problemos šaka, paieška (kad būtų supaprastinta paieška, filialo pavadinimas sutampa su problema numeris Jira). Dažniausiai užduotis turi tik vieną šaką vienoje saugykloje; tai supaprastina diegimo eilės valdymą ir sumažina ryšį tarp saugyklų.
  • Kiekvienai rastai šakai atliekama tokia veiksmų seka:

    i) Pagrindinės šakos atnaujinimas („Git“ mikropaslauga darbui su kodu).
    ii) Kūrėjas blokuoja šaką nuo pakeitimų („Bitbucket“ mikropaslauga).
    iii) Šiam filialui sukuriama ištraukimo užklausa („Bitbucket“ mikropaslauga).
    iv) Pranešimas apie naują ištraukimo užklausą siunčiamas į kūrėjų pokalbius („Notify microservice“, skirtas darbui su pranešimais).
    v) Kūrimo, testavimo ir diegimo užduotys pradedamos naudojant DEV (Jenkins mikroservisas, skirtas darbui su Jenkins).
    vi) Jei visi ankstesni veiksmai buvo sėkmingai atlikti, „Integro“ įtraukia patvirtinimą į ištraukimo užklausą („Bitbucket“ mikropaslauga).

  • „Integro“ laukia patvirtinimo ištraukimo užklausos iš paskirtų vertintojų.
  • Kai tik bus gauti visi reikalingi patvirtinimai (įskaitant automatinius testus teigiamai), Integro perkelia užduotį į Test on Dev (Jira mikropaslaugos) būseną.

6. Testuotojai išbando užduotį. Jei problemų nėra, užduotis perkeliama į būseną „Parengta statyti“.

7. „Integro“ „mato“, kad užduotis yra paruošta paleisti, ir pradeda jos diegimą kanarėlės režimu (Jenkins mikropaslauga). Pasirengimas paleisti nustatomas pagal taisyklių rinkinį. Pavyzdžiui, užduotis yra reikiamos būsenos, nėra užraktų kitose užduotyse, šiuo metu nėra aktyvių šios mikropaslaugos įkėlimų ir pan.

8. Užduotis perkeliama į Kanarų statusą (Jira mikroservisas).

9. Jenkins paleidžia diegimo užduotį per Nomad Canary režimu (dažniausiai 1-3 egzemplioriai) ir apie diegimą praneša leidimų stebėjimo tarnybai (DeployWatch mikropaslauga).

10. „DeployWatch“ mikropaslauga surenka klaidų foną ir, jei reikia, į jį reaguoja. Viršijus klaidos foną (fono norma apskaičiuojama automatiškai), kūrėjai informuojami per „Notify“ mikropaslaugą. Jei po 5 minučių kūrėjas neatsako (spustelėjo Grįžti arba Pasilikti), paleidžiamas automatinis kanarėlių egzempliorių atšaukimas. Jei fonas neviršytas, kūrėjas turi rankiniu būdu paleisti užduoties diegimą į gamybą (spustelėdamas NS mygtuką). Jei kūrėjas per 60 minučių nepaleis gamybinės versijos diegimo, saugumo sumetimais bus atšaukti ir „Canary“ egzemplioriai.

11. Paleidus diegimą į gamybą:

  • Užduotis perkeliama į Gamybos būseną (Jira mikroservisas).
  • „Jenkins“ mikropaslauga pradeda diegimo procesą ir praneša „DeployWatch“ mikro paslaugai apie diegimą.
  • „DeployWatch“ mikropaslauga patikrina, ar buvo atnaujinti visi gamybos konteineriai (buvo atvejų, kai buvo atnaujinti ne visi).
  • Per „Notify“ mikropaslaugą „Gamybai“ siunčiamas pranešimas apie diegimo rezultatus.

12. Kūrėjai turės 30 minučių, kad pradėtų grąžinti užduotį iš gamybinės versijos, jei bus aptikta neteisinga mikro paslaugos elgsena. Pasibaigus šiam laikui, užduotis bus automatiškai sujungta į pagrindinį („Git“ mikroservisą).

13. Sėkmingai sujungus su pagrindiniu, užduoties būsena bus pakeista į Uždaryta (Jira mikropaslauga).

Diagrama nepretenduoja į visišką detalumą (realybėje žingsnių yra dar daugiau), tačiau ji leidžia įvertinti integracijos į procesus laipsnį. Nemanome, kad ši schema yra ideali ir tobuliname automatinio išleidimo ir diegimo palaikymo procesus.

Kas toliau?

Turime didelių planų automatizavimo plėtrai, pavyzdžiui, panaikinti rankines operacijas monolitinių leidimų metu, pagerinti stebėjimą automatinio diegimo metu ir gerinti sąveiką su kūrėjais.

Bet kol kas sustokime čia. Daugelį temų automatikos apžvalgoje apžvelgėme paviršutiniškai, kai kurios iš viso nebuvo paliestos, todėl mielai atsakysime į klausimus. Laukiame pasiūlymų ką aprėpti detaliau, rašykite komentaruose.

Šaltinis: www.habr.com

Добавить комментарий