Fan skripts oant ús eigen platfoarm: hoe't wy ûntwikkeling automatisearje by CIAN

Fan skripts oant ús eigen platfoarm: hoe't wy ûntwikkeling automatisearje by CIAN

By RIT 2019 makke ús kollega Alexander Korotkov melde oer automatisearring fan ûntwikkeling by CIAN: om libben en wurk te ferienfâldigjen, brûke wy ús eigen Integro-platfoarm. It folget de libbenssyklus fan taken, ûntlêst ûntwikkelders fan routine operaasjes en ferminderet it oantal bugs yn produksje signifikant. Yn dizze post sille wy it rapport fan Alexander oanfolje en jo fertelle hoe't wy gongen fan ienfâldige skripts nei it kombinearjen fan iepen boarne produkten fia ús eigen platfoarm en wat ús aparte automatisearringsteam docht.
 

Nul nivo

"D'r is net sa'n ding as in nulnivo, ik wit soks net"
Master Shifu út 'e film "Kung Fu Panda"

Automatisearring by CIAN begon 14 jier nei't it bedriuw waard oprjochte. Op dat stuit sieten der 35 minsken yn it ûntwikkelingsteam. Min te leauwen, krekt? Fansels bestie automatisearring yn ien of oare foarm, mar in aparte rjochting foar trochgeande yntegraasje en koadelevering begon yn 2015 foarm te krijen. 

Op dat stuit hienen wy in enoarme monolith fan Python, C # en PHP, ynset op Linux / Windows-tsjinners. Om dit meunster yn te setten, hienen wy in set skripts dy't wy mei de hân rûnen. D'r wie ek de gearstalling fan 'e monolit, dy't pine en lijen brocht troch konflikten by it fusearjen fan tûken, korrizjearjen fan mankeminten en werbou "mei in oare set fan taken yn' e bou." In ferienfâldige proses seach der sa út:

Fan skripts oant ús eigen platfoarm: hoe't wy ûntwikkeling automatisearje by CIAN

Wy wiene hjir net bliid mei, en wy woenen in werhelle, automatisearre en beheare bouw- en ynsetproses bouwe. Hjirfoar hiene wy ​​in CI / CD-systeem nedich, en wy keas tusken de fergese ferzje fan Teamcity en de fergese ferzje fan Jenkins, om't wy mei har wurken en beide by ús pasten yn termen fan 'e set fan funksjes. Wy hawwe Teamcity keazen as in resint produkt. Op dat stuit hienen wy noch gjin microservice-arsjitektuer brûkt en ferwachten net in grut oantal taken en projekten.

Wy komme by it idee fan ús eigen systeem

De ymplemintaasje fan Teamcity ferwidere mar in diel fan it hânwurk: wat oerbliuwt is it meitsjen fan Pull Requests, promoasje fan problemen troch status yn Jira, en seleksje fan problemen foar frijlitting. It Teamcity-systeem koe dit net mear oan. It wie nedich om it paad fan fierdere automatisearring te kiezen. Wy hawwe opsjes beskôge foar wurkjen mei skripts yn Teamcity of oerskeakelje nei automatisearringssystemen fan tredden. Mar op it lêst hawwe wy besletten dat wy maksimale fleksibiliteit nedich wiene, wat allinich ús eigen oplossing kin leverje. Dit is hoe't de earste ferzje fan it ynterne automatisearringssysteem mei de namme Integro ferskynde.

Teamcity hâldt him dwaande mei automatisearring op it nivo fan it lansearjen fan de bou- en ynsetprosessen, wylst Integro har rjochte op automatisearring op it heechste nivo fan ûntwikkelingsprosessen. It wie nedich om wurk te kombinearjen mei problemen yn Jira mei ferwurking fan assosjearre boarnekoade yn Bitbucket. Op dit stadium begon Integro har eigen workflows te hawwen foar it wurkjen mei taken fan ferskate soarten. 

Troch de tanimming fan automatisearring yn saaklike prosessen is it oantal projekten en runs yn Teamcity tanommen. Sa kaam der in nij probleem: ien fergese Teamcity-eksimplaar wie net genôch (3 aginten en 100 projekten), wy hawwe in oare eksimplaar tafoege (3 mear aginten en 100 projekten), dan noch ien. As gefolch hawwe wy in systeem fan ferskate klusters bedarre, dat lestich te behearjen wie:

