Mula sa mga script hanggang sa sarili naming platform: kung paano namin na-automate ang pag-develop sa CIAN

Mula sa mga script hanggang sa sarili naming platform: kung paano namin na-automate ang pag-develop sa CIAN

Sa RIT 2019, ginawa ng aming kasamahan na si Alexander Korotkov ulat tungkol sa automation ng development sa CIAN: para gawing simple ang buhay at trabaho, ginagamit namin ang sarili naming platform ng Integro. Sinusubaybayan nito ang siklo ng buhay ng mga gawain, pinapaginhawa ang mga developer ng mga nakagawiang operasyon at makabuluhang binabawasan ang bilang ng mga bug sa produksyon. Sa post na ito, pupunuin namin ang ulat ni Alexander at sasabihin sa iyo kung paano kami nagmula sa mga simpleng script hanggang sa pagsasama-sama ng mga open source na produkto sa pamamagitan ng sarili naming platform at kung ano ang ginagawa ng aming hiwalay na automation team.
 

Zero level

"Walang bagay na zero level, hindi ko alam ang ganoong bagay"
Master Shifu mula sa pelikulang "Kung Fu Panda"

Nagsimula ang automation sa CIAN 14 na taon pagkatapos maitatag ang kumpanya. Sa oras na iyon mayroong 35 katao sa pangkat ng pag-unlad. Mahirap paniwalaan, tama ba? Siyempre, umiral ang automation sa ilang anyo, ngunit nagsimulang magkaroon ng hiwalay na direksyon para sa tuluy-tuloy na pagsasama at paghahatid ng code noong 2015. 

Noong panahong iyon, mayroon kaming malaking monolith ng Python, C# at PHP, na na-deploy sa mga server ng Linux/Windows. Upang i-deploy ang halimaw na ito, mayroon kaming isang set ng mga script na manu-mano naming pinapatakbo. Nagkaroon din ng pagpupulong ng monolith, na nagdala ng sakit at pagdurusa dahil sa mga salungatan kapag pinagsama ang mga sanga, pagwawasto ng mga depekto, at muling pagtatayo "na may ibang hanay ng mga gawain sa pagtatayo." Ang isang pinasimple na proseso ay ganito ang hitsura:

Mula sa mga script hanggang sa sarili naming platform: kung paano namin na-automate ang pag-develop sa CIAN

Hindi kami natuwa dito, at gusto naming bumuo ng isang nauulit, awtomatiko at napapamahalaang proseso ng pagbuo at pag-deploy. Para dito, kailangan namin ng CI/CD system, at pumili kami sa pagitan ng libreng bersyon ng Teamcity at ng libreng bersyon ng Jenkins, dahil nagtrabaho kami sa kanila at pareho kaming nababagay sa mga tuntunin ng hanay ng mga function. Pinili namin ang Teamcity bilang isang mas kamakailang produkto. Sa oras na iyon, hindi pa kami gumagamit ng microservice architecture at hindi inaasahan ang isang malaking bilang ng mga gawain at proyekto.

Dumating tayo sa ideya ng sarili nating sistema

Ang pagpapatupad ng Teamcity ay nag-alis lamang ng bahagi ng manu-manong gawain: ang natitira ay ang paggawa ng Mga Pull Request, pag-promote ng mga isyu ayon sa status sa Jira, at pagpili ng mga isyu para sa pagpapalabas. Hindi na ito nakayanan ng sistema ng Teamcity. Kinakailangang piliin ang landas ng karagdagang automation. Isinaalang-alang namin ang mga opsyon para sa pagtatrabaho sa mga script sa Teamcity o paglipat sa mga third-party na automation system. Ngunit sa huli, napagpasyahan namin na kailangan namin ng maximum na kakayahang umangkop, na tanging ang sarili naming solusyon ang makakapagbigay. Ito ay kung paano lumitaw ang unang bersyon ng panloob na sistema ng automation na tinatawag na Integro.

