Kaj je GitOps?

Op. prev.: Po nedavni objavi gradiva o metodah pull in push v GitOps smo opazili zanimanje za ta model kot celoto, vendar je bilo v slovenščini objav na to temo zelo malo (na Habu sploh ni). Zato z veseljem ponujamo vašemuu vidiku prevod drugega članka — čeprav je skoraj eno leto star! — podjetja Weaveworks, katerega vodja je skoval izraz 'GitOps'. V besedilu so pojasnjeni bistvo pristopa in ključne razlike od obstoječih.

Pred letom dni smo objavili uvod v GitOps. Takrat smo opisali, kako je ekipa Weaveworks zagnala SaaS, popolnoma temelječ na Kubernetes, ter razvila nabor priporočenih najboljših praks za uvajanje, upravljanje in spremljanje v okolju cloud native.

Članek je bil priljubljen. Drugi so začeli govoriti o GitOpsu, objavljali nove pripomočke za git push, razvoj, skrivnosti, funkcij, neprekinjene integracije itd. Na naši spletni strani se je pojavilo veliko število objav in primerov uporabe GitOps. Vendar pa so nekateri ljudje imeli še vedno vprašanja. Kako se model razlikuje od tradicionalne infrastructure as code in neprekinjene dostave (continuous delivery)? Je nujno uporabljati Kubernetes?

Kmalu smo spoznali, da je potrebno novo opisovanje, ki ponuja:

  1. Veliko primerov in zgodb;
  2. Konkreten opis GitOps;
  3. Primerjavo s tradicionalno neprekinjeno dostavo.

V tem članku smo poskušali zajeti vse te teme. V njem boste našli posodobljen uvod v GitOps in pogled nanj z vidika razvijalcev in CI/CD. Prevladujoče se osredotočamo na Kubernetes, vendar se model lahko povsem posploši.

Spoznajte: GitOps

Predstavljajte si Aliso. Upravljala bo podjetjem Family Insurance, ki nudi zavarovalne police za zdravje, avtomobile, nepremičnine in potovanj zavarovanja ljudem, ki so preveč zaposleni, da bi se sami ukvarjali s podrobnostmi pogodb. Njen posel se je začel kot stranski projekt, ko je Alisa delala v banki kot podatkovna znanstvenica. Nekega dne je spoznala, da lahko uporabi napredne računalniške algoritem za učinkovitejšo analizo podatkov in oblikovanje zavarovalnih paketov. Investitorji so financirali projekt, in zdaj njeno podjetje prinaša več kot 20 milijonov dolarjev na leto in hitro raste. Trenutno zaposluje 180 ljudi na različnih delovnih mestih. Med njimi je tehnološka ekipa, ki skrbi za razvoj, vzdrževanje spletne strani, baze podatkov in analizo strank. Ekipo, ki jo sestavlja 60 ljudi, vodi Bob — tehnični direktor podjetja.

Bobova ekipa uvaja produkcijske sisteme v oblaku. Njihove glavne aplikacije delujejo na GKE in izkoriščajo prednosti Kubernetes v Google Cloud. Poleg tega pri svojem delu uporabljajo različna orodja za obdelavo podatkov in analitiko.

Family Insurance sprva ni nameravala uporabljati kontejnerjev, a je bila navdušena nad Dockerjem. Kmalu so strokovnjaki podjetja odkrili, da GKE omogoča enostavno in brezskrbno uvajanje klastra za testiranje novih funkcij. Dodali so Jenkins za CI in Quay za organizacijo registra kontejnerjev ter napisali skripte za Jenkins, ki so potisnile nove kontejnerje in konfiguracije v GKE.

Čas je minil. Alisa in Bob sta bila razočarana nad učinkovitostjo izbranega pristopa in njegovim vplivom na posel. Uvajanje kontejnerjev ni povečalo uspešnosti toliko, kolikor je ekipa upala. Včasih so se deploymenti sesuli in ni bilo jasno, ali so krivi spremembe kode. Prav tako je bilo težko spremljati spremembe nastavitev. Pogosto so morali ustvariti nov klaster in preseliti vanj aplikacije, saj je bilo to najlažje za odpravo kaosa, v katerega se je sistem spremenil. Alisa se je bala, da se bo situacija poslabšala s razvojem aplikacije (poleg tega se je obetala nov projekt na osnovi strojnega učenja). Bob je avtomatiziral večino dela in ni razumel, zakaj je pipeline še vedno nestabilen, slabo se širi in občasno zahteva ročno posredovanje?

