Sa True Engineering, nag-set up kami ng proseso para sa patuloy na paghahatid ng mga update sa mga server ng aming customer at gusto naming ibahagi ang karanasang ito.
Nagsimula kami sa pamamagitan ng pagbuo ng isang online na sistema para sa kliyente at pag-deploy nito sa aming sariling Kubernetes cluster. Ngayon ang aming high-load na solusyon ay lumipat na sa platform ng kliyente, kung saan nag-set up kami ng ganap na automated na proseso ng Continuous Deployment. Pinabilis nito ang aming time-to-market—naghahatid ng mga pagbabago sa kapaligiran ng produksyon.
Sa artikulong ito, sasakupin namin ang lahat ng hakbang na kasangkot sa proseso ng Continuous Deployment (CD), o paghahatid ng mga update sa platform ng customer:
- paano magsisimula ang prosesong ito,
- pag-synchronize sa Git repository ng customer,
- backend at frontend assembly,
- awtomatikong pag-deploy ng application sa kapaligiran ng pagsubok,
- Awtomatikong deployment sa Prod.
Ibabahagi namin ang mga detalye ng pag-setup sa daan.

1. Simulan ang CD
Nagsisimula ang Continuous Deployment sa isang developer na nagtutulak ng mga pagbabago sa release branch ng aming Git repository.
Ang aming aplikasyon ay batay sa isang arkitektura ng microservices, at lahat ng mga bahagi nito ay naka-imbak sa iisang repositoryo. Tinitiyak nito na ang lahat ng mga microservice ay binuo at naka-install, kahit na ang isa sa mga ito ay magbago.
Inayos namin ang aming trabaho sa pamamagitan ng iisang repository para sa ilang kadahilanan:
- Dali ng pag-unlad - ang application ay aktibong binuo, upang maaari mong gamitin ang lahat ng code nang sabay-sabay.
- Tinitiyak ng pinag-isang pipeline ng CI/CD na ang application bilang isang sistema ay pumasa sa lahat ng mga pagsubok at inihahatid sa kapaligiran ng produksyon ng customer.
- Inaalis namin ang pagkalito sa bersyon—hindi namin kailangang magpanatili ng mapa ng mga bersyon ng microservice at ilarawan ang configuration para sa bawat microservice sa mga script ng Helm.
2. Pag-synchronize sa Git source code repository ng customer
Ang mga pagbabagong ginawa ay awtomatikong naka-sync sa Git repository ng kliyente. Ang pagbuo ng application ay na-configure doon, na-trigger pagkatapos ng mga pag-update ng sangay, at isinasagawa din ang pag-deploy sa produksyon. Ang parehong mga proseso ay nangyayari sa loob ng kanilang kapaligiran mula sa Git repository.
Hindi kami direktang makakapagtrabaho sa repository ng kliyente dahil kailangan namin ng sarili naming development at testing environment. Ginagamit namin ang aming sariling Git repository para sa mga layuning ito, na naka-synchronize sa kanila. Sa sandaling itulak ng developer ang mga pagbabago sa naaangkop na sangay ng aming repositoryo, agad na itinutulak ng GitLab ang mga pagbabagong iyon sa kliyente.