Nakikitungo ang Teamcity sa automation sa antas ng paglulunsad ng mga proseso ng build at deployment, habang ang Integro ay nakatuon sa top-level na automation ng mga proseso ng pag-develop. Kinailangan na pagsamahin ang trabaho sa mga isyu sa Jira sa pagproseso ng nauugnay na source code sa Bitbucket. Sa yugtong ito, nagsimula ang Integro na magkaroon ng sarili nitong mga daloy ng trabaho para sa pagtatrabaho sa mga gawain ng iba't ibang uri. 

Dahil sa pagtaas ng automation sa mga proseso ng negosyo, tumaas ang bilang ng mga proyekto at tumatakbo sa Teamcity. Kaya dumating ang isang bagong problema: hindi sapat ang isang libreng halimbawa ng Teamcity (3 ahente at 100 proyekto), nagdagdag kami ng isa pang pagkakataon (3 higit pang ahente at 100 proyekto), pagkatapos ay isa pa. Bilang resulta, napunta kami sa isang sistema ng ilang mga kumpol, na mahirap pangasiwaan:

Mula sa mga script hanggang sa sarili naming platform: kung paano namin na-automate ang pag-develop sa CIAN

Nang lumitaw ang tanong tungkol sa isang ika-4 na pagkakataon, napagtanto namin na hindi namin maaaring magpatuloy na mamuhay nang ganito, dahil ang kabuuang gastos sa pagsuporta sa 4 na pagkakataon ay wala na sa anumang limitasyon. Ang tanong ay lumitaw tungkol sa pagbili ng bayad na Teamcity o pagpili ng libreng Jenkins. Gumawa kami ng mga kalkulasyon sa mga pagkakataon at mga plano sa pag-automate at nagpasya na mabubuhay kami sa Jenkins. Pagkalipas ng ilang linggo, lumipat kami sa Jenkins at inalis ang ilan sa sakit ng ulo na nauugnay sa pagpapanatili ng maraming pagkakataon sa Teamcity. Samakatuwid, nagawa naming tumuon sa pagbuo ng Integro at pag-customize ng Jenkins para sa aming sarili.

Sa paglaki ng pangunahing automation (sa anyo ng awtomatikong paglikha ng Mga Kahilingan sa Paghila, pagkolekta at paglalathala ng saklaw ng Code at iba pang mga pagsusuri), mayroong matinding pagnanais na iwanan ang mga manu-manong paglabas hangga't maaari at ibigay ang gawaing ito sa mga robot. Bilang karagdagan, nagsimulang lumipat ang kumpanya sa mga microservice sa loob ng kumpanya, na nangangailangan ng madalas na pagpapalabas, at hiwalay sa isa't isa. Ganito kami unti-unting nakarating sa mga awtomatikong paglabas ng aming mga microservice (kasalukuyan naming inilalabas ang monolith nang manu-mano dahil sa pagiging kumplikado ng proseso). Ngunit, tulad ng karaniwang nangyayari, lumitaw ang isang bagong kumplikado. 

I-automate namin ang pagsubok

Mula sa mga script hanggang sa sarili naming platform: kung paano namin na-automate ang pag-develop sa CIAN

Dahil sa automation ng mga release, bumilis ang mga proseso ng pag-unlad, bahagyang dahil sa paglaktaw ng ilang yugto ng pagsubok. At ito ay humantong sa isang pansamantalang pagkawala ng kalidad. Ito ay tila walang halaga, ngunit kasabay ng pagbilis ng mga paglabas, kinakailangan na baguhin ang pamamaraan ng pagbuo ng produkto. Kinakailangang mag-isip tungkol sa automation ng pagsubok, pag-instill ng personal na responsibilidad (narito, pinag-uusapan natin ang tungkol sa "pagtanggap ng ideya sa ulo", hindi mga multa sa pera) ng developer para sa inilabas na code at mga bug sa loob nito, pati na rin ang desisyon na ilabas/huwag ilabas ang isang gawain sa pamamagitan ng awtomatikong pag-deploy. 

