Skriptidest meie enda platvormini: kuidas automatiseerisime arendust CIANis

Skriptidest meie enda platvormini: kuidas automatiseerisime arendust CIANis

RIT 2019-l tegi meie kolleeg Aleksander Korotkov aruanne arenduse automatiseerimisest CIANis: elu ja töö lihtsustamiseks kasutame oma Integro platvormi. See jälgib ülesannete elutsüklit, vabastab arendajad rutiinsetest toimingutest ja vähendab oluliselt tootmises esinevate vigade arvu. Selles postituses täiendame Alexanderi aruannet ja räägime teile, kuidas jõudsime lihtsatest skriptidest avatud lähtekoodiga toodete kombineerimiseni oma platvormi kaudu ja mida meie eraldiseisev automatiseerimismeeskond teeb.
 

Null tase

"Sellist asja nagu nulltase pole olemas, ma ei tea sellist asja"
Meister Shifu filmist "Kung Fu Panda"

CIANi automatiseerimine algas 14 aastat pärast ettevõtte asutamist. Toona oli arendusmeeskonnas 35 inimest. Raske uskuda, eks? Muidugi oli automatiseerimine mingil kujul olemas, kuid eraldi suund pidevaks integreerimiseks ja koodi edastamiseks hakkas kujunema 2015. aastal. 

Sel ajal oli meil tohutu Pythoni, C# ja PHP monoliit, mis oli juurutatud Linuxi/Windowsi serverites. Selle koletise juurutamiseks oli meil komplekt skripte, mida käitasime käsitsi. Toimus ka monoliidi kokkupanek, mis tõi kaasa valu ja kannatusi konfliktide tõttu okste liitmisel, defektide parandamisel ja ümberehitamisel „ehitamisel teistsuguste ülesannetega”. Lihtsustatud protsess nägi välja selline:

Skriptidest meie enda platvormini: kuidas automatiseerisime arendust CIANis

Me ei olnud sellega rahul ning tahtsime luua korratava, automatiseeritud ja hallatava ehitus- ja juurutamisprotsessi. Selleks vajasime CI/CD süsteemi ja valisime Teamcity tasuta versiooni ja Jenkinsi tasuta versiooni vahel, kuna töötasime nendega ja mõlemad sobisid meile funktsioonide komplekti poolest. Valisime uuema tootena Teamcity. Sel ajal ei olnud me veel mikroteenuste arhitektuuri kasutanud ega oodanud suurt hulka ülesandeid ja projekte.

Jõuame oma süsteemi ideeni

Teamcity juurutamine eemaldas vaid osa käsitsitööst: järele jääb tõmbetaotluste loomine, probleemide reklaamimine Jiras staatuse järgi ja väljaannete valimine. Teamcity süsteem ei suutnud sellega enam toime tulla. Tuli valida edasise automatiseerimise tee. Kaalusime võimalusi Teamcitys skriptidega töötamiseks või kolmandate osapoolte automatiseerimissüsteemidele üleminekuks. Kuid lõpuks otsustasime, et vajame maksimaalset paindlikkust, mida suudab pakkuda ainult meie enda lahendus. Nii ilmus sisemise automatiseerimissüsteemi esimene versioon nimega Integro.

Teamcity tegeleb automatiseerimisega ehitus- ja juurutamisprotsesside käivitamise tasemel, Integro aga keskendus arendusprotsesside tipptasemel automatiseerimisele. Oli vaja ühendada Jira probleemidega töö ja seotud lähtekoodi töötlemine Bitbucketis. Selles etapis hakkasid Integrol olema oma töövood erinevat tüüpi ülesannetega töötamiseks. 

Seoses äriprotsesside automatiseerimise suurenemisega on Teamcitys kasvanud projektide ja käikude arv. Seega tuli uus probleem: ühest tasuta Teamcity eksemplarist ei piisanud (3 agenti ja 100 projekti), lisasime teise eksemplari (veel 3 agenti ja 100 projekti), siis teise. Selle tulemusel jõudsime mitmest klastrist koosneva süsteemini, mida oli raske hallata:

