
RIT 2019 toimus meie kolleegi Aleksandr Korotkovi ettekanne arenduse automatiseerimisest CIANis: elu ja töö lihtsustamiseks kasutame oma platvormi Integro. See jälgib ülesannete elutsüklit, vabastab arendajad rutiinsetest toimingutest ja vähendab oluliselt tootmisvigade arvu. Selles postituses täiendame Aleksandri ettekannet ja räägime, kuidas me liikusime lihtsatest skriptidest open source toodete integreerimise kaudu oma platvormini ning milles meie eraldiseisev automatiseerimise meeskond tegeleb.
Nulltase
„Nulltaset ei ole, ma ei tea midagi sellisest“
Meister Shifu filmist „Kung Fu Panda“
CIANis sai automatiseerimine alguse 14 aastat pärast ettevõtte asutamist. Toona oli arendusmeeskonnas 35 inimest. Raske uskuda, eks? Loomulikult mingil moel automatiseerimine ikkagi eksisteeris, kuid pideva integreerimise ja koodi juurutamise eriline suund hakkas kujunema just 2015. aastal.
Sel ajal oli meil suur monoliit Pythonis, C#-is ja PHP-s, mis töötas Linuxi/Windosi serverites. Selle hiiglasliku deploimiseks oli meil käsitsi käivitatav skriptide kogum. Samuti oli olemas monoliidi kokkupanek, mis põhjustas valu ja kannatusi haru ühinemise konfliktide, defektide parandamise ja „teise ülesannete kogumi koostamisprotsessis“ tõttu. Lihtsustatult nägi protsess välja nii:

See ei rahuldanud meid ning soovisime luua korduvat, automatiseeritud ja hallatavat süsteemi kokkupanekuks ja deploimiseks. Selleks vajasime CI/CD süsteemi ja valisime tasuta Teamcity versiooni ja tasuta Jenkins'i vahel, kuna olime nendega varem töötanud ja mõlemad sobisid meie funktsioonide komplektiga. Valisime Teamcity, kuna see oli uuem toode. Toona ei kasutanud me veel mikroteenuste arhitektuuri ega lootnud suurele ülesannete ja projektide hulgale.
Me jõuame ideeni oma süsteemist
Teamcity käivitamine vähendas ainult osa käsitsi tehtavast tööst: jäänud on veel Pull Requestide loomine, ülesannete edendamine Jira staatustes ja ülesannete valimine väljaande jaoks. Sellega Teamcity enam toime ei tulnud. Oli vaja valida edasise automatiseerimise tee. Me vaatasime võimalusi skriptide kasutamiseks Teamcitys või kolmandate osapoolte automatiseerimissüsteemide suunas. Kuid lõpuks otsustasime, et vajame maksimaalset paindlikkust, mida pakub ainult meie enda lahendus. Nii sündis esimene versioon sisemisest automatiseerimissüsteemist nimega Integro.
Teamcity tegeleb automatiseerimisega ehitamis- ja paigaldusprotsesside tasemel, samas kui Integro keskendub kõrgema taseme arendusprotsesside automatiseerimisele. Oli vaja siduda töö Jira ülesannetega Bitbucketis olevate seotud allika-koodide töötlemisega. Selle etapi jooksul hakkasid Integro sees tekkima oma töövood erinevat tüüpi ülesannete käsitlemiseks.
Automatiseerimise suurenemise tõttu äriprotsessides kasvas projektide ja Teamcity jooksude arv. Nii ilmnes uus probleem: ühest tasuta Teamcity instantsist ei piisanud (3 agenti ja 100 projekti), me lisasime veel ühe instantsi (veel 3 agenti ja 100 projekti), siis veel ühe. Lõpuks saime süsteemi, mis koosnes mitmest klastrist ja millega oli raske hallata:

Kui tekkis küsimus neljanda instantsi kohta, mõistsime, et sellisel kujul ei saa me enam elada, kuna nelja instantsi hooldamise kulud ei mahtunud enam mingitesse raamidesse. Tekkis küsimus tasulise Teamcity soetamisest või tasuta Jenkinsile eelmisest. Tegime instantside ja automatiseerimisplaanide osas arvutused ja otsustasime, et elame Jenkinsiga. Paari nädala pärast kolisime Jenkinsile ja vabanesime osast peavalust, mis oli seotud mitme Teamcity instantsi hooldamisega. Seetõttu saime keskenduda Integro arendamisele ja Jenkinssi kohandamisele enda jaoks.
Baasi automatiseerimise kasvuga (näiteks Pull Requestide automaatne loomine, koodi katvuse kogumine ja avaldamine ning muud kontrollid) tekkis püsiv soov loobuda käsitsi väljaannetest ja usaldada see töö robotitele. Lisaks alustas ettevõttesisene üleminek mikroteenustele, mis nõudsid sagedasi väljaandeid, ja need pidid olema omavahel eraldi. Nii jõudsime järk-järgult oma mikroteenuste automaatseteni (monoliitset jätkame praegu käsitsi, kuna protsess on keeruline). Kuid nagu see tavaliselt juhtub, tekkis uus keerukus.
Automatiseerime testimise