Inaalis ang mga problema sa kalidad, nakarating kami sa dalawang mahahalagang desisyon: nagsimula kaming magsagawa ng pagsubok sa canary at ipinakilala ang awtomatikong pagsubaybay sa background ng error na may awtomatikong tugon sa labis nito. Ang unang solusyon ay naging posible upang makahanap ng mga halatang error bago ang code ay ganap na inilabas sa produksyon, ang pangalawa ay binawasan ang oras ng pagtugon sa mga problema sa produksyon. Ang mga pagkakamali, siyempre, ay nangyayari, ngunit ginugugol natin ang karamihan sa ating oras at pagsisikap hindi sa pagwawasto sa kanila, ngunit sa pagliit ng mga ito. 

Koponan ng Automation

Kasalukuyan kaming may kawani ng 130 developer, at nagpapatuloy kami lumaki. Ang team para sa tuluy-tuloy na pagsasama at paghahatid ng code (mula rito ay tinutukoy bilang ang Deploy and Integration o DI team) ay binubuo ng 7 tao at gumagana sa 2 direksyon: pagbuo ng Integro automation platform at DevOps. 

Ang DevOps ay responsable para sa Dev/Beta environment ng CIAN site, ang Integro environment, tumutulong sa mga developer na malutas ang mga problema at bumuo ng mga bagong diskarte sa pag-scale ng mga environment. Ang direksyon ng pag-unlad ng Integro ay tumatalakay sa mismong Integro at mga kaugnay na serbisyo, halimbawa, mga plugin para sa Jenkins, Jira, Confluence, at bumubuo rin ng mga auxiliary utilities at application para sa mga development team. 

Ang DI team ay nakikipagtulungan sa Platform team, na bumubuo ng arkitektura, mga aklatan, at mga diskarte sa pag-develop sa loob. Kasabay nito, ang sinumang developer sa loob ng CIAN ay maaaring mag-ambag sa automation, halimbawa, gumawa ng micro-automation upang umangkop sa mga pangangailangan ng team o magbahagi ng magandang ideya kung paano pahusayin ang automation.

Layer cake ng automation sa CIAN

Mula sa mga script hanggang sa sarili naming platform: kung paano namin na-automate ang pag-develop sa CIAN

Ang lahat ng mga system na kasangkot sa automation ay maaaring nahahati sa ilang mga layer:

  1. Mga panlabas na system (Jira, Bitbucket, atbp.). Ang mga development team ay nakikipagtulungan sa kanila.
  2. Integro platform. Kadalasan, hindi direktang gumagana ang mga developer dito, ngunit ito ang nagpapanatili sa pagtakbo ng lahat ng automation.
  3. Mga serbisyo sa paghahatid, orkestra at pagtuklas (halimbawa, Jeknins, Consul, Nomad). Sa tulong nila, nagde-deploy kami ng code sa mga server at tinitiyak na gumagana ang mga serbisyo sa isa't isa.
  4. Pisikal na layer (server, OS, kaugnay na software). Gumagana ang aming code sa antas na ito. Maaari itong maging isang pisikal na server o isang virtual (LXC, KVM, Docker).

Batay sa konseptong ito, hinahati namin ang mga lugar ng responsibilidad sa loob ng pangkat ng DI. Ang unang dalawang antas ay nasa lugar ng responsibilidad ng direksyon ng pag-unlad ng Integro, at ang huling dalawang antas ay nasa lugar na ng responsibilidad ng DevOps. Ang paghihiwalay na ito ay nagpapahintulot sa amin na tumuon sa mga gawain at hindi nakakasagabal sa pakikipag-ugnayan, dahil malapit kami sa isa't isa at patuloy na nagpapalitan ng kaalaman at karanasan.

buo

Tumutok tayo sa Integro at magsimula sa stack ng teknolohiya:

  • CentOS 7
  • Docker + Nomad + Consul + Vault
  • Java 11 (ang lumang Integro monolith ay mananatili sa Java 8)
  • Spring Boot 2.X + Spring Cloud Config
  • PostgreSql 11
  • Kuneho MQ 
  • Apache Ignite
  • Camunda (naka-embed)
  • Grafana + Graphite + Prometheus + Jaeger + ELK
  • Web UI: React (CSR) + MobX
  • SSO: Keycloak