Pagkatapos nito, kailangan mong buuin ang app. Binubuo ito ng ilang yugto: backend at frontend assembly, pagsubok, at paghahatid sa produksyon.
3. Pag-assemble ng backend at frontend
Ang backend at frontend build ay dalawang magkatulad na gawain na ginagawa sa GitLab Runner. Ang paunang configuration ng build ay matatagpuan sa parehong repositoryo.
.
Kinukuha ng GitLab Runner ang code mula sa kinakailangang repository, ginagamit ang Java application build command para buuin ito, at itinutulak ito sa Docker registry. Dito, binubuo namin ang backend at frontend, bumubuo ng mga larawan ng Docker, at iniimbak ang mga ito sa repositoryo ng kliyente. Ginagamit namin ang Docker upang pamahalaan ang mga imahe ng Docker. .
Isina-synchronize namin ang aming mga bersyon ng larawan sa bersyon ng paglabas na idi-deploy sa Docker. Para matiyak ang maayos na operasyon, gumawa kami ng ilang pagsasaayos:
1. Hindi itinayong muli ang mga lalagyan sa pagitan ng mga kapaligiran ng pagsubok at produksyon. Nagpatupad kami ng parameterization para gumana ang parehong container sa lahat ng setting, variable ng kapaligiran, at serbisyo sa parehong mga kapaligiran sa pagsubok at produksyon nang hindi muling ginagawa.
2. Upang i-update ang isang application sa pamamagitan ng Helm, kailangan mong tukuyin ang bersyon nito. Para sa amin, ang pagbuo ng backend, frontend, at pag-update ng application ay tatlong magkahiwalay na gawain, kaya mahalagang gamitin ang parehong bersyon ng application sa lahat ng gawain. Para sa gawaing ito, gumagamit kami ng data mula sa kasaysayan ng Git, dahil ang aming K8S cluster configuration at mga application ay matatagpuan sa parehong Git repository.
Nakukuha namin ang bersyon ng application mula sa mga resulta ng pagpapatupad ng command.
git describe --tags --abbrev=7.
4. Awtomatikong pag-deploy ng lahat ng pagbabago sa kapaligiran ng pagsubok (UAT)
Ang susunod na hakbang sa build script na ito ay awtomatikong ina-update ang K8S cluster. Nangyayari ito kapag naitayo na ang buong application at na-publish na ang lahat ng artifact sa Docker Registry. Pagkatapos nito, ina-update ang kapaligiran ng pagsubok.
Nagsimula ang pag-update ng cluster sa Kung ang isang bagay ay hindi mapupunta gaya ng binalak, awtomatiko at independiyenteng ibabalik ng Helm ang lahat ng mga pagbabago nito. Ang operasyon nito ay hindi nangangailangan ng anumang pangangasiwa.
Ipinapadala namin ang configuration ng cluster ng K8S kasama ang build. Samakatuwid, ang susunod na hakbang ay i-update ito: configMaps, deployment, serbisyo, lihim, at anumang iba pang configuration ng K8S na binago namin.
Pagkatapos nito, nagpapatakbo ang Helm ng RollOut update ng mismong application sa kapaligiran ng pagsubok bago ito i-deploy sa produksyon. Ginagawa ito upang manual na masubukan ng mga user ang mga feature ng negosyo na na-deploy namin sa environment ng pagsubok.
5. Awtomatikong i-deploy ang lahat ng pagbabago sa Prod
Para mag-deploy ng update sa production environment, ang kailangan mo lang gawin ay mag-click sa isang button sa GitLab, at ang mga container ay ihahatid kaagad sa production environment.
Ang parehong application ay maaaring tumakbo sa iba't ibang mga kapaligiran-pagsubok at produksyon-nang walang muling pagtatayo. Ginagamit namin ang parehong mga artifact nang hindi binabago ang anumang bagay sa application, at itinakda namin ang mga parameter sa labas.
Ang flexible parameterization ng mga setting ng application ay depende sa kapaligiran kung saan tatakbo ang application. Na-externalize namin ang lahat ng setting ng kapaligiran: ang lahat ay na-parameter sa pamamagitan ng configuration ng K8S at mga Helm na parameter. Kapag nag-deploy ang Helm ng build sa kapaligiran ng pagsubok, inilalapat ang mga parameter ng pagsubok, at sa kapaligiran ng produksyon, inilalapat ang mga parameter ng produksyon.
Ang pinakamahirap na bahagi ay ang pag-parameter ng lahat ng mga serbisyo at variable na ginamit na nakasalalay sa kapaligiran at pagsasalin ng mga ito sa mga variable ng kapaligiran at isang paglalarawan-configuration ng mga parameter ng kapaligiran para sa Helm.
Gumagamit ang mga parameter ng application ng mga variable ng kapaligiran. Nakatakda ang kanilang mga halaga sa mga container gamit ang K8S configmap, na naka-templatize gamit ang mga template ng Go. Halimbawa, ang pagtatakda ng environment variable sa domain name ay maaaring gawin tulad nito:
APP_EXTERNAL_DOMAIN: {{ (pluck .Values.global.env .Values.app.properties.app_external_domain | first) }}
.Values.global.env – iniimbak ng variable na ito ang pangalan ng kapaligiran (prod, stage, UAT).
.Values.app.properties.app_external_domain – sa variable na ito itinakda namin ang gustong domain sa .Values.yaml file
Kapag nag-a-update ng application, gumagawa si Helm ng configmap.yaml file mula sa mga template at nilalagyan ng naaangkop na value ang APP_EXTERNAL_DOMAIN variable depende sa kapaligiran kung saan sinisimulan ang pag-update ng application. Nakatakda na ang variable na ito sa container at naa-access mula sa application mismo, ibig sabihin, magkakaroon ng ibang value ang bawat environment ng application para sa variable na ito.
Kamakailan lamang, nagdagdag ang Spring Cloud ng suporta para sa K8S, kabilang ang suporta para sa configMaps: Habang ang proyekto ay aktibong umuunlad at sumasailalim sa mga makabuluhang pagbabago, hindi namin ito magagamit sa produksyon. Gayunpaman, aktibong sinusubaybayan namin ang status nito at ginagamit ito sa mga configuration ng DEV. Kapag na-stabilize na ito, lilipat tayo mula sa paggamit ng mga variable ng kapaligiran dito.
Sa kabuuan
Kaya, ang Continuous Deployment ay naka-set up at tumatakbo. Ang lahat ng mga update ay nangyayari sa isang solong keystroke. Ang paghahatid ng mga pagbabago sa kapaligiran ng produksyon ay awtomatiko. At, mahalaga, ang mga update ay hindi nakakaabala sa pagpapatakbo ng system.