Skriptidest meie enda platvormini: kuidas automatiseerisime arendust CIANis

Kui tekkis küsimus 4. astmest, saime aru, et nii edasi elada ei saa, sest 4 instantsi toetamise kogukulud ei olnud enam piirides. Tekkis küsimus tasulise Teamcity ostmise või tasuta Jenkinsi valimise kohta. Tegime arvutused eksemplaride ja automatiseerimisplaanide kohta ning otsustasime, et elame Jenkinsi peal. Paari nädala pärast läksime üle Jenkinsile ja kõrvaldasime osa peavalust, mis on seotud mitme Teamcity eksemplari säilitamisega. Seetõttu saime keskenduda Integro arendamisele ja Jenkinsi enda jaoks kohandamisele.

Põhilise automatiseerimise kasvuga (Pull Requests automaatse loomise, Code coverage kogumise ja avaldamise ning muude kontrollide näol) on kange tahtmine käsitsi väljalasketest võimalikult palju loobuda ja see töö robotitele anda. Lisaks hakkas ettevõte üle minema mikroteenustele ettevõtte sees, mis nõudis sagedasi väljalaseid ja üksteisest eraldi. Nii jõudsime järk-järgult oma mikroteenuste automaatsete väljalaseteni (praegu vabastame monoliidi protsessi keerukuse tõttu käsitsi). Kuid nagu tavaliselt, tekkis uus keerukus. 

Automatiseerime testimise

Skriptidest meie enda platvormini: kuidas automatiseerisime arendust CIANis

Seoses väljaannete automatiseerimisega on arendusprotsessid kiirenenud, osaliselt ka mõne testimisetapi vahelejätmise tõttu. Ja see tõi kaasa ajutise kvaliteedi kadumise. Kõlab triviaalselt, kuid koos väljalasete kiirenemisega oli vaja muuta tootearenduse metoodikat. Tuli mõelda testimise automatiseerimisele, arendaja isikliku vastutuse sisendamisele (siinkohal räägime “idee peas aktsepteerimisest”, mitte rahalistest trahvidest) välja antud koodi ja selles leiduvate vigade eest, samuti otsusele vabasta/ei vabasta ülesanne automaatse juurutamise kaudu. 

Kvaliteediprobleeme kõrvaldades jõudsime kahe olulise otsuseni: hakkasime läbi viima kanaari testimist ja võtsime kasutusele veatausta automaatse jälgimise koos automaatse reageerimisega selle ülemäärasusele. Esimene lahendus võimaldas leida ilmsed vead enne koodi täielikku tootmisse laskmist, teine ​​vähendas reageerimisaega tootmises esinevatele probleemidele. Vigu muidugi juhtub, kuid me kulutame suurema osa oma ajast ja jõupingutustest mitte nende parandamisele, vaid nende minimeerimisele. 

Automatiseerimismeeskond

Praegu töötab meil 130 arendajat ja me jätkame kasvama. Pideva integreerimise ja koodi edastamise meeskond (edaspidi Deploy and Integration ehk DI meeskond) koosneb 7 inimesest ja töötab kahes suunas: Integro automatiseerimisplatvormi arendamine ja DevOps. 

DevOps vastutab CIANi saidi arendus-/beetakeskkonna, Integro keskkonna eest, aitab arendajatel probleeme lahendada ja töötab välja uusi lähenemisviise keskkondade skaleerimiseks. Integro arendussuund tegeleb nii Integro enda kui ka sellega seotud teenustega, näiteks Jenkinsi, Jira, Confluence'i pluginatega ning arendab ka abiutiliite ja rakendusi arendusmeeskondadele. 