Sumusunod kami sa prinsipyo ng microservice development, bagama't mayroon kaming legacy sa anyo ng monolith ng isang maagang bersyon ng Integro. Ang bawat microservice ay tumatakbo sa sarili nitong Docker container, at ang mga serbisyo ay nakikipag-ugnayan sa isa't isa sa pamamagitan ng HTTP requests at RabbitMQ messages. Hinahanap ng mga microservice ang isa't isa sa pamamagitan ng Consul at humiling dito, na nagpapasa ng pahintulot sa pamamagitan ng SSO (Keycloak, OAuth 2/OpenID Connect).

Mula sa mga script hanggang sa sarili naming platform: kung paano namin na-automate ang pag-develop sa CIAN

Bilang isang halimbawa sa totoong buhay, isaalang-alang ang pakikipag-ugnayan kay Jenkins, na binubuo ng mga sumusunod na hakbang:

  1. Ang microservice sa pamamahala ng daloy ng trabaho (mula rito ay tinutukoy bilang ang Flow microservice) ay gustong magpatakbo ng build sa Jenkins. Upang gawin ito, ginagamit niya ang Consul upang mahanap ang IP:PORT ng microservice para sa pagsasama sa Jenkins (mula rito ay tinutukoy bilang Jenkins microservice) at nagpapadala ng asynchronous na kahilingan dito upang simulan ang build sa Jenkins.
  2. Pagkatapos makatanggap ng kahilingan, ang Jenkins microservice ay bumubuo at tumutugon gamit ang isang Job ID, na pagkatapos ay magagamit upang tukuyin ang resulta ng trabaho. Kasabay nito, nati-trigger nito ang build sa Jenkins sa pamamagitan ng REST API na tawag.
  3. Ginagawa ni Jenkins ang build at, pagkatapos makumpleto, nagpapadala ng webhook na may mga resulta ng pagpapatupad sa microservice ng Jenkins.
  4. Ang Jenkins microservice, na natanggap ang webhook, ay bumubuo ng isang mensahe tungkol sa pagkumpleto ng pagpoproseso ng kahilingan at inilakip ang mga resulta ng pagpapatupad dito. Ang nabuong mensahe ay ipinadala sa RabbitMQ queue.
  5. Sa pamamagitan ng RabbitMQ, naaabot ng na-publish na mensahe ang Flow microservice, na natututo tungkol sa resulta ng pagproseso ng gawain nito sa pamamagitan ng pagtutugma sa Job ID mula sa kahilingan at sa natanggap na mensahe.

Ngayon ay mayroon na kaming humigit-kumulang 30 microservices, na maaaring hatiin sa ilang grupo:

  1. Pamamahala ng configuration.
  2. Impormasyon at pakikipag-ugnayan sa mga user (mensahero, mail).
  3. Paggawa gamit ang source code.
  4. Pagsasama sa mga tool sa pag-deploy (jenkins, nomad, consul, atbp.).
  5. Pagsubaybay (release, error, atbp.).
  6. Mga kagamitan sa web (UI para sa pamamahala ng mga kapaligiran ng pagsubok, pagkolekta ng mga istatistika, atbp.).
  7. Pagsasama sa mga tagasubaybay ng gawain at mga katulad na sistema.
  8. Pamamahala ng daloy ng trabaho para sa iba't ibang gawain.

Mga gawain sa daloy ng trabaho

Ino-automate ng Integro ang mga aktibidad na nauugnay sa lifecycle ng gawain. Sa pinasimpleng mga termino, ang ikot ng buhay ng isang gawain ay mauunawaan bilang ang daloy ng trabaho ng isang gawain sa Jira. Ang aming mga proseso ng pag-unlad ay may ilang mga pagkakaiba-iba ng daloy ng trabaho depende sa proyekto, ang uri ng gawain at ang mga opsyon na pinili sa isang partikular na gawain. 