Nato sta izvedela za GitOps. To rešitev se je izkazala za tisto, kar sta potrebovala za samozavestno napredovanje.

Alisa in Bob sta že vrsto let slišala za delovne tokove, ki temeljijo na Gitu, DevOps in infrastrukturo kot kodo. Edinstvena lastnost GitOps je, da prinaša vrsto najboljših praks — kategoriyčnih in normativnih — za uresničevanje teh idej v kontekstu Kubernetes. Ta tematika je bila večkrat omenjena, vključno z blogom Weaveworks.

Family Insurance se odloča za uvajanje GitOps. Zdaj ima podjetje avtomatiziran model delovanja, ki je združljiv s Kubernetes in združuje hitrost z stabilnostjo, saj so:

  • odkrili, da je produktivnost ekipe dvakrat večja in nihče pri tem ne izgublja zdrave pameti;
  • prenehali oskrbovati skripte. Namesto tega se sedaj lahko osredotočijo na nove funkcije in izboljšajo inženirske metode — na primer, uvedli so kanarjevo uvajanje in izboljšali testiranje;
  • izboljšali proces uvajanja — sedaj redko odpove;
  • pridobili možnost obnavljanja deploymentov po delnih okvarah brez ročnega posredovanja;
  • pridobili booljšo zaupanje v dobavne sisteme. Alisa in Bob sta odkrila, da lahko ekipo razdelita na skupine, ki se ukvarjajo z mikroservisi in delajo vzporedno;
  • lahko uvedeta 30-50 sprememb v projekt vsak dan s prizadevanji vsake skupine in preizkušata nove tehnike;
  • enostavno pritegne nove razvijalce k projektu, ki imajo možnost nameščati posodobitve na produkcijo s pomočjo pull requestov že v nekaj urah;
  • enostavno opravijo revizijo v okviru SOC2 (v skladu s zahtevami ponudnikov storitev za varno upravljanje podatkov; več o tem lahko preberete na primer, ovde — op. prev.).

Kaj se je zgodilo?

GitOps — to sta dve stvari:

  1. Model delovanja za Kubernetes in cloud native. Ponuja nabor najboljših praks za nameščanje, upravljanje in spremljanje aplikacij in klasterjev, zbranih v kontejnerje. Eleganten opis v obliki enega diapozitiva od Luis Faceira:
  2. Pot do ustvarjanja okolja, usmerjenega v razvijalce, za upravljanje aplikacij. Uporabljamo delovni postopek Git tako za delovanje kot za razvoj. Upoštevajte, da ne gre le za Git push, temveč za organizacijo celotnega nabora orodij CI/CD in UI/UX.

Nekaj besed o Gitu

Če niste seznanjeni s sistemi za nadzor različic in delovnim postopkom, temelječim na Gitu, vam močno priporočamo, da jih raziščete. Sprva se lahko delo z vejami in pull requesti zdi magično, vendar so koristi vredne truda. Tukaj je dober članek za začetek.

Kako deluje Kubernetes

V naši zgodbi sta Alice in Bob prešla na GitOps po nekem času dela s Kubernetesom. GitOps je dejansko tesno povezan s Kubernetesom — to je model delovanja za infrastrukturo in aplikacije, ki temeljijo na Kubernetesu.

Kaj Kubernetes nudi uporabnikom?

Tukaj je nekaj ključnih značilnosti:

  1. V modelu Kubernetes je vse mogoče opisati v deklarativni obliki.
  2. API strežnik Kubernetes sprejema takšno deklaracijo kot vhodne podatke in nato nenehno poskuša pripeljati klaster v stanje, opisano v deklaraciji.
  3. Deklaracije so zadostne za opis in upravljanje širokega spektra delovnih obremenitev - 'aplikacij'.
  4. Zaradi tega se spremembe v aplikaciji in klastru zgodijo zaradi:
    • sprememb v slikah kontejnerjev;
    • sprememb v deklarativni specifikaciji;
    • napak v okolju - na primer, padcev kontejnerjev.

Čudovite sposobnosti Kubernetes za konvergenco