DI-meeskond teeb koostööd platvormi meeskonnaga, kes arendab sisemiselt arhitektuuri, teeke ja arendusmeetodeid. Samas saab iga CIANi arendaja panustada automatiseerimisse, näiteks teha meeskonna vajadustele vastavat mikroautomaatikat või jagada lahedat ideed, kuidas automatiseerimist veelgi paremaks muuta.

CIANi automatiseerimise kiht

Skriptidest meie enda platvormini: kuidas automatiseerisime arendust CIANis

Kõik automatiseerimisega seotud süsteemid võib jagada mitmeks kihiks:

  1. Välised süsteemid (Jira, Bitbucket jne). Nendega töötavad arendusmeeskonnad.
  2. Integro platvorm. Enamasti ei tööta arendajad sellega otseselt, kuid see hoiab kogu automatiseerimise töös.
  3. Tarne-, orkestreerimis- ja avastusteenused (näiteks Jeknins, Consul, Nomad). Nende abiga juurutame koodi serverites ja tagame, et teenused töötavad omavahel.
  4. Füüsiline kiht (serverid, OS, seotud tarkvara). Meie kood töötab sellel tasemel. See võib olla kas füüsiline või virtuaalne server (LXC, KVM, Docker).

Sellest kontseptsioonist lähtuvalt jagame DI meeskonnas vastutusvaldkonnad. Esimesed kaks taset kuuluvad Integro arendussuuna vastutusalasse ja kaks viimast taset juba DevOpsi vastutusalasse. See eraldatus võimaldab meil keskenduda ülesannetele ega sega suhtlemist, kuna oleme üksteise lähedal ning vahetame pidevalt teadmisi ja kogemusi.

Terved

Keskendume Integrole ja alustame tehnoloogiavirust:

  • CentOS 7
  • Docker + Nomad + konsul + Vault
  • Java 11 (vana Integro monoliit jääb Java 8-le)
  • Spring Boot 2.X + Spring Cloud Config
  • PostgreSql 11
  • JänesMQ 
  • Apache Ignite
  • Camunda (manustatud)
  • Grafana + Grafiit + Prometheus + Jääger + ELK
  • Veebi kasutajaliides: React (CSR) + MobX
  • SSO: Keycloak

Peame kinni mikroteenuste arendamise põhimõttest, kuigi meil on pärand Integro varase versiooni monoliidi kujul. Iga mikroteenus töötab oma Dockeri konteineris ja teenused suhtlevad üksteisega HTTP-päringute ja RabbitMQ-sõnumite kaudu. Mikroteenused leiavad üksteist Consuli kaudu ja esitavad sellele päringu, edastades volituse SSO (Keycloak, OAuth 2/OpenID Connect) kaudu.

Skriptidest meie enda platvormini: kuidas automatiseerisime arendust CIANis

Tõelise elu näitena kaaluge Jenkinsiga suhtlemist, mis koosneb järgmistest sammudest.

  1. Töövoohalduse mikroteenus (edaspidi Flow mikroteenus) soovib käitada Jenkinsis järgu. Selleks otsib ta Consuli abil Jenkinsiga integreerimiseks mikroteenuse IP:PORT (edaspidi Jenkinsi mikroteenus) ja saadab sellele asünkroonse päringu Jenkinsis ehitamise alustamiseks.
  2. Pärast päringu saamist genereerib Jenkinsi mikroteenus ja vastab sellele Job ID, mille abil saab seejärel tuvastada töö tulemuse. Samal ajal käivitab see Jenkinsi ehitamise REST API-kõne kaudu.
  3. Jenkins teostab koostamise ja saadab pärast lõpetamist Jenkinsi mikroteenusele veebihaagi täitmise tulemustega.
  4. Jenkinsi mikroteenus, olles saanud veebihaagi, genereerib sõnumi päringu töötlemise lõpetamise kohta ja lisab sellele täitmistulemused. Loodud sõnum saadetakse RabbitMQ järjekorda.
  5. RabbitMQ kaudu jõuab avaldatud sõnum Flow mikroteenusesse, mis saab oma ülesande töötlemise tulemusest teada, sobitades päringu ja vastuvõetud sõnumi Job ID.

