À RIT 2019, u nostru cumpagnu Alexander Korotkov hà fattu
Livellu zero
"Ùn ci hè nunda cum'è un livellu zero, ùn cunnoscu micca una cosa cusì"
Maestru Shifu da u filmu "Kung Fu Panda"
L'automatizazione in CIAN hà iniziatu 14 anni dopu a fondazione di a cumpagnia. À quellu tempu ci era 35 persone in a squadra di sviluppu. Difficile à crede, nò? Di sicuru, l'automatizazione esistia in una certa forma, ma una direzzione separata per l'integrazione cuntinua è a consegna di codice hà cuminciatu à piglià forma in 2015.
À quellu tempu, avemu avutu un grande monolitu di Python, C# è PHP, implementatu nantu à i servitori Linux / Windows. Per implementà stu mostru, avemu avutu un inseme di script chì avemu eseguitu manualmente. Ci era ancu l'assemblea di u monolitu, chì hà purtatu u dulore è u soffrenu per via di cunflitti quandu unisce e rami, corregge i difetti, è ricustruisce "cun un altru settore di compiti in a custruzzione". Un prucessu simplificatu pareva cusì:
Ùn eramu micca cuntenti di questu, è vuliamu custruisce un prucessu di creazione è implementazione ripetibile, automatizatu è gestibile. Per questu, avemu bisognu di un sistema CI / CD, è avemu sceltu trà a versione libera di Teamcity è a versione libera di Jenkins, postu chì avemu travagliatu cun elli è tutti dui ci sò adattati in quantu à u settore di funzioni. Avemu sceltu Teamcity cum'è un pruduttu più recente. À quellu tempu, ùn aviamu micca ancu utilizatu l'architettura di microserviziu è ùn s'aspittava micca un gran numaru di travaglii è prughjetti.
Venemu à l'idea di u nostru sistema
L'implementazione di Teamcity hà eliminatu solu una parte di u travagliu manuale: ciò chì resta hè a creazione di Pull Requests, a prumuzione di prublemi per statutu in Jira, è a selezzione di prublemi per a liberazione. U sistema Teamcity ùn pudia più affruntà questu. Era necessariu di sceglie a strada di più automatizazione. Avemu cunsideratu l'opzioni per travaglià cù script in Teamcity o cambià à sistemi d'automatizazione di terzu. Ma à a fine avemu decisu chì avemu bisognu di flessibilità massima, chì solu a nostra propria suluzione pò furnisce. Hè cusì chì a prima versione di u sistema d'automatizazione internu chjamatu Integro hè apparsu.
Teamcity tratta di l'automatizazione à u livellu di lanciazione di i prucessi di custruzzione è di implementazione, mentre chì Integro si cuncintrau in l'automatizazione di u primu livellu di i prucessi di sviluppu. Era necessariu di cumminà u travagliu cù prublemi in Jira cù u processu di codice fonte assuciatu in Bitbucket. À questu stadiu, Integro hà cuminciatu à avè u so propiu flussu di travagliu per travaglià cù travaglii di diversi tipi.
A causa di l'automatizazione in i prucessi di cummerciale, u numeru di prughjetti è corse in Teamcity hè aumentatu. Allora un novu prublema hè ghjuntu: una istanza libera di Teamcity ùn era micca abbastanza (3 agenti è 100 prughjetti), avemu aghjustatu un altru esempiu (3 più agenti è 100 prughjetti), dopu un altru. In u risultatu, avemu finitu cù un sistema di parechji clusters, chì era difficiule di gestisce:
Quandu a quistione di una 4a istanza hè ghjunta, avemu capitu chì ùn pudemu micca cuntinuà à campà cusì, perchè i costi totali di supportu 4 istanze ùn eranu più in alcun limite. A quistione hè ghjunta nantu à l'acquistu di Teamcity pagatu o di sceglie Jenkins gratuiti. Avemu fattu calculi nantu à istanze è piani d'automatizazione è decisu chì vivemu nantu à Jenkins. Dopu un paru di settimane, avemu cambiatu à Jenkins è eliminatu alcuni di u mal di testa assuciatu à mantene parechje istanze di Teamcity. Dunque, avemu pussutu fucalizza nantu à sviluppà Integro è persunalizà Jenkins per noi stessi.
Cù a crescita di l'automatizazione di basa (in a forma di creazione automatica di Pull Requests, cullizzioni è publicazione di a cobertura di u Code è altri cuntrolli), ci hè un forte desideriu di abbandunà e versioni manuali quant'è pussibule è dà stu travagliu à i robots. Inoltre, a cumpagnia hà cuminciatu à trasfurmà à i microservizi in a cumpagnia, chì necessitava liberazioni frequenti, è separatamente l'una di l'altru. Hè cusì chì avemu gradualmente ghjuntu à e versioni automatiche di i nostri microservizi (attualmente stendemu u monolitu manualmente per via di a cumplessità di u prucessu). Ma, cum'è di solitu succede, hè ghjunta una nova cumplessità.
Automatizemu a prova
A causa di l'automatizazione di e versioni, i prucessi di sviluppu anu acceleratu, in parte per via di saltà di alcune tappe di prova. È questu hà purtatu à una perdita temporale di qualità. Sembra triviale, ma cù l'accelerazione di e versioni, era necessariu di cambià a metodulugia di sviluppu di u produttu. Hè statu necessariu di pensà à l'automatizazione di e teste, infundendu a rispunsabilità persunale (quì si parla di "accettà l'idea in u capu", micca fine monetaria) di u sviluppatore per u codice liberatu è i bug in questu, è ancu a decisione di liberate / micca liberate un compitu per mezu di implementazione automatica.
Eliminendu i prublemi di qualità, avemu ghjuntu à duie decisioni impurtanti: avemu cuminciatu à fà una prova canaria è hà introduttu u monitoraghju automaticu di u fondu di errore cù una risposta automatica à u so eccessu. A prima suluzione hà permessu di truvà errori evidenti prima chì u codice hè stata liberata cumplettamente in a produzzione, a seconda hà riduciutu u tempu di risposta à i prublemi in a produzzione. L'errori, sicuru, succedenu, ma passamu a maiò parte di u nostru tempu è sforzu micca per correggerli, ma per minimizzà.
Squadra di l'automatizazione
Avemu attualmente un staffu di sviluppatori 130, è cuntinuemu
DevOps hè rispunsevule per l'ambiente Dev / Beta di u situ CIAN, l'ambienti Integro, aiuta à i sviluppatori à risolve i prublemi è sviluppa novi approcci à scaling ambienti. A direzzione di sviluppu Integro si tratta di l'Integro stessu è di i servizii cunnessi, per esempiu, plugins per Jenkins, Jira, Confluence, è ancu sviluppa utilità ausiliarie è applicazioni per i gruppi di sviluppu.
U squadra DI travaglia in cullaburazione cù a squadra di a Piattaforma, chì sviluppa l'architettura, biblioteche è approcci di sviluppu internamente. À u listessu tempu, ogni sviluppatore in CIAN pò cuntribuisce à l'automatizazione, per esempiu, fà micro-automatizazione per adattà à i bisogni di a squadra o sparte una idea fresca nantu à cumu fà l'automatizazione ancu megliu.
Torta à strati di l'automatizazione à u CIAN
Tutti i sistemi implicati in l'automatizazione ponu esse divisi in parechji strati:
- Sistemi esterni (Jira, Bitbucket, etc.). I gruppi di sviluppu travaglianu cun elli.
- piattaforma Integro. A maiò spessu, i sviluppatori ùn travaglianu micca direttamente cun ellu, ma hè ciò chì mantene tutte l'automatizazione in esecuzione.
- Servizi di consegna, orchestrazione è scuperta (per esempiu, Jeknins, Consul, Nomad). Cù u so aiutu, implementemu codice nantu à i servitori è assicuratemu chì i servizii travaglianu cun l'altri.
- Stratu fisicu (servitori, OS, software rilativi). U nostru codice opera à stu livellu. Questu pò esse un servitore fisicu o virtuale (LXC, KVM, Docker).
Basatu annantu à stu cuncettu, dividemu e zone di rispunsabilità in a squadra DI. I primi dui livelli sò in l'area di rispunsabilità di a direzzione di sviluppu Integro, è l'ultimi dui livelli sò digià in l'area di responsabilità di DevOps. Sta separazione ci permette di fucalizza nantu à i travaglii è ùn interferiscenu micca cù l'interazzione, postu chì simu vicinu à l'altru è scambià constantemente cunniscenze è sperienza.
Intactu
Fighjemu nantu à Integro è cuminciamu cù a pila di tecnulugia:
- CentOS 7
- Docker + Nomad + Consul + Vault
- Java 11 (u vechju monolitu Integro resterà in Java 8)
- Spring Boot 2.X + Spring Cloud Config
- PostgreSql 11
- Rabbit MQ
- Apache Ignite
- Camunda (incrustata)
- Grafana + Grafite + Prometheus + Jaeger + ELK
- UI Web: React (CSR) + MobX
- SSO: Keycloak
Aderemu à u principiu di u sviluppu di u microserviziu, ancu s'è avemu un legatu in forma di un monolitu di una prima versione di Integro. Ogni microserviziu funziona in u so propiu cuntainer Docker; i servizii cumunicanu cù l'altri via richieste HTTP è missaghji RabbitMQ. I microservizi si trovanu à traversu Consul è facenu una dumanda à ellu, passendu l'autorizazione per SSO (Keycloak, OAuth 2/OpenID Connect).
Cum'è un esempiu di a vita reale, cunzidira l'interazzione cù Jenkins, chì si compone di i seguenti passi:
- U microserviziu di gestione di u flussu di travagliu (in seguitu chjamatu u microserviziu Flow) vole eseguisce una custruzzione in Jenkins. Per fà questu, usa Consul per truvà l'IP: PORT di u microserviziu per l'integrazione cù Jenkins (in seguitu chjamatu Jenkins microservice) è li manda una dumanda asincrona per inizià a custruzione in Jenkins.
- Dopu avè ricivutu una dumanda, u microserviziu Jenkins genera è risponde cù un ID di travagliu, chì pò esse usatu per identificà u risultatu di u travagliu. À u listessu tempu, attiva a custruzione in Jenkins via una chjamata API REST.
- Jenkins esegue a custruzzione è, dopu à a fine, manda un webhook cù i risultati di l'esekzione à u microserviziu Jenkins.
- U microserviziu Jenkins, dopu avè ricevutu u webhook, genera un missaghju nantu à a fine di u processu di a dumanda è aghjunghje i risultati di l'esekzione. U messagiu generatu hè mandatu à a fila RabbitMQ.
- Per mezu di RabbitMQ, u missaghju publicatu ghjunghje à u microserviziu Flow, chì ampara nantu à u risultatu di trasfurmà u so compitu cumminendu l'ID di Job da a dumanda è u missaghju ricevutu.
Avà avemu circa 30 microservizi, chì ponu esse divisi in parechji gruppi:
- Gestione di a cunfigurazione.
- Infurmazione è interaczione cù l'utilizatori (messageri, mail).
- U travagliu cù u codice fonte.
- Integrazione cù strumenti di implementazione (jenkins, nomadi, cunsul, etc.).
- Monitoring (releases, errors, etc.).
- Utilità Web (UI per a gestione di l'ambienti di prova, a cullizzioni di statistiche, etc.).
- Integrazione cù trackers di attività è sistemi simili.
- Gestione di u flussu di travagliu per diverse attività.
I travaglii di u flussu di travagliu
Integro automatizza l'attività ligati à u ciclu di vita di u travagliu. In termini simplificati, u ciclu di vita di un compitu serà capitu cum'è u flussu di travagliu di un compitu in Jira. I nostri prucessi di sviluppu anu parechje variazioni di flussu di travagliu secondu u prughjettu, u tipu di compitu è l'opzioni selezziunate in un compitu particulari.
Fighjemu u flussu di travagliu chì usemu più spessu:
In u diagramma, l'ingranaggio indica chì a transizione hè chjamata automaticamente da Integro, mentri a figura umana indica chì a transizione hè chjamata manualmente da una persona. Fighjemu parechji percorsi chì un compitu pò piglià in stu flussu di travagliu.
Testu cumpletamente manuale nantu à DEV + BETA senza teste canari (di solitu hè cusì chì liberamu un monolitu):
Ci ponu esse altre combinazioni di transizione. Calchì volta u percorsu chì un prublema pigliarà pò esse sceltu attraversu l'opzioni in Jira.
U muvimentu di u travagliu
Fighjemu i passi principali chì sò realizati quandu un compitu si move attraversu u flussu di travagliu "Test DEV + Test Canary":
1. U sviluppatore o PM crea u compitu.
2. U sviluppatore piglia u compitu à travaglià. Dopu à a fine, passa à u statu IN REVIEW.
3. Jira manda un Webhook à u microservice Jira (rispunsevuli di integrazione cù Jira).
4. U microservice Jira manda una dumanda à u serviziu Flow (rispunsevuli di i flussi di travagliu internu in quale u travagliu hè realizatu) per inizià u flussu di travagliu.
5. Dentru u serviziu di flussu:
- I revisori sò attribuiti à u compitu (Users microservice chì sapi tuttu di l'utilizatori + Jira microservice).
- Per mezu di u microserviziu Source (sà di repositori è rami, ma ùn travaglia micca cù u codice stessu), una ricerca hè fatta per i repositori chì cuntenenu un ramu di u nostru prublema (per simplificà a ricerca, u nome di a ramu coincide cù u prublema). numeru in Jira). A maiò spessu, un compitu hà solu un ramu in un repository; questu simplifica a gestione di a fila di implementazione è riduce a connettività trà i repositori.
- Per ogni ramu truvata, a seguente sequenza di azzioni hè realizata:
i) Aghjurnà u ramu maestru (microserviziu Git per travaglià cù u codice).
ii) U ramu hè bluccatu da i cambiamenti da u sviluppatore (microserviziu Bitbucket).
iii) Una Pull Request hè creata per questa filiera (microserviziu Bitbucket).
iv) Un missaghju nantu à una nova Pull Request hè mandatu à i chats di sviluppatore (Notifica microservice per travaglià cù notificazioni).
v) Custruisce, teste è implementà i travaglii sò iniziati in DEV (microserviziu Jenkins per travaglià cù Jenkins).
vi) Se tutti i passi precedenti sò cumpletati cù successu, allora Integro mette a so Approvazione in a Pull Request (microservice Bitbucket). - Integro aspetta l'Approvazione in Pull Request da i revisori designati.
- Appena tutte l'appruvazioni necessarie sò state ricevute (cumprese e teste automatizzate sò passate positivamente), Integro trasferisce u compitu à u statu di Test on Dev (microservice Jira).
6. Testers pruvà u compitu. Se ùn ci sò micca prublemi, u compitu hè trasferitu à u statu di Ready For Build.
7. Integro "vede" chì u compitu hè prontu per a liberazione è principia a so implementazione in modu canariu (microservice Jenkins). A preparazione per a liberazione hè determinata da un inseme di regule. Per esempiu, u compitu hè in u statutu necessariu, ùn ci sò micca chjusi nantu à altre attività, ùn ci hè attualmente micca uploads attivu di stu microserviziu, etc.
8. U compitu hè trasferitu à u statu di Canary (microservice Jira).
9. Jenkins lancia un compitu di implementazione attraversu Nomad in modu canarinu (in solitu 1-3 casi) è notifica à u serviziu di monitoraghju di liberazione (microservice DeployWatch) nantu à a implementazione.
10. U microserviziu DeployWatch recullà u fondu di l'errore è reagisce à questu, se ne necessariu. Se u fondu di l'errore hè superatu (a norma di fondo hè calculata automaticamente), i sviluppatori sò notificati via u microserviziu Notify. Se dopu à 5 minuti u sviluppatore ùn hà micca rispostu (cliccatu Revert or Stay), allora un rollback automaticu di i casi canarii hè lanciatu. Se u sfondate ùn hè micca superatu, allora u sviluppatore deve lancià manualmente l'implementazione di u compitu in Produzione (cliccate un buttone in l'UI). Se in 60 minuti u sviluppatore ùn hà micca lanciatu l'implementazione à a Produzione, allora l'istanze canarie seranu ancu annullate per ragioni di sicurezza.
11. Dopu avè lanciatu a implementazione à a Produzione:
- U compitu hè trasferitu à u statutu di Produzione (microservice Jira).
- U microserviziu Jenkins principia u prucessu di implementazione è notifica à u microserviziu DeployWatch nantu à a implementazione.
- U microserviziu DeployWatch verifica chì tutti i cuntenituri nantu à a Produzione sò stati aghjurnati (ci sò stati casi quandu micca tutti sò stati aghjurnati).
- Per mezu di u microserviziu Notify, una notificazione nantu à i risultati di a implementazione hè mandata à Produzione.
12. I sviluppatori averebbenu 30 minuti per cumincià à ritruvà un compitu da a Produzione se un comportamentu di microserviziu incorrectu hè rilevatu. Dopu stu tempu, u compitu serà automaticamente unitu in maestru (microservice Git).
13. Dopu à una fusione successu in u maestru, u statutu di u compitu serà cambiatu in Closed (Jira microservice).
U diagramma ùn pretende micca esse cumpletamente detallatu (in realtà ci sò ancu più passi), ma permette di valutà u gradu di integrazione in i prucessi. Ùn cunsideremu micca stu schema ideale è migliurà i prucessi di liberazione automatica è supportu di implementazione.
Chì vene
Avemu grandi piani per u sviluppu di l'automatizazione, per esempiu, l'eliminazione di l'operazioni manuali durante e versioni di monoliti, a migliurà a monitorizazione durante l'implementazione automatica, è a migliurà l'interazzione cù i sviluppatori.
Ma fermemu quì per avà. Avemu cupertu assai temi in a rivista di l'automatizazione superficialmente, alcuni ùn sò micca stati toccu in tuttu, cusì seremu felici di risponde à e dumande. Aspittemu suggerimenti nantu à ciò chì copre in dettagliu, scrivite in i cumenti.
Source: www.habr.com