Ko administrator spremeni konfiguracijo, bo orkestrator Kubernetes te spremembe uporabil na klastru, dokler njegovo stanje ne doseže nove konfiguracije.. Ta modela deluje za vse vire Kubernetes in se širi z uporabo Custom Resource Definitions (CRDs). Zato ima Kubernetesove namestitve naslednje čudovite lastnosti:

  • Avtomatizacija: posodobitve Kubernetes ponujajo mehanizem za avtomatizacijo postopka pravilne in pravočasne uporabe sprememb.
  • Konvergenca: Kubernetes bo še naprej poskušal posodobitve, dokler ne bo uspešen.
  • Idempotentnost: ponovna uporaba konvergence vodi do istega rezultata.
  • Detereminiranost: ob zadostnih virih stanje posodobljenega grozda temelji le na želenem stanju.

Kako deluje GitOps

Dovolj smo spoznali Kubernetes, da pojasnimo principe delovanja GitOps.

Vrnimo se k skupinam Family Insurance, povezanih z mikroservisi. S čim se običajno ukvarjajo? Oglejte si seznam spodaj (če se vam katera od postavk zdi čudna ali nepoznana — prosimo, počakajte s kritiko in ostanite z nami). To so le primeri delovnih procesov na podlagi Jenkins. Obstaja še mnoge druge procese, ko delate z drugimi orodji.

Najpomembnejše je, da vidimo, da se vsaka posodobitev konča s spremembami v konfiguracijskih datotekah in Git repozitorijih. Te spremembe v Gitu povzročijo, da "GitOps operater" posodobi grozd:

1. Delovni proces: "Gradnja Jenkins — veja master».
Seznam nalog:

  • Jenkins pošlje označene slike v Quay;
  • Jenkins pošlje konfiguracijo in Helm grafikone v vedro master skladišča;
  • Oblačna funkcija kopira konfiguracijo in grafikone iz vedra master skladišča v Git repozitorij master;
  • GitOps operater posodobi grozd.

2. Gradnja Jenkins — veja release ali hotfix:

  • Jenkins pošlje neoznačene slike v Quay;
  • Jenkins pošlje konfiguracijo in Helm grafikone v vedro staging skladišča;
  • Oblačna funkcija kopira konfiguracijo in grafikone iz vedra staging skladišča v Git repozitorij staging;
  • GitOps operater posodobi grozd.

3. Gradnja Jenkins — veja develop ali feature:

  • Jenkins pošlje neoznačene slike v Quay;
  • Jenkins pošlje konfiguracijo in Helm grafikone v vedro develop skladišča;
  • Oblačna funkcija kopira konfiguracijo in grafikone iz vedra develop skladišča v Git repozitorij develop;
  • GitOps operater posodobi grozd.

4. Dodajanje novega klienta:

  • Manager ali skrbnik (LCM/ops) pokliče Gradle za prvotno implementacijo in nastavitev omrežnih uravnoteževalnikov obremenitve (NLB);
  • LCM/ops zaključi novo konfiguracijo za pripravo namestitve na posodobitve;
  • GitOps operater posodobi grozd.

Kratki opis GitOps

  1. Opišite željeno stanje cijelog sistema koristeći deklarativne specifikacije za svako okruženje (u našoj priči Bobov tim definira cijelu konfiguraciju sistema u Gitu).
    • Git repozitorij je jedini izvor istine u vezi sa željenim stanjem cijelog sistema.
    • Sve promjene željenog stanja vrše se putem commit-a u Git.
    • Svi željeni parametri klastera također su vidljivi u samom klasteru. Tako možemo utvrditi da li se željeno i promatrano stanje podudaraju (konvergiraju, converge) ili razlikuju (divergiraju, diverge) od željenog i promatranog stanja.
  2. Ako se željeno i promatrano stanje razlikuju, tada:
    • Postoji mehanizam konvergencije koji će prije ili kasnije automatski uskladiti ciljno i promatrano stanje. Unutar klastera, tim se bavi Kubernetes.
    • Proces se pokreće odmah s obavještenjem „promjena je izvršena”.
    • Nakon određenog prilagodljivog vremenskog razdoblja može biti poslato obavještenje „diff”, ako se stanja razlikuju.
  3. Tako svi commit-i u Git pokreću provjerljive i idempotentne nadogradnje u klasteru.
    • Rollback je konvergencija na prethodno željeno stanje.
  4. Konvergencija je konačna. O njenom postizanju svjedoče:
    • Nedostatak obavještenja „diff” tokom određenog vremenskog perioda.
    • Obavještenje „konvergirano” (na primjer, webhook, događaj Git writeback).