Väljaannete automatiseerimise tõttu on arendusprotsessid kiirenend, osaliselt isegi katsetamise teatud etappide vahele jätmise arvelt. See on aga kaasa toonud ajutise kvaliteedi languse. See näeb välja tavaline, kuid koos väljaannete kiirenemisega oli vaja muuta ka arendusmeetodoloogiat. Piisavalt tuli mõelda testimise automatiseerimise, arendaja isiklike vastutuste loomise (siin on jutt 'idee pähe omaksmisest', mitte rahalistest karistustest) ja ülesande väljaandmise/mitte väljaandmise otsuse tegemise üle automaatse juurutamise kaudu.
Kvaliteediprobleemide lahendamisel jõudsime kahte olulisse otsusesse: hakkasime viima läbi kanaristestimist ja rakendasime automaatse vea jälgimise koos automaatse reageerimisega selle ületamisel. Esimene otsus võimaldas leida ilmseid vigu enne koodi täielikku jõudmist productionisse, teine vähendas reageerimise aega productioni probleemidele. Vead ju esinevad, kuid me kulutame suurema osa ajast ja vaevast mitte parandamisele, vaid minimiseerimisele.
Automatiseerimise meeskond
Praegu on meil 130 arendajat, ja me jätkame . Jätkuva integreerimise ja koodi kohaletoimetamise meeskond (edaspidi - Deploy and Integration ehk DI meeskond) koosneb 7 inimesest ja töötab 2 suunas: automatiseerimise platvormi arendamine Integro ja DevOps.
DevOps vastutab CIANi Dev/Beta keskkondade eest, Integro keskkondade ees, aitab arendajatel probleemide lahendamisel ning töötatakse välja uusi lähenemisviise keskkondade suurendamiseks. Integro arendussuund tegeleb nii Integroga kui ka külgteenustega, näiteks Jenkins, Jira, Confluence pistikprogrammidega, ning arendab töötajate jaoks abitööriistu ja rakendusi.
DI meeskond töötab koos Platvormi meeskonnaga, mis tegeleb arhitektuuri, raamatukogude ja arendusuuringute väljatöötamisega ettevõttes. Samuti võivad kõik arendajad CIANi sees panustada automatiseerimisse, näiteks luua meeskonnale mikroautomaatika või jagada ägeda idee, kuidas automatiseerimist veelgi paremaks muuta.
Automaatimise kihiline kook CIANis

Kõiki automatiseerimises osalevaid süsteeme saab jagada mitmeks kihiks:
- Välised süsteemid (Jira, Bitbucket jne). Nende kallal töötavad arendusmeeskonnad.
- Integro platvorm. Arendajad ei tööta sellega tavaliselt otse, kuid just see toetab kogu automatiseerimise tööd.
- Kohaletoimetamise, orkestreerimise ja avastamise teenused (näiteks Jenkins, Consul, Nomad). Nende abil paigaldame koodi serveritesse ja tagame, et teenused omavahel töötaksid.
- Füüsiline tase (serverid, operatsioonisüsteem, kõrvutarkvara). Sellel tasemel töötab meie kood. See võib olla nii füüsiline server kui ka virtuaalne (LXC, KVM, Docker).
Väljaspool seda kontseptsiooni jagame DI meeskonna sees vastutuspiirkondi. Kaks esimest taset kuuluvad Integro arendussuuna vastutusele, samas kui kaks viimast taset kuuluvad DevOpsi vastutusele. Selline jaotus võimaldab keskenduda ülesannetele, takistamata koostööd, kuna me oleme üksteisest lähedal ja vahetame pidevalt teadmisi ja kogemusi.
Integro
Keskendume Integrole ja alustame tehnoloogilisest järjestusest:
- CentOs 7
- Docker + Nomad + Consul + Vault
- Java 11 (vana Integro monoliit jääb Java 8-le)
- Spring Boot 2.X + Spring Cloud Config
- PostgreSql 11
- RabbitMQ
- Apache Ignite
- Camunda (embedded)
- Grafana + Graphite + Prometheus + Jaeger + ELK
- Veebiliides: React (CSR) + MobX
- SSO: Keycloak
Meie järgime mikroteenuste arendamise põhimõtet, kuigi meil on olemas ka pärandina varasema versiooni Integro monoliit. Iga mikroteenus töötab oma docker-konteineris, teenused suhtlevad omavahel HTTP-päringute ja RabbitMQ sõnumite kaudu. Mikroteenused leiavad üksteist Consuli kaudu ja teevad sellele päringu, läbides autoriseerimise SSO (Keycloak, OAuth 2/OpenID Connect) kaudu.

Reaalse näitena vaatame Jenkinsiga suhtlemist, mis koosneb järgmistest sammudest:
- Workflow haldamise mikroteenus (edaspidi Flow-mikroteenus) soovib Jenkinsis ehituse käivitada. Selleks leiab ta Consuli kaudu IP:PORT integreerimise mikroteenuse (edaspidi Jenkins-mikroteenus) ja saadab sellele asünkroonse päringu Jenkinsis ehituse käivitamiseks.
- Jenkins-mikroteenus vormib ja tagastab pärast päringu saamist töö ID, mille abil saab hiljem töö tulemusi tuvastada. Samuti käivitab ta Jenkinsis ehituse REST API kutse kaudu.
- Jenkins sooritab ehituse ja pärast selle lõppemist saadab webhooks tulemused Jenkins-mikroteenusele.
- Jenkins-mikroteenus, olles saanut webhooki, koostab sõnumi päringu töötlemise lõpetamisest ja lisab sellele töötlemise tulemused. Koostatud sõnum saadetakse RabbitMQ järjekorda.
- RabbitMQ kaudu jõuab avaldatud sõnum Flow-mikroteenusesse, mis saab teada oma ülesande töötlemise tulemustest, võrreldes päringust ja saadud sõnumist pärit töö ID-d.
Praegu on meil umbes 30 mikroteenust, mille saab jagada mitmeks rühmaks:
- Konfiguratsioonide haldamine.
- Kasutajate informeerimine ja suhtlemine (messenger'id, e-post).
- Töö lähtekoodiga.
- Integreerimine juurutustööriistadega (jenkins, nomad, consul jne).
- Jälgimine (väljalaskeid, vigu jne).
- Veebiutiliidid (UI testkeskkondade haldamiseks, statistika kogumiseks jne).
- Integreerimine ülesandejälgijate ja sarnaste süsteemidega.
- Workflow haldamine erinevate ülesannete jaoks.
Ülesande workflow
Integro automatiseerib ülesande elutsükliga seotud toimingud. Lihtsustatult mõistame ülesande elutsükli all Jira ülesande workflow'd. Meie arendusprotsessides on mitmeid workflow variante, sõltuvalt projektist, ülesande tüübist ja konkreetses ülesandes valitud valikutest.
Vaatame workflow'd, mida kasutame kõige sagedamini:

Skeemil osutab hammasratta kaudu, et transition kutsub Integro automaatselt esile, samas kui inimese kujukene tähendab, et transition kutsub esile inimene käsitsi. Vaatame üle mitu teed, kuidas ülesanne võib selle töövoo raames kulgeda.
Täielik käsitsi testimine DEV+BETA ilma kanaröstimise testideta (tavaliselt nii lanceerime monoliiti):

Saavad olla ka teised transition kombinatsioonid. Mõnikord saab ülesande teed valida Jira valikute kaudu.
Ülesande liikumine
Vaatame põhietapid, mis toimuvad ülesande liikumisel töövoos "Testimine DEV + kanaröstimise testid":
1. Arendaja või PM loob ülesande.
2. Arendaja võtab ülesande enda toimetusse. Pärast lõpetamist viib ta selle olekusse IN REVIEW.
3. Jira saadab Webhook'i Jira mikroteenusele (vastutab Jira integreerimise eest).
4. Jira mikroteenus saadab Flow teenusele päringu (vastutab sisemiste töövoogude eest, kus töö toimub), et käivitada töövoog.
5. Flow teenuse sees:
- Määratakse ülesannetele ülevaatajad (Kasutajad mikroteenus, mis teab kõike kasutajatest + Jira mikroteenus).
- Source mikroteenuse kaudu (teab reposte ja harusid, kuid ei tee tööd koodiga) otsitakse reposte, kus on meie ülesande haru (otsingu lihtsustamiseks vastab haru nimi Jira ülesande numbrile). Enamasti on ülesandel vaid üks haru ühes repos, see lihtsustab juurdepääsu haldamist ja vähendab reposte omavahelist sõltuvust.
- Iga leitud haru puhul viiakse läbi järgmised toimingud:
i) Master-haru ühendamine (Git mikroteenus koodi töötlemiseks).
ii) Haru lukustamine muudatuste eest arendaja poolt (Bitbucket mikroteenus).
iii) Sellele harule luuakse Pull Request (Bitbucket mikroteenus).
iv) Uus Pull Requesti sõnum saadetakse arendajate vestlustesse (Notify mikroteenus teavitamiseks).
v) Käivitatakse ülesande kogumine, testimine ja deploy DEV-is (Jenkins mikroteenus Jenkinsiga tegelemiseks).
vi) Kui kõik eelnevad punktid on edukalt lõpetatud, siis Integro lisab oma Ameerika Ühendriikide Pull Requesti (Bitbucket mikroteenus). - Integro ootab määratud ülevaatajatelt Pull Requestis Ameerika Ühendriikide saamist.
- Niipea kui kõik vajalikud Ameerika Ühendriigid on saadud (sealhulgas automaatsete testide positiivne läbimine), muudab Integro ülesande staatust Test on Dev (Jira mikroteenus).
6. Testijad viivad ülesande testimise läbi. Kui probleeme pole, siis viivad nad ülesande staatusesse Ready For Build.
7. Integro „näeb“, et ülesanne on valmis väljaandmiseks ja käivitab selle paigaldamise kanarerežiimis (Jenkins-mikroteenus). Valmidus väljaandmiseks määratakse reeglite kogumi järgi. Näiteks peab ülesanne olema õigel staatustaseme, teisi ülesandeid ei tohiks blokeerida, aktiivseid paigaldusi ei tohiks sellele mikroteenusele hetkel olla jne.
8. Ülesanne viiakse staatusele Canary (Jira-mikroteenus).
9. Jenkins käivitab Nomadi kaudu ülesande paigaldamise kanarerežiimis (tavaliselt 1-3 instantsi) ja teavitab paigaldusest versioonide jälgimise teenust (DeployWatch-mikroteenus).
10. DeployWatch-mikroteenus kogub vigade tausta ja reageerib sellele, kui on vaja. Kui vigade taust ületab normi (norm kalkuleeritakse automaatselt), teavitavad arendajad Notify-mikroteenus. Kui arendaja ei reageeri 5 minuti jooksul (vajutab Revert või Stay), käivitub automaatne kanarinstantside tagasipööramine. Kui taust ei ole ületatud, peab arendaja käsitsi käivitama ülesande paigaldamise tootmises (vajutades nuppu UI-s). Kui arendaja ei käivita tootmises paigaldust 60 minuti jooksul, tagastatakse ka kanarinstantsid, et tagada ohutus.
11. Pärast tootmises paigaldamise käivitamist:
- Ülesanne viiakse staatusele Production (Jira-mikroteenus).
- Jenkins-mikroteenus käivitab paigaldusprotsessi ja teavitab paigaldusest DeployWatch-mikroteenus.
- DeployWatch-mikroteenus kontrollib, et kõiki konteinerite tootmises on uuendatud (on olnud juhtumeid, kus mitte kõik uuendatakse).
- Notify-mikroteenus saadab teate paigaldamise tulemustest tootmises.
12. Arendajatel on 30 minutit aega ülesande tagasivõtmiseks tootmisest, kui mikroteenuse vale käitumine avastatakse. Selle aja möödudes on ülesanne automaatselt sisse viidud masterisse (Git-mikroteenus).
13. Pärast eduka sulandumise masterisse muutub ülesande staatuseks Closed (Jira-mikroteenus).
Skeem ei pretendeeri täielikule detaile, kuid võimaldab hinnata integreerimise astet protsessidesse. Me ei pea seda skeemi ideaaliks ja parandame automaatsete väljaannete ja paigaldamisprotsesside protsesse.
Mis edasi
Meil on suured plaanid automatiseerimise arendamiseks, näiteks käsitsi operatsioonide lõpetamine monoliitide väljaandmise ajal, jälgimise parendamine automaatse paigaldamise puhul, arendajate koostöö parandamine.
Kuid jääme siinkohal pidama. Oleme palju teemasid automatiseerimise ülevaates pinnapealselt käsitlenud, mõned on jäänud üldse kõrvale, seetõttu vastame me rõõmuga küsimustele. Ootame ettepanekuid, mida põhjalikult käsitleda, kirjutage kommentaarides.
Allikas: habr.com