Nüüd on meil umbes 30 mikroteenust, mille saab jagada mitmeks rühmaks:

  1. Konfiguratsiooni juhtimine.
  2. Teave ja suhtlus kasutajatega (sõnumitoojad, post).
  3. Lähtekoodiga töötamine.
  4. Integratsioon juurutusvahenditega (jenkins, nomad, konsul jne).
  5. Järelevalve (väljalasked, vead jne).
  6. Veebiutiliidid (kasutajaliides testkeskkondade haldamiseks, statistika kogumiseks jne).
  7. Integratsioon ülesannete jälgijate ja sarnaste süsteemidega.
  8. Töövoo juhtimine erinevate ülesannete jaoks.

Töövoo ülesanded

Integro automatiseerib ülesande elutsükliga seotud tegevused. Lihtsustatult mõistetakse ülesande elutsüklit Jiras ülesande töövoona. Meie arendusprotsessidel on mitu töövoo variatsiooni sõltuvalt projektist, ülesande tüübist ja konkreetses ülesandes valitud valikutest. 

Vaatame töövoogu, mida me kõige sagedamini kasutame:

Skriptidest meie enda platvormini: kuidas automatiseerisime arendust CIANis

Diagrammil näitab hammasratas, et Integro kutsub üleminekut automaatselt välja, samas kui inimfiguur näitab, et inimene kutsub üleminekut käsitsi. Vaatame mitut teed, mida ülesanne selles töövoos läbida võib.

Täiesti käsitsi testimine DEV+BETA-s ilma kanaari testideta (tavaliselt vabastame monoliidi nii):

Skriptidest meie enda platvormini: kuidas automatiseerisime arendust CIANis

Võib olla ka teisi üleminekukombinatsioone. Mõnikord saab probleemi teekonna valida Jira valikute kaudu.

Ülesande liikumine

Vaatame peamisi samme, mida tehakse, kui ülesanne liigub läbi töövoo „DEV testimine + Canary testid”.

1. Arendaja või PM loob ülesande.

2. Arendaja võtab ülesande tööle. Pärast lõpetamist lülitub see olekusse LÄBIVAATAMINE.

3. Jira saadab veebihaagi Jira mikroteenusele (vastutab Jiraga integreerimise eest).

4. Jira mikroteenus saadab teenusele Flow (vastutab sisemiste töövoogude eest, milles töid tehakse) töövoo käivitamiseks.

5. Teenuses Flow:

  • Ülesandele määratakse ülevaatajad (kasutajate mikroteenus, mis teab kasutajatest kõike + Jira mikroteenus).
  • Source mikroteenuse kaudu (teab hoidlaid ja harusid, kuid ei tööta koodi endaga) otsitakse hoidlaid, mis sisaldavad meie väljaande haru (otsingu lihtsustamiseks kattub haru nimi probleemiga number Jiras). Kõige sagedamini on ülesandel ühes hoidlas ainult üks haru; see lihtsustab juurutusjärjekorra haldamist ja vähendab hoidlate vahelist ühenduvust.
  • Iga leitud haru jaoks tehakse järgmine toimingute jada:

    i) Põhiharu värskendamine (Git mikroteenus koodiga töötamiseks).
    ii) Arendaja blokeerib haru muudatuste eest (Bitbucketi mikroteenus).
    iii) Selle haru jaoks luuakse tõmbetaotlus (Bitbucketi mikroteenus).
    iv) Arendaja vestlustesse saadetakse teade uue tõmbamistaotluse kohta (teavitustega töötamiseks mõeldud mikroteenus).
    v) DEV-is (Jenkinsi mikroteenus Jenkinsiga töötamiseks) alustatakse tööülesannete koostamist, testimist ja juurutamist.
    vi) Kui kõik eelnevad sammud on edukalt lõpule viidud, lisab Integro oma kinnituse tõmbetaotlusesse (Bitbucketi mikroteenus).

  • Integro ootab määratud ülevaatajatelt kinnitustaotlust.
  • Niipea kui kõik vajalikud kinnitused on saadud (sh automaattestid on positiivselt läbinud), kannab Integro ülesande üle Test on Dev (Jira mikroteenus) olekusse.