Šta je divergencija?

Ponovimo još jednom: sva željena svojstva klastera moraju biti vidljiva u samom klasteru.

Nekoliko primjera divergencije:

  • Promjena u konfiguracijskoj datoteci zbog spajanja grana u Gitu.
  • Promjena u konfiguracijskoj datoteci zbog commit-a u Gitu, napravljenog putem GUI klijenta.
  • Višestruke promjene u željenom stanju uslijed PR-a u Gitu uz naknadnu izradu kontejnerske slike i promjenama u konfiguraciji.
  • Promjena stanja klastera zbog greške, sukoba resursa koji dovodi do „lošeg ponašanja”, ili jednostavno slučajnog odstupanja od originalnog stanja.

Šta predstavlja mehanizam konvergencije?

Nekoliko primjera:

  • Za kontejnere i klastere, mehanizam konvergencije pruža Kubernetes.
  • Isti mehanizam se može koristiti za upravljanje aplikacijama i konstrukcijama temeljenim na Kubernetes-u (na primjer, Istio i Kubeflow).
  • Mehanizem za upravljanje delovnim interakcijam med Kubernetesom, repozitoriji slik in Gitom zagotavlja GitOps-operator Weave Flux, ki je del Weave Cloud.
  • Za osnovne naprave mora biti mehanizem konvergence deklarativen in avtonomen. Po naših izkušnjah lahko rečemo, da Terraform je najbližje tej definiciji, vendar še vedno zahteva nadzor človeka. V tem smislu GitOps širi tradicije Infrastructure as Code.

GitOps združuje Git s odličnim mehanizmom konvergence Kubernetes, ponuja model za delovanje.

GitOps nam omogoča, da izjavimo: avtomatizaciji in nadzoru podrejene samo tiste sisteme, ki jih je mogoče opisati in opazovati.

GitOps je namenjen celotnemu cloud native-堆 (na primer, Terraform itd.)

GitOps ni samo Kubernetes. Želimo, da bi bil celoten sistem upravljan deklarativno in uporabljal konvergenco. Pod celotnim sistemom razumemo nabor okolij, ki delujejo s Kubernetesom - na primer 'dev cluster 1', 'produkcija' itd. Vsako okolje vključuje naprave, klastre, aplikacije ter vmesnike za zunanje storitve, ki zagotavljajo podatke, spremljanje itd.

Opazite, kako pomemben je v tem primeru Terraform za težavo z zagonom. Kubernetes mora biti nekje nameščen, in uporaba Terraform pomeni, da lahko uporabimo iste delovne tokove GitOps za ustvarjanje upravljalnega sloja, ki leži v ozadju Kubernetes in aplikacij. To je koristna najboljša praksa.

Veliko pozornosti je namenjeno uporabi konceptov GitOps za sloje nad Kubernetesom. V tem trenutku so na voljo rešitve tipa GitOps za Istio, Helm, Ksonnet, OpenFaaS in Kubeflow ter na primer za Pulumi, ki ustvarjajo sloj za razvoj aplikacij za cloud native.

Kubernetes CI/CD: primerjava GitOps z drugimi pristopi

Kot je bilo omenjeno, je GitOps dva stvari:

  1. Model delovanja za Kubernetes in cloud native, opisan zgoraj.
  2. Pot do organizirane okolice, usmerjene v razvijalce, za upravljanje aplikacij.

Za mnoge je GitOps predvsem delovni postopek temeljen na Git push-ih. Tudi nam je to všeč. A to ni vse: poglejmo zdaj CI/CD cevi.

GitOps zagotavlja neprekinjeno uvajanje (CD) pod Kubernetesom

GitOps ponuja mehanizem neprekinjenega uvajanja, ki odpravlja potrebo po ločenih 'sistemih za upravljanje uvajanj'. Vso delo opravi za vas Kubernetes.

  • Posodobitev aplikacije zahteva posodobitev v Git-u. To je transakcijska posodobitev do želene state. „Implementacija“ se nato izvede znotraj grozda s samim Kubernetesom na podlagi posodobljenega opisa.
  • Zaradi specifičnosti delovanja Kubernetesa so te posodobitve konvergentne. Tako je zagotovljen mehanizem za neprekinjeno uvajanje, v katerem so vse posodobitve atomske.
  • Opomba: Weave Cloud ponuja GitOps operator, ki integrira Git in Kubernetes ter omogoča izvajanje CD s usklajevanjem želene in trenutne state grozda.