Tingnan natin ang daloy ng trabaho na pinakamadalas nating ginagamit:

Mula sa mga script hanggang sa sarili naming platform: kung paano namin na-automate ang pag-develop sa CIAN

Sa diagram, ang gear ay nagpapahiwatig na ang paglipat ay awtomatikong tinatawag ng Integro, habang ang figure ng tao ay nagpapahiwatig na ang paglipat ay tinatawag na manu-mano ng isang tao. Tingnan natin ang ilang mga landas na maaaring gawin ng isang gawain sa daloy ng trabaho na ito.

Ganap na manu-manong pagsubok sa DEV+BETA nang walang mga canary test (karaniwan ay ganito ang paglalabas namin ng monolith):

Mula sa mga script hanggang sa sarili naming platform: kung paano namin na-automate ang pag-develop sa CIAN

Maaaring may iba pang kumbinasyon ng paglipat. Minsan ang landas na tatahakin ng isang isyu ay maaaring piliin sa pamamagitan ng mga opsyon sa Jira.

Paggalaw ng gawain

Tingnan natin ang mga pangunahing hakbang na ginagawa kapag gumagalaw ang isang gawain sa daloy ng trabaho na β€œDEV Testing + Canary Tests”:

1. Ginagawa ng developer o PM ang gawain.

2. Ginagawa ng developer ang gawain upang gumana. Pagkatapos makumpleto, lilipat ito sa status na IN REVIEW.

3. Nagpapadala si Jira ng Webhook sa microservice ng Jira (responsable para sa pagsasama sa Jira).

4. Ang Jira microservice ay nagpapadala ng kahilingan sa Flow service (responsable para sa mga panloob na daloy ng trabaho kung saan isinasagawa ang trabaho) upang simulan ang workflow.

5. Sa loob ng serbisyo ng Daloy:

  • Ang mga reviewer ay itinalaga sa gawain (Mga user microservice na nakakaalam ng lahat tungkol sa mga user + Jira microservice).
  • Sa pamamagitan ng Source microservice (alam nito ang tungkol sa mga repository at branch, ngunit hindi gumagana sa mismong code), isang paghahanap para sa mga repository na naglalaman ng isang sangay ng aming isyu (upang gawing simple ang paghahanap, ang pangalan ng branch ay tumutugma sa isyu numero sa Jira). Kadalasan, ang isang gawain ay may isang sangay lamang sa isang repositoryo; pinapasimple nito ang pamamahala ng queue ng deployment at binabawasan ang pagkakakonekta sa pagitan ng mga repositoryo.
  • Para sa bawat nahanap na sangay, ang sumusunod na pagkakasunud-sunod ng mga aksyon ay isinasagawa:

    i) Pag-update ng master branch (Git microservice para sa pagtatrabaho sa code).
    ii) Ang sangay ay hinarangan mula sa mga pagbabago ng developer (Bitbucket microservice).
    iii) Isang Pull Request ang ginawa para sa branch na ito (Bitbucket microservice).
    iv) Isang mensahe tungkol sa isang bagong Pull Request ay ipinadala sa mga chat ng developer (Abisuhan ang microservice para sa pagtatrabaho sa mga notification).
    v) Sinimulan ang pagbuo, pagsubok at pag-deploy ng mga gawain sa DEV (Jenkins microservice para sa pakikipagtulungan kay Jenkins).
    vi) Kung matagumpay na nakumpleto ang lahat ng nakaraang hakbang, ilalagay ng Integro ang Approve nito sa Pull Request (Bitbucket microservice).

  • Hinihintay ng Integro ang Approve in Pull Request mula sa mga itinalagang reviewer.
  • Sa sandaling matanggap na ang lahat ng kinakailangang pag-apruba (kabilang ang mga automated na pagsusuri ay positibong pumasa), ililipat ng Integro ang gawain sa Test on Dev (Jira microservice) status.

6. Sinusuri ng mga tagasubok ang gawain. Kung walang mga problema, ililipat ang gawain sa status na Ready For Build.

7. "Nakikita" ng Integro na ang gawain ay handa na para sa pagpapalabas at sinimulan ang pag-deploy nito sa canary mode (Jenkins microservice). Ang kahandaan para sa pagpapalaya ay tinutukoy ng isang hanay ng mga panuntunan. Halimbawa, ang gawain ay nasa kinakailangang katayuan, walang mga kandado sa iba pang mga gawain, kasalukuyang walang aktibong pag-upload ng microservice na ito, atbp.

8. Ang gawain ay inilipat sa Canary status (Jira microservice).

9. Inilunsad ni Jenkins ang isang deployment task sa pamamagitan ng Nomad sa canary mode (karaniwan ay 1-3 instance) at inaabisuhan ang release monitoring service (DeployWatch microservice) tungkol sa deployment.

10. Kinokolekta ng DeployWatch microservice ang background ng error at tumutugon dito, kung kinakailangan. Kung lumampas ang background ng error (awtomatikong kinakalkula ang pamantayan sa background), aabisuhan ang mga developer sa pamamagitan ng Notify microservice. Kung pagkatapos ng 5 minuto ay hindi tumugon ang developer (na-click ang Ibalik o Manatili), pagkatapos ay isang awtomatikong rollback ng mga canary instance ay ilulunsad. Kung hindi lalampas ang background, dapat manu-manong ilunsad ng developer ang deployment ng gawain sa Production (sa pamamagitan ng pag-click sa isang button sa UI). Kung sa loob ng 60 minuto ay hindi nailunsad ng developer ang deployment sa Production, ibabalik din ang mga canary instance para sa mga kadahilanang pangseguridad.

11. Pagkatapos ilunsad ang deployment sa Produksyon:

  • Ang gawain ay inilipat sa katayuan ng Produksyon (Jira microservice).
  • Sinisimulan ng Jenkins microservice ang proseso ng deployment at inaabisuhan ang DeployWatch microservice tungkol sa deployment.
  • Tinitingnan ng DeployWatch microservice na na-update na ang lahat ng container sa Production (may mga kaso kung kailan hindi lahat ay na-update).
  • Sa pamamagitan ng Notify microservice, ang isang notification tungkol sa mga resulta ng deployment ay ipinapadala sa Production.

12. Ang mga developer ay magkakaroon ng 30 minuto upang simulan ang pagbabalik ng isang gawain mula sa Production kung may matukoy na maling gawi sa microservice. Pagkatapos ng panahong ito, ang gawain ay awtomatikong isasama sa master (Git microservice).

13. Pagkatapos ng matagumpay na pagsasama sa master, ang katayuan ng gawain ay mapapalitan sa Sarado (Jira microservice).

Ang diagram ay hindi nagpapanggap na ganap na detalyado (sa katotohanan ay may higit pang mga hakbang), ngunit pinapayagan ka nitong masuri ang antas ng pagsasama sa mga proseso. Hindi namin itinuturing na perpekto ang scheme na ito at pinapabuti namin ang mga proseso ng awtomatikong pagpapalabas at suporta sa pag-deploy.

kung ano ang susunod

Mayroon kaming malalaking plano para sa pagbuo ng automation, halimbawa, pag-aalis ng mga manual na operasyon sa panahon ng mga monolith release, pagpapabuti ng pagsubaybay sa panahon ng awtomatikong pag-deploy, at pagpapabuti ng pakikipag-ugnayan sa mga developer.

Ngunit huminto tayo dito sa ngayon. Sinasaklaw namin ang maraming paksa sa pagsusuri ng automation nang mababaw, ang ilan ay hindi nahawakan, kaya ikalulugod naming sagutin ang mga tanong. Naghihintay kami ng mga mungkahi sa kung ano ang sasaklawin nang detalyado, isulat sa mga komento.

Pinagmulan: www.habr.com

Magdagdag ng komento