6. Testijad testivad ülesannet. Kui probleeme pole, kantakse ülesanne üle olekusse Ready For Build.

7. Integro “näeb”, et ülesanne on vabastamiseks valmis ja alustab selle juurutamist kanaari režiimis (Jenkinsi mikroteenus). Vabastamiseks valmisolek määratakse reeglite kogumiga. Näiteks ülesanne on nõutavas olekus, teistel ülesannetel pole lukke, hetkel pole selle mikroteenuse aktiivseid üleslaadimisi jne.

8. Ülesanne kantakse üle Kanaari staatusesse (Jira mikroteenus).

9. Jenkins käivitab Nomadi kaudu juurutusülesande kanaari režiimis (tavaliselt 1-3 eksemplari) ja teavitab juurutusest väljalaske jälgimise teenust (DeployWatch mikroteenus).

10. DeployWatchi mikroteenus kogub kokku vea tausta ja reageerib sellele vajadusel. Vea tausta ületamisel (fooninorm arvutatakse automaatselt), teavitatakse arendajaid sellest mikroteenuse Notify kaudu. Kui 5 minuti pärast pole arendaja vastanud (klõpsanud nuppu Taasta või Jää), käivitatakse kanaari eksemplaride automaatne tagasipööramine. Kui tausta ei ületata, peab arendaja käsitsi käivitama ülesande juurutamise tootmisse (klõpsates kasutajaliideses nuppu). Kui arendaja ei ole 60 minuti jooksul tootmisse juurutamist käivitanud, tühistatakse turvakaalutlustel ka kanaari eksemplarid.

11. Pärast tootmises juurutamise käivitamist:

  • Ülesanne viiakse üle tootmisolekusse (Jira mikroteenus).
  • Jenkinsi mikroteenus käivitab juurutusprotsessi ja teavitab DeployWatchi mikroteenust juurutusest.
  • DeployWatchi mikroteenus kontrollib, et kõiki tootmisüksuses olevaid konteinereid oleks värskendatud (mõnikord oli juhtumeid, kui kõiki ei värskendatud).
  • Teavitamise mikroteenuse kaudu saadetakse tootmisüksusele teade juurutamise tulemuste kohta.

12. Kui tuvastatakse vale mikroteenuse käitumine, on arendajatel aega 30 minutit, et alustada ülesande tootmisest tagasivõtmist. Selle aja möödudes liidetakse ülesanne automaatselt ülemseadmeks (Git mikroteenus).

13. Pärast edukat ühendamist põhiseadmega muudetakse ülesande olekuks Suletud (Jira mikroteenus).

Diagramm ei pretendeeri täiesti detailsusele (tegelikkuses on samme veelgi rohkem), kuid see võimaldab hinnata protsessidesse integreerituse astet. Me ei pea seda skeemi ideaalseks ja täiustame automaatse vabastamise ja juurutamise toe protsesse.

mis edasi

Meil on suured plaanid automatiseerimise arendamiseks, näiteks kaotada käsitsi toimingud monoliitväljaannete ajal, parandada jälgimist automaatse juurutamise ajal ja parandada suhtlemist arendajatega.

Aga peatume siin praegu. Käsitlesime automatiseerimisülevaates paljusid teemasid pealiskaudselt, mõnda ei puudutatud üldse, seega vastame küsimustele hea meelega. Ootame ettepanekuid, mida täpsemalt kajastada, kirjutage kommentaaridesse.

Allikas: www.habr.com

Lisa kommentaar