Brez kubectl in skriptov

Izogibati se je treba uporabi Kubectl za posodobitev grozda, zlasti pa skriptom za grupiranje ukazov kubectl. Namesto tega lahko uporabnik posodobi svoj grozd Kubernetes prek GitOps pipeline.

Prednosti vključujejo:

  1. Pravilnost. Skupino posodobitev lahko uporabimo, konvergiramo in na koncu validiramo, kar nas približa cilju atomske implementacije. Nasprotno, uporaba skriptov ne zagotavlja nobenih jamstev konvergence (več o tem spodaj).
  2. Sigurnost. Citiram Kelsey Hightower: „Omejite dostop do grozda Kubernetes orodjem za avtomatizacijo in skrbnikom, katerih odgovornost je njegova odpravljanje napak ali vzdrževanje delovanja“. Glejte tudi moj članek o varnosti in skladnosti s tehničnimi zahtevami, ter članek o kršitvi Homebrew s krajo poverilnic iz slabo napisanega Jenkins skripta.
  3. Uporabniška izkušnja. Kubectl razkriva mehaniko objektnega modela Kubernetesa, ki je precej zapleten. V idealnem primeru bi morali uporabniki interagirati s sistemom na višji ravni abstrakcije. Tukaj se spet sklicujem na Kelseyja in priporočam, da si ogledate točen pregled.

Razlika med CI in CD

GitOps izboljšuje obstoječe CI/CD modele.

Sodoben CI strežnik je orodje za orkestracijo. Zlasti je to orodje za orkestracijo CI pipeline-ov. Ti vključujejo build, test, merge to trunk itd. CI strežniki avtomatizirajo upravljanje zapletenih večstopenjskih pipeline-ov. Pogosta skušnjava je ustvariti skript za niz posodobitev Kubernetesa in ga izvajati kot del pipeline-a za push sprememb v grozd. Resnično, tako ravnajo mnogi strokovnjaki. Vendar to ni optimalno, in tukaj je razlog.

CI naj bi se uporabljal za uvajanje posodobitev v trunk, medtem ko se mora Kubernetes klaster spreminjati na podlagi teh posodobitev, da upravlja CD „notranje“. To imenujemo pull-model za CD, kar se razlikuje od CI push-modela. CD je del runtime-orchestracije.

Zakaj CI strežniki ne bi smeli izvajati CD prek neposrednih posodobitev v Kubernetes

Ne uporabljajte CI strežnika za orkestracijo neposrednih posodobitev v Kubernetes v obliki niza CI nalog. To je protikoren, o katerem smo že smo že govorili v našem blogu.

Poglejmo Aliso in Boba.

S katerimi težavami sta se srečala? CI strežnik Boba uporablja spremembe v klastru, toda če med postopkom pade, Bob ne bo vedel, v katerem stanju je (ali bi moral biti) klaster in kako ga popraviti. Enako velja v primeru uspeha.

Predpostavimo, da je Bobova ekipa zgradila novo sliko in nato popravila svoje nastavitve, da bi razporedila sliko (vse to iz CI cevi).

Če se slika sestavi normalno, vendar cev pade, se bo ekipa morala spraševati:

  • Ali je bila posodobitev razporejena?
  • Ali izvajamo novo gradnjo? Bo to povzročilo nepotrebne stranske učinke — možnost pridobitve dveh gradenj iste nespremenjene slike?
  • Ali naj počakamo na naslednjo posodobitev, preden zaženemo gradnjo?
  • Kaj točno je šlo narobe? Katere korake je treba ponoviti (in katere je varno ponoviti)?

Organizacija delovnega procesa, ki temelji na Gitu, ne zagotavlja, da se bo Bobova ekipa izognila tem težavam. Še vedno se lahko zmotijo pri pushu spremembe, oznaki ali katerem koli drugem parametru; vendar je ta pristop še vedno precej bližje jasnemu vsem-ali-nic.