Fan skripts oant ús eigen platfoarm: hoe't wy ûntwikkeling automatisearje by CIAN

Doe't de fraach fan in 4e eksimplaar opkaam, realisearren wy dat wy sa net bliuwe koenen, om't de totale kosten fan it stypjen fan 4 ynstânsjes net mear binnen gjin grinzen wiene. De fraach ûntstie oer it keapjen fan betelle Teamcity of it kiezen fan fergese Jenkins. Wy makken berekkeningen op gefallen en automatisearringsplannen en besletten dat wy op Jenkins soene wenje. Nei in pear wiken skeakelen wy oer nei Jenkins en elimineare wat fan 'e hoofdpijn ferbûn mei it behâld fan meardere Teamcity-eksimplaren. Dêrom koenen wy rjochtsje op it ûntwikkeljen fan Integro en it oanpassen fan Jenkins foar ússels.

Mei de groei fan basis automatisearring (yn 'e foarm fan automatyske oanmeitsjen fan Pull Requests, kolleksje en publikaasje fan Code dekking en oare kontrôles), der is in sterke winsk te ferlitten hânmjittich releases safolle mooglik en jou dit wurk oan robots. Derneist begon it bedriuw te ferhúzjen nei mikrotsjinsten binnen it bedriuw, dy't faak útjeften easke, en apart fan elkoar. Dit is hoe't wy stadichoan kamen ta automatyske releases fan ús mikrotsjinsten (wy binne op it stuit de monolith frijlitten troch de kompleksiteit fan it proses). Mar, lykas gewoanlik bart, ûntstie in nije kompleksiteit. 

Wy automatisearje testen

Fan skripts oant ús eigen platfoarm: hoe't wy ûntwikkeling automatisearje by CIAN

Troch de automatisearring fan releases binne ûntwikkelingsprosessen fersneld, foar in part troch it oerslaan fan guon teststadia. En dit late ta in tydlik ferlies fan kwaliteit. It klinkt triviaal, mar tegearre mei de fersnelling fan releases wie it nedich om de metodyk foar produktûntwikkeling te feroarjen. It wie nedich om te tinken oer de automatisearring fan testen, it ynstellen fan persoanlike ferantwurdlikens (hjir prate wy oer "it idee yn 'e holle akseptearje", net monetêre boetes) fan' e ûntwikkelder foar de frijlitten koade en bugs dêryn, lykas it beslút om frijlitte / net frijlitte in taak fia automatyske ynset. 

Eliminearjen fan kwaliteit problemen, wy kamen ta twa wichtige besluten: wy begûn te fieren kanaryske testen en yntrodusearre automatyske tafersjoch op de flater eftergrûn mei in automatyske reaksje op syn oerskot. De earste oplossing makke it mooglik om dúdlike flaters te finen foardat de koade folslein yn produksje waard frijlitten, de twadde fermindere de reaksjetiid op problemen yn produksje. Flaters komme fansels foar, mar wy besteegje de measte fan ús tiid en muoite net oan it korrizjearjen, mar oan it minimalisearjen fan se. 

Automatisearring Team

Wy hawwe op it stuit in personiel fan 130 ûntwikkelders, en wy trochgean groeie. It team foar trochgeande yntegraasje en koadelevering (hjirnei oantsjutten as it Deploy and Integration of DI-team) bestiet út 7 minsken en wurket yn 2 rjochtingen: ûntwikkeling fan it Integro automatisearringsplatfoarm en DevOps. 

DevOps is ferantwurdlik foar de Dev/Beta-omjouwing fan 'e CIAN-side, de Integro-omjouwing, helpt ûntwikkelders problemen op te lossen en ûntwikkelt nije oanpakken foar skaalfermiddens. De Integro-ûntwikkelingsrjochting behannelt sawol Integro sels as relatearre tsjinsten, bygelyks plugins foar Jenkins, Jira, Confluence, en ûntwikkelet ek auxiliary utilities en applikaasjes foar ûntwikkelingsteams. 

It DI-team wurket gear mei it Platform-team, dat de arsjitektuer, biblioteken en ûntwikkelingsbenaderingen yntern ûntwikkelet. Tagelyk kin elke ûntwikkelder binnen CIAN bydrage oan automatisearring, bygelyks mikro-automatisearring meitsje om oan 'e behoeften fan it team te passen of in koel idee te dielen oer hoe't automatisearring noch better kin wurde.

Laachcake fan automatisearring by CIAN

Fan skripts oant ús eigen platfoarm: hoe't wy ûntwikkeling automatisearje by CIAN

Alle systemen belutsen by automatisearring kinne wurde ferdield yn ferskate lagen:

  1. Eksterne systemen (Jira, Bitbucket, ensfh.). Untwikkelingsteams wurkje mei har.
  2. Integro platfoarm. Meastentiids wurkje ûntwikkelders der net direkt mei, mar it is wat alle automatisearring draait.
  3. Tsjinsten foar levering, orkestraasje en ûntdekking (Bygelyks Jeknins, Consul, Nomad). Mei har help sette wy koade yn op servers en soargje derfoar dat tsjinsten mei-inoar wurkje.
  4. Fysike laach (servers, OS, relatearre software). Us koade wurket op dit nivo. Dit kin in fysike tsjinner wêze as in firtuele (LXC, KVM, Docker).

Op grûn fan dit konsept ferdiele wy ferantwurdlikensgebieten binnen it DI-team. De earste twa nivo's binne op it mêd fan ferantwurdlikens fan 'e Integro-ûntwikkelingsrjochting, en de lêste twa nivo's binne al op it mêd fan ferantwurdlikens fan DevOps. Dizze skieding lit ús rjochtsje op taken en interferearje net mei ynteraksje, om't wy tichtby elkoar binne en konstant kennis en ûnderfining útwikselje.

Yntakt

Litte wy rjochtsje op Integro en begjinne mei de technologystack:

  • CentOS 7
  • Docker + Nomad + Konsul + Vault
  • Java 11 (de âlde Integro-monolith sil op Java 8 bliuwe)
  • Spring Boot 2.X + Spring Cloud Config
  • PostgreSql 11
  • Konyn MQ 
  • Apache Ignite
  • Camunda (ynbêde)
  • Grafana + Graphite + Prometheus + Jaeger + ELK
  • Web UI: React (CSR) + MobX
  • SSO: Keycloak

Wy hâlde ús oan it prinsipe fan ûntwikkeling fan mikrotsjinsten, hoewol wy legacy hawwe yn 'e foarm fan in monolith fan in iere ferzje fan Integro. Elke mikrotsjinst rint yn in eigen Docker-kontener, en de tsjinsten kommunisearje mei elkoar fia HTTP-oanfragen en RabbitMQ-berjochten. Mikrotsjinsten fine inoar fia Consul en meitsje in fersyk nei it, trochjaan fan autorisaasje fia SSO (Keycloak, OAuth 2 / OpenID Connect).

Fan skripts oant ús eigen platfoarm: hoe't wy ûntwikkeling automatisearje by CIAN

As in echte foarbyld, beskôgje ynteraksje mei Jenkins, dy't bestiet út de folgjende stappen:

  1. De mikrotsjinst foar workflowbehear (hjirnei oantsjutten as de Flow-mikrotsjinst) wol in build útfiere yn Jenkins. Om dit te dwaan, brûkt hy Consul om de IP: PORT fan 'e mikrotsjinst te finen foar yntegraasje mei Jenkins (hjirnei oantsjutten as Jenkins microservice) en stjoert in asynchrone fersyk nei it om de bou yn Jenkins te begjinnen.
  2. Nei ûntfangst fan in fersyk genereart en reagearret de Jenkins mikroservice mei in Job ID, dy't dan kin wurde brûkt om it resultaat fan it wurk te identifisearjen. Tagelyk triggert it de build yn Jenkins fia in REST API-oprop.
  3. Jenkins fiert de bou út en stjoert nei foltôging in webhook mei de útfieringsresultaten nei de Jenkins mikroservice.
  4. De mikroservice fan Jenkins, nei't de webhook ûntfongen is, genereart in berjocht oer it foltôgjen fan ferwurking fan fersyk en heakket de útfieringsresultaten deroan. It oanmakke berjocht wurdt stjoerd nei de RabbitMQ-wachtrige.
  5. Troch RabbitMQ berikt it publisearre berjocht de Flow-mikroservice, dy't leart oer it resultaat fan it ferwurkjen fan syn taak troch oerien te kommen mei de Job ID fan it fersyk en it ûntfongen berjocht.

No hawwe wy sa'n 30 mikrotsjinsten, dy't kinne wurde ferdield yn ferskate groepen:

  1. Konfiguraasje behear.
  2. Ynformaasje en ynteraksje mei brûkers (boaden, post).
  3. Wurkje mei boarnekoade.
  4. Yntegraasje mei ynset ark (jenkins, nomad, konsul, ensfh.).
  5. Monitoring (releases, flaters, ensfh.).
  6. Web-nutsbedriuwen (UI foar it behearen fan testomjouwings, it sammeljen fan statistiken, ensfh.).
  7. Yntegraasje mei taak trackers en ferlykbere systemen.
  8. Wurkstreambehear foar ferskate taken.

Workflow taken

Integro automatisearret aktiviteiten yn ferbân mei de taaklibbenssyklus. Yn ferienfâldige termen sil de libbenssyklus fan in taak wurde begrepen as de workflow fan in taak yn Jira. Us ûntwikkeling prosessen hawwe ferskate workflow fariaasjes ôfhinklik fan it projekt, it type taak en de opsjes selektearre yn in bepaalde taak. 

Litte wy nei de workflow sjen dy't wy it meast brûke:

Fan skripts oant ús eigen platfoarm: hoe't wy ûntwikkeling automatisearje by CIAN

Yn it diagram jout it gear oan dat de oergong automatysk wurdt neamd troch Integro, wylst de minsklike figuer oanjout dat de oergong manuell troch in persoan neamd wurdt. Litte wy nei ferskate paden sjen dy't in taak kin nimme yn dizze workflow.

Folslein hânmjittich testen op DEV + BETA sûnder kanaryske testen (meastentiids is dit hoe't wy in monolith frijlitte):

Fan skripts oant ús eigen platfoarm: hoe't wy ûntwikkeling automatisearje by CIAN

D'r kinne oare oergongskombinaasjes wêze. Soms kin it paad dat in probleem sil nimme wurde selektearre fia opsjes yn Jira.

Taakbeweging

Litte wy nei de haadstappen sjen dy't wurde útfierd as in taak troch de workflow "DEV Testing + Canary Tests" beweecht:

1. De ûntwikkelder of PM makket de taak.

2. De ûntwikkelder nimt de taak om te wurkjen. Nei foltôging skeakelt it nei IN REVIEW status.

3. Jira stjoert in Webhook nei de Jira mikroservice (ferantwurdlik foar yntegraasje mei Jira).

4. De mikroservice Jira stjoert in fersyk nei de Flow-tsjinst (ferantwurdlik foar ynterne workflows dêr't wurk yn útfierd wurdt) om de workflow te begjinnen.

5. Binnen de Flow tsjinst:

  • Resinsinten wurde tawiisd oan de taak (Microservice fan brûkers dy't alles wit oer brûkers + Jira mikroservice).
  • Troch de boarne-mikrotsjinst (it wit oer repositories en tûken, mar wurket net mei de koade sels), wurdt in syktocht makke nei repositories dy't in tûke fan ús kwestje befetsje (om it sykjen te ferienfâldigjen komt de namme fan 'e tûke gear mei it probleem nûmer yn Jira). Meastentiids hat in taak mar ien tûke yn ien repository; dit ferienfâldigt it behear fan 'e ynsetwachtrige en ferminderet ferbining tusken repositories.
  • Foar elke fûn tûke wurdt de folgjende folchoarder fan aksjes útfierd:

    i) Bywurkjen fan de master branch (Git microservice foar wurkjen mei koade).
    ii) De tûke wurdt blokkearre foar feroaringen troch de ûntwikkelder (Bitbucket microservice).
    iii) In Pull Request wurdt makke foar dizze branch (Bitbucket microservice).
    iv) In berjocht oer in nij Pull Request wurdt stjoerd nei ûntwikkelderschats (Notify microservice foar wurkjen mei notifikaasjes).
    v) Build, test en ynsette taken wurde begûn op DEV (Jenkins microservice foar wurkjen mei Jenkins).
    vi) As alle foargeande stappen mei sukses foltôge binne, set Integro syn goedkarring yn 'e Pull Request (Bitbucket microservice).

  • Integro wachtet op Approve in Pull Request fan oanwiisde resinsinten.
  • Sadree't alle nedige goedkarring binne ûntfongen (ynklusyf automatisearre tests binne posityf trochjûn), draacht Integro de taak oer nei Test on Dev (Jira microservice) status.