Mga plano sa hinaharap: awtomatikong paglilipat ng database
Isinasaalang-alang namin ang pag-upgrade ng database at ang kakayahang ibalik ang mga pagbabagong ito. Pagkatapos ng lahat, dalawang magkaibang bersyon ng app ang tumatakbo nang sabay-sabay: ang luma ay tumatakbo, at ang bago ay inilulunsad. Idi-disable lang namin ang lumang bersyon kapag natitiyak namin na gumagana ang bagong bersyon. Dapat payagan ng paglilipat ng database ang parehong bersyon ng app na gumana.
Samakatuwid, hindi lang natin maaaring baguhin ang pangalan ng column o iba pang data. Gayunpaman, maaari tayong gumawa ng bagong column, kopyahin ang data mula sa lumang column papunta dito, at magsulat ng mga trigger na sabay na kokopya at ia-update ang data sa kabilang column kapag na-update ito. Matapos matagumpay na i-deploy ang bagong bersyon ng application, pagkatapos mag-expire ang panahon ng suporta pagkatapos ng paglunsad, maaari naming tanggalin ang lumang column at ang hindi na kailangan na trigger.
Kung ang isang bagong bersyon ng app ay hindi gumagana nang tama, maaari kaming bumalik sa nakaraang bersyon, kabilang ang nakaraang bersyon ng database. Sa madaling salita, ang aming mga pagbabago ay magbibigay-daan sa iyo upang gumana sa maraming bersyon ng app nang sabay-sabay.
Plano naming i-automate ang paglilipat ng database sa pamamagitan ng mga trabaho sa K8S, na isinasama ito sa proseso ng CD. Talagang ibabahagi namin ang karanasang ito sa Habr.
Pinagmulan: www.habr.com