Na kratko, tukaj je, zakaj CI strežniki ne bi smeli opravljati CD:

  • Skripti za posodobitev niso vedno deterministični; enostavno je narediti napake.
  • CI strežniki ne konvergirajo k deklarativnemu modelu klasterja.
  • Težko je zagotoviti idempotentnost. Uporabniki morajo razumeti globoko semantiko sistema.
  • Težje je obnoviti po delnem neuspehu.

Opomba o Helmu: če želite uporabljati Helm, priporočamo, da ga združite z GitOps-operatorjem, kot je Flux-Helm. To bo pomagalo zagotoviti konvergenco. Sam Helm ni niti determinističen niti atomaren.

GitOps kot najboljši način za izvajanje Continuous Delivery za Kubernetes

Ekipa Alice in Boba uvaja GitOps in ugotavlja, da je veliko lažje delati s programsko opremo ter ohranjati visoko učinkovitost in stabilnost. Zaključimo ta članek s ilustracijami, ki prikazujejo, kako izgleda njihov nov pristop. Upoštevajte, da se večinoma pogovarjamo o aplikacijah in storitvah, vendar se GitOps lahko uporablja za upravljanje celotne platforme.

Model delovanja za Kubernetes

Oglejte si naslednjo diagramo. Predstavlja Git in shrambo slik kontejnerjev kot skupne vire za dva orkestrirana življenjska cikla:

  • Cevovod neprekinjene integracije, ki bere in zapisuje datoteke v Git ter lahko posodobi repozitorij slik kontejnerjev.
  • Cevovod Runtime GitOps, ki združuje namestitev z upravljanjem in opazovanjem. Bere in zapisuje datoteke v Git ter lahko nalaga slike kontejnerjev.

Kakšni so glavni sklepi?

  1. Ločitev težav: Upoštevajte, da se lahko oba cevovoda izmenjujeta podatke, tako da posodabljata Git ali repozitorij slik. Z drugimi besedami, obstaja požarni zid med CI in runtime okoljem. Imenujemo ga 'požarni zid nespremenljivosti' (immutability firewall), saj vse posodobitve repozitorijev ustvarjajo nove različice. Za dodatne informacije o tej temi se obrnite na diapozitive 72-87. te predstavitve.
  2. Lahko uporabite katerikoli CI- in Git-strežnik: GitOps deluje z vsemi komponentami. Še naprej lahko uporabljate svoje priljubljene CI- in Git-strežnike, repozitorije slik in nize testov. Skoraj vsi drugi pripomočki za neprekinjeno dostavo na trgu zahtevajo svoj lastni CI-/Git-strežnik ali shrambo slik. To je lahko omejevalni dejavnik v razvoju cloud native. Pri GitOps lahko uporabite znane pripomočke.
  3. Dogodki kot orodje integracije: Takoj, ko so podatki v Gitu posodobljeni, Weave Flux (ali operater Weave Cloud) obvesti o tem runtime. Vsakič, ko Kubernetes sprejme niz sprememb, se Git posodobi. To zagotavlja preprost model integracije za organizacijo delovnih procesov za GitOps, kot je prikazano spodaj.

Zaključek

GitOps zagotavlja pomembne garancije posodobitev, ki so potrebne kateremukoli sodobnemu orodju CI/CD:

  • avtomatizacija;
  • konvergenca;
  • idempotentnost;
  • determiniranost.

To je pomembno, saj ponuja model delovanja za razvijalce na področju cloud native.

  • Tradicionalna orodja za upravljanje in nadzor sistemov so povezana s ekipami za delovanje, ki delujejo v okviru runbook-a. (niza rutinskih postopkov in operacij — op. prev.), vezanega na določen deployment.
  • Pri upravljanju cloud native sistemov je orodje za opazovanje najboljši način za oceno rezultatov razporeditev, da se lahko ekipa razvijalcev nanje hitro odzove.

Predstavljajte si številne klastre, raztresene po različnih oblakih, in številne storitve s svojimi ekipami in načrti razporeditev. GitOps ponuja obsežno modeliranje za upravljanje vsega tega bogastva.

P.S. od prevajalca

Preberite tudi na našem blogu:

Samo registrovani korisnici mogu učestvovati u anketi. Prijavite se, molim vas.

Ali ste vedeli za GitOps, preden sta ti dve prevodni objavi prišli na Habr?

  • Ja, vse sem vedel(a)

  • Le površno

  • Ne

35 uporabnikov je glasovalo. 10 uporabnikov se je vzdržalo.

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster