Pidev juurutamine (CD) on tava uue koodi automaatselt tootmisse juurutada. Enamik pideva juurutamise süsteeme kinnitab, et kasutatav kood on elujõuline, käivitades üksuse ja funktsionaalsed testid, ja kui kõik tundub hea, juurutatakse juurutamine. Levitamine toimub tavaliselt etapiviisiliselt, et oleks võimalik taastada, kui kood ei käitu ootuspäraselt.
Blogipostitustest pole puudust selle kohta, kuidas rakendada oma CD-ga torujuhet mitmesuguste tööriistade abil, nagu AWS-i virn, Google Cloudi virn, Bitbucketi torujuhe jne. Kuid leian, et enamik neist ei sobi minu ettekujutusega hea CD-ga peaks välja nägema selline: mis ehitab esimesena ning testib ja juurutab ainult seda ühte ehitatud faili.
Selles artiklis kavatsen ehitada sündmustepõhise pideva kasutuselevõtu torujuhtme, mis ehitab kõigepealt üles ja seejärel testib meie juurutamise lõplikku artefakti. See mitte ainult ei muuda meie testitulemusi usaldusväärsemaks, vaid muudab CD-gaasijuhtme hõlpsasti laiendatavaks. See näeks välja umbes selline:
Selles artiklis eeldatakse vähemalt Kubernetese ja konteinerite tehnoloogia mööduvat tundmist, kuid kui te pole tuttav või võiksite kasutada värskendust, vaadake Mis on Kubernetes? Konteinerite ja kasutuselevõtu juhend .
Siin on minu probleem enamiku CD-ga seotud torujuhtmetega: tavaliselt teevad nad kõik faili järk. Enamikul ajaveebipostitustest, mida olen selle kohta lugenud, on mõni järgneva järjestuse variatsioon mis tahes ehitusfailis, mis neil on (cloudbuild.yaml
Google Cloud Buildi jaoks, bitbucket-pipeline.yaml
Bitbucketi jaoks).
Tehes asju selles järjekorras, käivitate oma testid. Kui need on edukad, siis ehitate pildi ja jätkate ülejäänud torujuhtmega. Mis juhtub, kui koostamisprotsess muutis teie pilti nii, et testid enam ei läbiks? Minu arvates peaksite alustama artefakti (lõpliku konteineripildi) tootmisest ja see artefakt ei tohiks muutuda ehitamise ja tootmisse juurutamise aja vahel. See tagab, et teie andmed nimetatud eseme kohta (testitulemused, suurus jne) on alati õiged.
Kasutades oma ehituskeskkonda pildi juurutamiseks tootmiskogusse, lubate sellel tõhusalt oma tootmiskeskkonda muuta. Ma arvan, et see on väga halb asi, sest kõik, kellel on teie allikahoidlale kirjutusjuurdepääs, saavad nüüd teie tootmiskeskkonnas teha kõike, mida soovivad.
Kui viimane etapp ebaõnnestub (näiteks mandaadiprobleemi tõttu), peate kogu oma gaasijuhtme uuesti käivitama, võttes aega ja muid ressursse, mida võiks paremini kulutada millegi muu tegemiseks.
See viib mind oma viimase punktini:
Üldisemas mõttes võimaldab iseseisvate sammude olemasolu teie gaasijuhtmel olla suurem paindlikkus. Oletame, et soovite torujuhtmele lisada funktsionaalseid katseid. Kui olete oma sammud ühes järgmises failis, peate oma ehitamiskeskkonna üles töötama funktsionaalse testikeskkonna ja käivitama selles testid (kõige tõenäolisemalt järjestikku). Kui teie sammud oleksid sõltumatud, võite lasta nii oma üksuse testid kui ka funktsionaalsed testid alguse „pildi ehitamise” sündmusega. Seejärel jookseksid nad paralleelselt omaenda keskkonnas.
Minu arvates oleks parem viis sellele probleemile läheneda, kui ürituste mehhanismiga on ühendatud rida sõltumatuid samme.
Sellel on eelmise meetodiga võrreldes mitmeid eeliseid:
Nagu eespool öeldud, avaldaks uue kuvandi edukas loomine lihtsalt 'eduka ehitamise' ürituse. Selle sündmuse käivitamisel võime omakorda lasta mitu asja käivitada. Meie puhul alustaksime seadme ja funktsionaalsuse teste. Võite mõelda ka sellistele asjadele nagu arendaja teavitamine ebaõnnestunud järk-järgulise sündmuse käivitamise korral või kui testid ei läbi.
Tehes iga sammu oma keskkonnas, eemaldame vajaduse, et kõik õigused oleksid ühes keskkonnas. Nüüd saab ehituskeskkond ehitada ainult, testimiskeskkond saab testida ja juurutuskeskkond saab ainult juurutada. See võimaldab teil olla kindel, et kui teie pilt on üles ehitatud, ei muutu see. Toodetud artefakt satub teie toodangu virna. See võimaldab ka hõlpsamalt kontrollida, milline teie torujuhtme etapp mida teeb, kuna saate ühe mandaadi komplekti ühe sammuga linkida.
Kas soovite kellelegi eduka järgu kohta meili saata? Lisage lihtsalt midagi, mis sellele sündmusele reageerib ja e-kirja saadab. See on lihtne - te ei pea oma ehituskoodi muutma ega pea oma allikahoidlas kellegi e-posti kodeerima.
Iseseisvate sammude olemasolu tähendab ka seda, et kui üks samm ebaõnnestub, ei pea te kogu gaasijuhet taaskäivitama. Kui ebaõnnestumise tingimus on ajutine või on käsitsi parandatud, võite lihtsalt nurjunud toimingut uuesti proovida. See võimaldab tõhusamat torujuhet. Kui koostamisetapp võtab mitu minutit, on hea, kui te ei pea pilti uuesti üles ehitama lihtsalt sellepärast, et unustasite anda oma juurutuskeskkonnale klastrile kirjutusõiguse.
Google Cloud Platformil on olemas kõik tööriistad, mis on vajalikud sellise süsteemi lühikese aja jooksul ja väga väikese koodiga ülesehitamiseks.
Meie testirakendus on lihtne kolvirakendus, mis serveerib lihtsalt tükki staatilist teksti. See rakendus on juurutatud Kubernetese klastrisse, mis teenindab seda laiemas Internetis.
Rakendan varem tutvustatud torujuhtme lihtsustatud versiooni. Põhimõtteliselt eemaldasin katsesammud, nii et see näeb nüüd välja selline:
Siin on meie torujuhtme graafiline esitus.
Vool on järgmine:
Meie lähtekood on väga lihtne kolbirakendus, mis lihtsalt teenib mõnda staatilist teksti. Siin on meie projekti ülesehitus:
├── docker │ ├── Dockerfile │ └── uwsgi.ini ├── k8s │ ├── deployment.yaml │ └── service.yaml ├── LICENSE ├── Pipfile ├── Pipfile.lock └── src └── main.py
Dockeri kataloog sisaldab kõike, mida on vaja Dockeri pildi loomiseks. Pilt põhineb pildil uWSGI ja Nginx pilt ja lihtsalt installib sõltuvused ja kopeerib rakenduse õigele teele.
K8s kataloog sisaldab Kubernetes seadistust. See koosneb ühest teenusest ja ühest juurutusest. Juurutamine käivitab ühe konteineri, mis põhineb sellest ehitatud pildil Dockerfile . Seejärel käivitab teenus avaliku IP-aadressiga koormuse tasakaalustaja ja suunab rakenduse konteinerisse.
Pilvehituse konfigureerimise saab ise teha pilvekonsooli või Google Cloudi käsurea kaudu. Valisin pilvekonsooli kasutamise.
Siin ehitame pildi mis tahes filiaali mis tahes pühendumuse jaoks, kuid teil võib olla näiteks Dev ja tootmise jaoks erinevad pildid.
Kui järk on edukas, avaldab pilvehaldus pildi konteinerregistris iseseisvalt. Seejärel avaldab see sõnumi pilve ehitava pubi / alamteemale.
Pilvehitis avaldab sõnumeid ka siis, kui järk on pooleli ja kui see ebaõnnestub, nii et võite ka neil sõnumitel reageerida.
Pilvehituse pubi / alamteatiste dokumentatsioon on siin ja teate vormingu leiate siin
kuidas angularjsiga alustada
Kui vaatate pilvekonsooli pilvepubis / alamvahekaardil, näete, et pilveehitus on loonud teema nimega pilverakendused. Siin avaldab pilvehitis oma olekuvärskendused.
Nüüd teeme pilvefunktsiooni loomise, mis käivitatakse kõigi pilveehituste teemal avaldatud sõnumite puhul. Jällegi võite kasutada kas pilvekonsooli või Google Cloudi käsurea utiliiti. Minu puhul tegin seda, et kasutan pilvefaili pilvefunktsiooni juurutamiseks iga kord, kui selles toimuvad muudatused.
Pilvefunktsiooni lähtekood on siin .
Vaatame kõigepealt koodi, mis selle pilvefunktsiooni juurutab:
steps: - name: 'gcr.io/cloud-builders/gcloud' id: 'test' args: ['functions', 'deploy', 'new-image-trigger', '--runtime=python37', '--trigger-topic=cloud-builds', '--entry-point=onNewImage', '--region=us-east1', '--source=https://source.developers.google.com/projects/$PROJECT_ID/repos/$REPO_NAME']
Siin kasutame Google Cloud Dockeri pilti. See võimaldab hõlpsalt käivitada GCcloudi käske. See, mida me täidame, on samaväärne järgmise käsu käivitamisega otse terminalist:
gcloud functions deploy new-image-trigger --runtime=python37 --trigger-topic=cloud-builds --entry-point=onNewImage --region=us-east1 --source=https://source.developers.google.com/projects/$PROJECT_ID/repos/$REPO_NAME
Palume Google Cloudil juurutada uus pilvefunktsioon (või asendada, kui selles piirkonnas selle nimega funktsioon juba olemas on), mis kasutab käitusaega Python 3.7 ja käivitatakse uute sõnumitega pilveehituse teemas. Samuti ütleme Google'ile, kust selle funktsiooni lähtekoodi leida (siin on PROJECT_ID ja REPO_NAME keskkonnamuutujad, mis määratakse koostamise käigus). Samuti ütleme talle, millist funktsiooni sisestuspunktiks kutsuda.
Vahemärkusena tuleb öelda, et selle toimimiseks peate oma cloudbuildi teenuse kontole andma nii pilvefunktsioonide arendaja kui ka teenuskonto kasutaja, et see saaks pilvefunktsiooni juurutada.
Siin on mõned pilve funktsioonikoodi kommenteeritud jupid
Sisestuspunkti andmed sisaldavad pubi / alamteemal saadud sõnumit.
def onNewImage(data, context):
Esimene samm on selle konkreetse juurutamise muutujate hankimine keskkonnast (need määratlesime pilvekonsooli pilvefunktsiooni muutmisega.
project = os.environ.get('PROJECT') zone = os.environ.get('ZONE') cluster = os.environ.get('CLUSTER') deployment = os.environ.get('DEPLOYMENT') deploy_image = os.environ.get('IMAGE') target_container = os.environ.get('CONTAINER')
Jätame vahele osa, kus kontrollime, kas sõnumi struktuur vastab ootustele, ja kinnitame, et koostamine oli edukas ja andis ühe pildiartefakti.
Järgmine samm on veenduda, et loodud pilt oleks see, mida soovime juurutada.
image = decoded_data['results']['images'][0]['name'] image_basename = image.split('/')[-1].split(':')[0] if image_basename != deploy_image: logging.error(f'{image_basename} is different from {deploy_image}') return
Nüüd saame Kubernetese kliendi ja toome juurutamise, mida soovime muuta
v1 = get_kube_client(project, zone, cluster) dep = v1.read_namespaced_deployment(deployment, 'default') if dep is None: logging.error(f'There was no deployment named {deployment}') return
Lõpuks lappime juurutamise uue pildiga; Selle rullimise eest hoolitseb Kubernetes.
for i, container in enumerate(dep.spec.template.spec.containers): if container.name == target_container: dep.spec.template.spec.containers[i].image = image logging.info(f'Updating to {image}') v1.patch_namespaced_deployment(deployment, 'default', dep)
See on väga elementaarne näide sellest, kuidas mulle meeldib, et asju kavandatakse CD-ga. Teil võiks olla rohkem samme, lihtsalt muutes seda, mis pubi / alamürituse käivitab.
Näiteks võite käivitada konteineri, mis käivitab pildi sees olevad testid ja avaldab sündmuse edukuse ja teise nurjumise kohta ning reageerida nendele kas värskendades juurutust või hoiatades vastavalt tulemusele.
Meie ehitatud torujuhe on üsna lihtne, kuid võite kirjutada teiste osade jaoks muid pilvefunktsioone (näiteks pilvefunktsioon, mis saadaks meilisõnumi arendajale, kes määras koodi, mis rikkus teie üksuse teste).
Nagu näete, ei saa meie ehituskeskkond meie Kubernetes-klastris midagi muuta ja juurutuskood (pilvefunktsioon) ei saa ehitatud pilti muuta. Meie privileegide eraldamine näeb hea välja ja võime magada kitsalt, teades, et petturitest arendaja ei lase meie tootmisklastrit alla. Samuti saame anda endast rohkem ops-orienteeritud arendajad juurdepääs pilve funktsioonikoodile, et nad saaksid seda parandada või täiustada.
Kui teil on küsimusi, märkusi või parandusi, pöörduge julgelt allpool toodud kommentaaride poole.
Pidev edastamine on tava, mille eesmärk on pakkuda stabiilset tarkvara mis tahes ajahetkel. Pidev juurutamine viib selle sammu edasi ja juurutab nimetatud tarkvara automaatselt (tavaliselt tarkvara teenusena keskkonnas).
Paigaldustorustik on tarkvara kogum, mis võimaldab arendajal minna rakenduse lähtekoodilt tootmises töötava rakenduse juurde. Tavaliselt hõlmab see tarkvara rakenduse loomiseks, testimiseks ja juurutamiseks.
Enamik traditsioonilisi pideva kasutuselevõtu torujuhtmeid tugineb sellele, et kogu teave oleks ühes ja samas kohas, sealhulgas volikirjad, et uus artefakt tootma hakata.
Ideaalis peaksid teie torujuhtme kõik erinevad osad olema sõltumatud ja kasutama teatud tüüpi sündmuste mehhanismi, et alustada sammu, kui eelmine on õnnestunud.