6. Testers test de taak. As d'r gjin problemen binne, dan wurdt de taak oerbrocht nei de status Ready For Build.

7. Integro "sjocht" dat de taak is klear foar frijlitting en begjint syn ynset yn kanaryske modus (Jenkins microservice). Reewilligens foar frijlitting wurdt bepaald troch in set regels. Bygelyks, de taak is yn 'e fereaske status, d'r binne gjin slûzen op oare taken, d'r binne op it stuit gjin aktive uploads fan dizze mikrotsjinst, ensfh.

8. De taak wurdt oerdroegen oan Kanaryske status (Jira microservice).

9. Jenkins lansearret in ynset taak fia Nomad yn kanaryske modus (meastentiids 1-3 eksimplaren) en notify de release monitoring tsjinst (DeployWatch microservice) oer de ynset.

10. De mikroservice DeployWatch sammelet de flatereftergrûn en reagearret dêrop, as it nedich is. As de flater eftergrûn wurdt oerskreden (de eftergrûn noarm wurdt automatysk berekkene), ûntwikkelders wurde op 'e hichte fia de Notify microservice. As nei 5 minuten de ûntwikkelder net hat reagearre (klikke op Weromsette of Bliuw), dan wurdt in automatysk weromdraaien fan 'e kanaryske eksimplaren lansearre. As de eftergrûn net wurdt oerskreaun, dan moat de ûntwikkelder de taakynset manuell starte nei produksje (troch op in knop te klikken yn 'e UI). As binnen 60 minuten de ûntwikkelder de ynset foar produksje net hat lansearre, dan wurde de kanaryske eksimplaren ek weromdraaid om feiligensredenen.

11. Nei it lansearjen fan de ynset nei produksje:

  • De taak wurdt oerdroegen oan Production status (Jira microservice).
  • De Jenkins-mikrotsjinst begjint it ynsetproses en meldt de DeployWatch-mikrotsjinst oer de ynset.
  • De mikroservice DeployWatch kontrolearret dat alle konteners op produksje binne bywurke (d'r wiene gefallen dat net allegear waarden bywurke).
  • Fia de Notify-mikroservice wurdt in notifikaasje oer de resultaten fan de ynset stjoerd nei Production.

12. Untwikkelders sille 30 minuten hawwe om in taak werom te rôljen fan Produksje as ferkeard mikroservicegedrach wurdt ûntdutsen. Nei dizze tiid sil de taak automatysk wurde gearfoege yn master (Git microservice).

13. Nei in suksesfolle fúzje yn master, wurdt de taakstatus feroare nei Closed (Jira microservice).

It diagram docht net as folslein detaillearre (yn werklikheid binne d'r noch mear stappen), mar it makket it mooglik om de mjitte fan yntegraasje yn prosessen te beoardieljen. Wy beskôgje dit skema net ideaal en ferbetterje de prosessen fan automatyske frijlitting en ynsetstipe.

Wat is hjirnei

Wy hawwe grutte plannen foar de ûntwikkeling fan automatisearring, bygelyks it eliminearjen fan hânmjittige operaasjes tidens monolith-releases, ferbetterjen fan tafersjoch by automatyske ynset, en ferbetterjen fan ynteraksje mei ûntwikkelders.

Mar lit ús hjir foar no ophâlde. Wy hawwe in protte ûnderwerpen yn 'e automatisearring oersicht oerflakkich behannele, guon waarden hielendal net oanrekke, dus wy sille graach fragen beantwurdzje. Wy wachtsje op suggestjes oer wat te dekken yn detail, skriuw yn 'e kommentaren.

Boarne: www.habr.com

Add a comment