{"id":36754,"date":"2019-10-31T22:13:37","date_gmt":"2019-10-31T19:13:37","guid":{"rendered":"https:\/\/prohoster.info\/blog\/werf-nash-instrument-dlya-ci-cd-v-kubernetes-obzor-i-video-doklada\/"},"modified":"2019-10-31T22:13:37","modified_gmt":"2019-10-31T19:13:37","slug":"werf-nash-instrument-dlya-ci-cd-v-kubernetes-obzor-i-video-doklada","status":"publish","type":"post","link":"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/werf-nash-instrument-dlya-ci-cd-v-kubernetes-obzor-i-video-doklada","title":{"rendered":"werf \u2014 meie t\u00f6\u00f6riist CI\/CD jaoks Kuberneteses (\u00fclevaade ja video ettekandest)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>27. mai DevOpsConf 2019 peamise saali konverentsil, mis toimub festivali raames <noindex><a rel=\"nofollow\" href=\"http:\/\/ritfest.ru\/2019\/\">RIT++ 2019<\/a><\/noindex>, konverentsi sektsioonis \"Pidev tarne\" esitati ettekannet \"werf - meie t\u00f6\u00f6riist CI\/CD jaoks Kuberneteses\". Ettekanne k\u00e4sitleb neid <b>probleeme ja v\u00e4ljakutseid, millega iga\u00fchel silmitsi seista tuleb, kui n\u00e4iteks kasutatakse Kuberneteset<\/b>, samuti n\u00fcansse, mis ei pruugi kohe silma paista. Potentsiaalsete lahenduste k\u00e4sitlemisel n\u00e4itame, kuidas see on ellu viidud avatud l\u00e4htekoodiga t\u00f6\u00f6riist <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/werf\">werf<\/a><\/noindex>.<\/p>\n<p>Alates ettekandest on meie utiliit (varem tuntud kui dapp) \u00fcletanud ajaloolise piiri <b>1000 t\u00e4hte GitHubis<\/b> \u2014 loodame, et kasvav kasutajate kogukond muudab paljude DevOps inseneride elu lihtsamaks.<\/p>\n<p><img decoding=\"async\" alt=\"werf \u2014 meie t\u00f6\u00f6riist CI\/CD jaoks Kuberneteses (\u00fclevaade ja video ettekandest)\" src=\"\/wp-content\/uploads\/2019\/08\/c2d1ad5133c0de944b60ae37e3dbe598.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNii et, tutvustame <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=cK3ackGUTLw\"><b>ettekande videot<\/b><\/a><\/noindex> (~47 minutit, oluliselt informatiivsem kui artikkel) ja selle p\u00f5hisisu tekstivormis. Alustame!<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Koodi kohaletoimetamine Kubernetesesse<\/h2>\n<p>\nEttekanne ei k\u00e4sitle enam werfi, vaid CI\/CD-d Kuberneteses, eeldades, et meie tarkvara on pakitud Docker-konteineritesse <i>(sellest r\u00e4\u00e4kisin ma <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/322686\/\">2016. aasta ettekandes<\/a><\/noindex>)<\/i>, ja K8s kasutatakse selle tootmisse viimisel <i>(sellest - <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/331188\/\">2017. aastal<\/a><\/noindex>)<\/i>.<\/p>\n<p>Kuidas n\u00e4eb v\u00e4lja kohaletoimetamine Kubernetesesse?<\/p>\n<ul>\n<li> On Git-repos, kus on kood ja selle koostamiseks vajalikud juhised. Rakendus kogutakse Docker-pildiks ja avaldatakse Docker Registry's.<\/li>\n<li> Samuti on samas repos juhised rakenduse kohaletoimetamiseks ja k\u00e4itamiseks. T\u00e4ienduse etapis saadetakse need juhised Kubernetesesse, mis saab vajalikku pilti registry'st ja k\u00e4ivitab selle.<\/li>\n<li> Ja tavaliselt on olemas ka testid. M\u00f5ningaid teste saab k\u00e4ivitada pildi avaldamise ajal. Samuti saab (neid samu juhiseid kasutades) luua rakenduse koopia (eraldi K8s nimespaces v\u00f5i eraldi klastris) ja testida seal.<\/li>\n<li> L\u00f5puks on vajalik CI-s\u00fcsteem, mis saab s\u00fcndmusi Git'ist (v\u00f5i nupuvajutustest) ja kutsub v\u00e4lja k\u00f5ik m\u00e4\u00e4ratud etapid: ehitamine, avaldamine, kohaletoimetamine, testimine.<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"werf \u2014 meie t\u00f6\u00f6riist CI\/CD jaoks Kuberneteses (\u00fclevaade ja video ettekandest)\" src=\"\/wp-content\/uploads\/2019\/08\/ec0d1fd1bf1a68cca92badf7cf1affe1.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSiin on mitu olulist t\u00e4helepanekut:<\/p>\n<ol>\n<li> Kuna meil on muutumatu infrastruktuur <i>(immutable infrastructure)<\/i>, peab rakenduse pilt, mida kasutatakse k\u00f5igis etappides (staging, tootmine jne), <b>olema \u00fcks<\/b>. <i>Selle kohta r\u00e4\u00e4kisin ma p\u00f5hjalikumalt koos n\u00e4idistega <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/324274\/\">siin<\/a><\/noindex>.<\/i><\/li>\n<li> Kuna me j\u00e4rgime l\u00e4henemist infrastruktuur kui kood <i>(IaC)<\/i>, rakenduskood, juhised selle koostamiseks ja k\u00e4itamiseks peavad olema <b>just selles \u00fches repos<\/b>. <i>Selle kohta - vt <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/324274\/\">samast ettekandest<\/a><\/noindex>.<\/i><\/li>\n<li> Kohaletoimetamise ahel <i>(delivery)<\/i> meie n\u00e4eme seda tavaliselt nii: rakendus on kokku pandud, testitud ja v\u00e4lja antud <i>(v\u00e4ljaandmise etapp)<\/i> ja k\u00f5ik \u2014 kohaletoimetamine on toimunud. Kuid tegelikult saab kasutaja selle, mis te v\u00e4lja andsite, <b>ei<\/b> sel hetkel, kui te selle tootmiseni toimetasite, ja millal ta sai sinna sisse logida ning see tootmine t\u00f6\u00f6tas. Seega arvan, et kohaletoimetamise ahel l\u00f5ppeb <b>ainult ekspluateerimise etapis<\/b> <i>(k\u00e4itus)<\/i>, ja t\u00e4psemalt isegi siis, kui kood k\u00f5rvaldati tootmisest (asendades selle uuega).<\/li>\n<\/ol>\n<p>\nNaaseme varem nimetatud kohaletoimetamise skeemi juurde Kuberneteses: selle l\u00f5id mitte ainult meie, vaid ka praktiliselt iga\u00fcke, kes selle probleemiga tegeleb. Selle mustrit nimetatakse praegu GitOps <i>(selle termini ja selle taga olevate ideede kohta saab lugeda <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/458878\/\">siin<\/a><\/noindex>)<\/i>. Vaatame skeemi etappe.<\/p>\n<h2>Kogumise etapp<\/h2>\n<p>\nTundub, et 2019. aastal on midagi \u00f6elda Docker-piltide koostamise kohta, kui k\u00f5ik oskavad kirjutada Dockerfile'e ja k\u00e4ivitada <code>docker build<\/code>?.. \u0412\u043e\u0442 \u043d\u044e\u0430\u043d\u0441\u044b, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435:<\/p>\n<ol>\n<li> <b>Pildi kaal<\/b> on oluline, seega kasutage <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/develop\/develop-images\/multistage-build\/\">multi-stage<\/a><\/noindex>, et j\u00e4tta pildis alles ainult see, mis on tegelikult rakenduse toimimiseks vajalik.<\/li>\n<li> <b>Kihtide arvu<\/b> tuleb minimeerida, \u00fchendades m\u00f5tteliselt seotud <code>K\u00c4IVITA<\/code>-k\u00e4skluste jadad.<\/li>\n<li> Kuid see toob kaasa probleeme <b>silumisega<\/b>, kuna t\u00f5rgete korral tuleb tuvastada t\u00e4pselt see k\u00e4sklus jadast, mis probleemi p\u00f5hjustas.<\/li>\n<li> <b>Koostamise kiirus<\/b> on oluline, sest soovime kiiresti muudatusi v\u00e4lja anda ja tulemust vaadata. N\u00e4iteks ei taha me igal rakenduse koostamisel s\u00f5ltuvusi \u00fcmber koostada.<\/li>\n<li> Sageli on \u00fchest Git-repositooriumist vajalik <b>palju pilte<\/b>, mida saab lahendada Dockerfile'ide komplekti (v\u00f5i sama faili nimetatud etappidena) ja Bash-skripti abil nende j\u00e4rjestikuseks koostamiseks.<\/li>\n<\/ol>\n<p>\nSee oli vaid j\u00e4\u00e4m\u00e4e tipp, millega k\u00f5ik silmitsi seisavad. Kuid olemas on ka teised probleemid, nimelt:<\/p>\n<ol>\n<li> Sageli on selle koostamise etapis meil vaja midagi <b>m\u00e4Mountida<\/b> (n\u00e4iteks apt-laadse k\u00e4su tulemuse vahem\u00e4lu kolmandasse kausta).<\/li>\n<li> Me soovime <b>Ansible<\/b> asemel, et kirjutada shellis.<\/li>\n<li> Me soovime <b>koostada ilma Dockerita<\/b> (miks meil on vaja lisavirtuaalmasinat, millele k\u00f5ik selle jaoks seadistada, kui meil on juba Kubernetes klaster, kus saab konteinerit k\u00e4ivitada?).<\/li>\n<li> <b>Paralleelne kogu<\/b>, mida saab t\u00f5lgendada erinevalt: erinevad k\u00e4sud Dockerfile'is (kui kasutatakse mitme etapi koostamist), mitu kommti \u00fches hoidlas, mitu Dockerfile'i.<\/li>\n<li> <b>Jaotatud koostamine<\/b>: me tahame midagi koostada pod'ides, mis on \u201eefemeersed\u201d, kuna neil kaob vahem\u00e4lu, seega tuleb see kuskile eraldi salvestada.<\/li>\n<li> L\u00f5puks nimetasin soovide tippu <b>automagiks<\/b>: oleks ideaalne sisse logida hoidlasse, sisestada mingi k\u00e4sk ja saada valmis pilt, mis on kokku pandud arusaamisega, kuidas ja mida \u00f5igesti teha. Siiski, isiklikult ei ole ma kindel, et k\u00f5iki nuansse saab nii etten\u00e4htud.<\/li>\n<\/ol>\n<p>\nJa siin on projektid:<\/p>\n<ul>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/moby\/buildkit\">moby\/buildkit<\/a><\/noindex> \u2014 koostaja ettev\u00f5ttelt Docker Inc (juba integreeritud aktuaalsetesse Docker'i versioonidesse), mis p\u00fc\u00fcab lahendada k\u00f5ik need probleemid;<\/li>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/GoogleContainerTools\/kaniko\">kaniko<\/a><\/noindex> \u2014 koostaja Google'ilt, mis v\u00f5imaldab kokku panna ilma Dockerita;<\/li>\n<li> <noindex><a rel=\"nofollow\" href=\"https:\/\/buildpacks.io\/\">Buildpacks.io<\/a><\/noindex> \u2014 CNCF katse teha automagiat ja eelk\u00f5ige huvitav lahendus rebase'i jaoks kihtide jaoks;<\/li>\n<li> ja veel hulk teisi t\u00f6\u00f6riistu, nagu <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/containers\/buildah\">buildah<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/genuinetools\/img\">genuinetools\/img<\/a><\/noindex>\u2026<\/li>\n<\/ul>\n<p>\n\u2026 ja vaadake, kui palju neil on t\u00e4hti GitHubis. Seega, \u00fchelt poolt, <code>docker build<\/code> on olemas ja nad v\u00f5ivad midagi teha, kuid tegelikult <b>k\u00fcsimus pole t\u00e4ielikult lahendatud<\/b> \u2014 t\u00f5estuseks sellele on mitme alternatiivse koostaja parallelne arendamine, iga\u00fchel neist on oma osa probleemide lahendamiseks.<\/p>\n<h2>Koostamine werf'is<\/h2>\n<p>\nNii j\u00f5udsime <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/werf\">werf<\/a><\/noindex> <i>(varem <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/333682\/\">kuulsast<\/a><\/noindex> nagu dapp)<\/i> \u2014 Open Source t\u00f6\u00f6riist ettev\u00f5ttelt \u201eFlant\u201d, mida me oleme juba mitu aastat arendanud. K\u00f5ik algas umbes 5 aastat tagasi Bash skriptidega, mis optimeerisid Dockerfile'ide koostamist, ja viimased 3 aastat on toimunud t\u00e4ielik arendus \u00fche projekti raames oma Git hoidla <i>(esialgu Ruby's, aga siis <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/437044\/\">\u00fcmber kirjutatud<\/a><\/noindex> Go's, ja \u00fchtlasi \u00fcmber nimetatud)<\/i>. Milliseid koostamise k\u00fcsimusi on werf lahendanud?<\/p>\n<p><img decoding=\"async\" alt=\"werf \u2014 meie t\u00f6\u00f6riist CI\/CD jaoks Kuberneteses (\u00fclevaade ja video ettekandest)\" src=\"\/wp-content\/uploads\/2019\/08\/ab6aa8831b49977a419fd4cc3543eb83.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSiniseks v\u00e4rvitud probleemid on juba rakendatud, paralleelne koostamine on tehtud \u00fche hosti raames, ja kollasega esile t\u00f5stetud k\u00fcsimused plaanime l\u00f5petada suve l\u00f5puks.<\/p>\n<h2>Registreerimisse (publish) etapp<\/h2>\n<p>\nSisse laaditud <code>docker push<\/code>\u2026 \u2014 mis v\u00f5ib olla keeruline, et laadida pilt registreerimisse? Ja siis tekib k\u00fcsimus: \u201eMillise sildi peaks pildile panema?\u201d See tekib seet\u00f5ttu, et meil on <b>Gitflow<\/b> (v\u00f5i m\u00f5ni muu Git strateegia) ja Kubernetes, ja t\u00f6\u00f6stus p\u00fc\u00fcab, et Kubernetesis toimuv j\u00e4rgiks seda, mis toimub Git'is. L\u00f5ppude l\u00f5puks on Git meie ainus t\u00f5estusallikas.<\/p>\n<p>Mis selles keerulist on? <b>Tagada korduv kasutatavust<\/b>: Git commitist, kellel on olemuslikult muutumatu <i>(muutumatuna)<\/i>, kuni Docker pildini, mida tuleb s\u00e4ilitada samana.<\/p>\n<p>Meile on samuti oluline <b>m\u00e4\u00e4ratleda p\u00e4ritolu<\/b>, sest me tahame m\u00f5ista, millisest commit'ist rakendus, mis on k\u00e4ivitatud Kubernetes'is, on kokku pandud (siis saame teha diff'e ja sarnaseid asju).<\/p>\n<h3>Sildistamise strateegiad<\/h3>\n<p>\nEsimene on lihtne <b>git tag<\/b>. Meil on registri pilt, mida on silti pandud nagu <code>1.0<\/code>. Kubernetes'is on etapp ja tootmine, kuhu see pilt on v\u00e4lja veetud. Git'is teeme commit'e ja mingil hetkel paneme sildi <code>2.0<\/code>. Kogume selle vastavalt repo juhistele ja paneme registrisse sildiga <code>2.0<\/code>. V\u00e4lja veame etapis ja, kui k\u00f5ik on korras, siis tootmisse.<\/p>\n<p><img decoding=\"async\" alt=\"werf \u2014 meie t\u00f6\u00f6riist CI\/CD jaoks Kuberneteses (\u00fclevaade ja video ettekandest)\" src=\"\/wp-content\/uploads\/2019\/08\/8545b84bfa63a91773f0d7dc1c2bd49f.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSelle l\u00e4henemise probleem on see, et me panime k\u00f5igepealt sildi ja alles siis testisime ja v\u00e4ljastasime. Miks? Esiteks, see on lihtsalt ebatavaline: me v\u00e4ljastame versiooni tarkvarast, mida me isegi ei ole kontrollinud (me ei saa teisiti, kuna testi tegemiseks tuleb silt panna). Teiseks, see tee ei \u00fchildu Gitflow'ga.<\/p>\n<p>Teine variant on <b>git commit + tag<\/b>. Master-haru on olemas silt <code>1.0<\/code>; selle jaoks registris on pilt, mis on v\u00e4lja veetud tootmisse. Lisaks on Kubernetes'i klastris preview ja staging kontuurid. Edasi j\u00e4rgime Gitflow't: peaharu arendamiseks (<code>develop<\/code>) loome uusi funktsioone, millega tekib commit identifikaator <code>#c1<\/code>. Kogume selle ja avaldame registrisse, kasutades seda identifikaatorit (<code>#c1<\/code>). Sama identifikaatoriga v\u00e4ljastame preview'l. Sarnast teeme commit'idega <code>#c2<\/code> ja <code>#c3<\/code>.<\/p>\n<p>Kui oleme aru saanud, et funktsioone on piisavalt, hakkame k\u00f5ike stabiliseerima. Git'is loome haru <code>release_1.1<\/code> (p\u00f5hjal <code>#c3<\/code> API-s <code>develop<\/code>). Selle v\u00e4ljaande kogumist ei ole vaja, kuna see tehti eelmisel etapil. Seet\u00f5ttu v\u00f5ime selle lihtsalt staging'ile v\u00e4lja anda. Parandame vead <code>#c4<\/code> ja samamoodi v\u00e4ljastame staging'ile. Samal ajal k\u00e4ib paralleelselt arendus <code>develop<\/code>, kuhu perioodiliselt kantakse muudatusi <code>release_1.1<\/code>. \u00dchel hetkel saame kokku pandud ja staging'ile v\u00e4lja antud commit'i, millega oleme rahul (<code>#c25<\/code>).<\/p>\n<p>Siis teeme merge (kiire edasi liikumisega) v\u00e4ljaande harust (<code>release_1.1<\/code>) masterisse. Paneme sellele commit'ile sildi uue versiooniga (<code>1.1<\/code>). Kuid see pilt on juba registris kokku pandud, seega, et seda uuesti kokku ei pandaks, lisame lihtsalt teise sildi juba olemasolevale pildile (n\u00fc\u00fcd on see registris silti <code>#c25<\/code> ja <code>1.1<\/code>). P\u00e4rast seda v\u00e4ljastame selle tootmisse.<\/p>\n<p>On puudus, et staging'ile on v\u00e4lja veetud \u00fcks pilt (<code>#c25<\/code>), ja tootmisse on v\u00e4lja veetud justkui teine (<code>1.1<\/code>), kuid me teame, et \u201ef\u00fc\u00fcsiliselt\u201d on see sama registreerimise pilt.<\/p>\n<p><img decoding=\"async\" alt=\"werf \u2014 meie t\u00f6\u00f6riist CI\/CD jaoks Kuberneteses (\u00fclevaade ja video ettekandest)\" src=\"\/wp-content\/uploads\/2019\/08\/b3fa2c34442aa401d1e7b30eb593be9a.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nT\u00f5eline miinus on see, et merge commit&#8217;e ei toetata, tuleb teha fast-forward.<\/p>\n<p>Saame edasi minna ja teha trikki\u2026 Vaadakem lihtsa Dockerfile n\u00e4idet:<\/p>\n<pre><code class=\"plaintext\">FROM ruby:2.3 as assets\nRUN mkdir -p \/app\nWORKDIR \/app\nCOPY . .\/\nRUN gem install bundler &amp;&amp; bundle install\nRUN bundle exec rake assets:precompile\nCMD bundle exec puma -C config\/puma.rb\n\nFROM nginx:alpine\nCOPY --from=assets \/app\/public \/usr\/share\/nginx\/www\/public<\/code><\/pre>\n<p>\nLoome sellest faili sellise p\u00f5him\u00f5tte kohaselt, et v\u00f5tame:<\/p>\n<ul>\n<li> SHA256 kasutatavate piltide identifikaatoritest (<code>ruby:2.3<\/code> ja <code>nginx:alpine<\/code>), mis on nende sisu kontrollsummad;<\/li>\n<li> k\u00f5ik k\u00e4sud (<code>K\u00c4IVITA<\/code>, <code>CMD<\/code> jne);<\/li>\n<li> SHA256 failidest, mis on lisatud.<\/li>\n<\/ul>\n<p>\n\u2026 ja v\u00f5tame kontrollsumma (uuesti SHA256) sellisest failist. See on <b>allkiri<\/b> k\u00f5ik, mis m\u00e4\u00e4ratleb Docker-pildi sisu.<\/p>\n<p><img decoding=\"async\" alt=\"werf \u2014 meie t\u00f6\u00f6riist CI\/CD jaoks Kuberneteses (\u00fclevaade ja video ettekandest)\" src=\"\/wp-content\/uploads\/2019\/08\/b2af0b7952eefe26ddbb145955e778e8.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nTagasi skeemi juurde ja <b>kasutame commit'ide asemel selliseid allkirju<\/b>, s.t. m\u00e4rgistame pilte allkirjadega.<\/p>\n<p><img decoding=\"async\" alt=\"werf \u2014 meie t\u00f6\u00f6riist CI\/CD jaoks Kuberneteses (\u00fclevaade ja video ettekandest)\" src=\"\/wp-content\/uploads\/2019\/08\/115f290bd5951614c041b3d510fae38e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nN\u00fc\u00fcd, kui on vaja n\u00e4iteks s&#8217;merge&#8217;ida muudatused rel\u00e4st masterisse, saame teha t\u00f5elise merge commit'i: sellel on teine identifikaator, kuid sama allkiri. Sellise identifikaatoriga saadame pildi tootmisse.<\/p>\n<p>Puuduseks on see, et n\u00fc\u00fcd ei saa m\u00e4\u00e4rata, milline commit on tootmises \u2014 kontrollsummad t\u00f6\u00f6tavad ainult \u00fches suunas. See probleem lahendatakse t\u00e4iendava metainfoki kihiga \u2014 r\u00e4\u00e4gin sellest hiljem.<\/p>\n<h3>M\u00e4rgistamine werfis<\/h3>\n<p>\nWerfis oleme l\u00e4inud veel kaugemale ja valmistasime ette jaotatud ehituse, mille vahem\u00e4lu ei asu \u00fchel masinal\u2026 Seega genereerime kahte t\u00fc\u00fcpi Docker-pilte, mida nimetame <i>stage<\/i> ja <i>image<\/i>.<\/p>\n<p>Git-repositooriumis werf hoitakse spetsiifilisi juhiseid ehitamiseks, mis kirjeldavad erinevaid ehitusetappe (<i>beforeInstall<\/i>, <i>install<\/i>, <i>beforeSetup<\/i>, <i>setup<\/i>). Esimene stage-pilt luuakse allkirjaga, mis on m\u00e4\u00e4ratletud esialgsete sammude kontrollsummana. Seej\u00e4rel lisame l\u00e4htekoodi, uue stage-pildi jaoks arvutame selle kontrollsumma\u2026 Need toimingud korduvad k\u00f5igis etappides, mille tulemusena saame komplekti stage-piltidest. Seej\u00e4rel loome l\u00f5pliku image-pildi, mis sisaldab ka selle p\u00e4ritolu metainfot. Ja just seda pilti me m\u00e4rgistame erinevate viisidega (detailid hiljem).<\/p>\n<p><img decoding=\"async\" alt=\"werf \u2014 meie t\u00f6\u00f6riist CI\/CD jaoks Kuberneteses (\u00fclevaade ja video ettekandest)\" src=\"\/wp-content\/uploads\/2019\/08\/22df8b6347b45be19ecb889c102b92b5.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLaske, et p\u00e4rast seda tekib uus commit, kus on muudetud ainult rakenduse koodi. Mis juhtub? Koodi muutuste jaoks luuakse patch, uue stage-image'i valmistamiseks. Selle allkiri m\u00e4\u00e4ratakse vanade stage-image'i ja uue pat\u0161i kontrollsummana. Sellest pildist vormitakse uus l\u00f5plik image.<\/p>\n<p>Nii on stage-image'd - vahem\u00e4lu, mida saab salvestada jaotatult, ja sellest loodud image'id laaditakse Docker Registry'sse.<\/p>\n<p><img decoding=\"async\" alt=\"werf \u2014 meie t\u00f6\u00f6riist CI\/CD jaoks Kuberneteses (\u00fclevaade ja video ettekandest)\" src=\"\/wp-content\/uploads\/2019\/08\/35805eca81605bd64c6910b7965b567e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h3>Registry puhastamine<\/h3>\n<p>\nR\u00e4\u00e4gime mitte kihtide eemaldamisest, mis on j\u00e4\u00e4nud h\u00f5ljuvaks p\u00e4rast kustutatud silte - see on Docker Registry enda standardne funktsioon. Jutt on olukorrast, kus akumuleerub palju Docker-silte ja me m\u00f5istame, et osa neist pole meile enam vajalik, aga nad v\u00f5tavad ruumi (ja\/v\u00f5i me maksame selle eest).<\/p>\n<p>Milliseid puhastamisstrateegiaid on?<\/p>\n<ol>\n<li> V\u00f5ib lihtsalt mitte midagi <b>puhastada<\/b>. M\u00f5nikord on t\u00f5esti lihtsam maksta natuke \u00fcleliigse ruumi eest, kui harutada lahti tohutult sildistatud kimbu. Kuid see t\u00f6\u00f6tab ainult teatud hetkeni.<\/li>\n<li> <b>T\u00e4ielik l\u00e4htestamine<\/b>. Kui kustutada k\u00f5ik pildid ja uuesti koostada ainult asjakohased CI-s\u00fcsteemis, v\u00f5ib tekkida probleem. Kui tootmises konteiner taask\u00e4ivitub, laaditakse sellele uus pilt - selline, mida pole veel keegi testinud. See tapab m\u00f5tte immutable infrastructure'ist.<\/li>\n<li> <b>Blue-green<\/b>. Kui \u00fcks registry hakkas \u00fcle koormama - laadime pildid teise. Sama probleem, mis eelmisel meetodil: millal saab seda registry't, mis hakkas \u00fcle koormama, puhastada?<\/li>\n<li> <b>Aja j\u00e4rgi<\/b>. Kustutada k\u00f5ik pildid, mis on vanemad kui 1 kuu? Aga kindlasti on olemas teenus, mis pole terve kuu uuendatud\u2026<\/li>\n<li> <b>K\u00e4sitsi<\/b> m\u00e4\u00e4rata, mida saab juba eemaldada.<\/li>\n<\/ol>\n<p>\nT\u00f5eliselt eluj\u00f5ulisi variante on kaks: mitte puhastada v\u00f5i siis blue-green + k\u00e4sitsi kombinatsioon. Viimase puhul on jutt j\u00e4rgnevast: kui m\u00f5istad, et on aeg registry't puhastada, lood uue ja lisad k\u00f5ik uued pildid sinna n\u00e4iteks kuu aja jooksul. Ja kuu p\u00e4rast vaatad, millised pod'id Kuberneteses kasutavad endiselt vana registry't, ja viid need ka uude registry'sse.<\/p>\n<p>Millele me l\u00f5puks j\u00f5udsime <b>werf<\/b>? \u041c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c:<\/p>\n<ol>\n<li> Git head: k\u00f5ik sildid, k\u00f5ik oksad - eeldades, et k\u00f5ik, mis on Git'is silte saanud, on vajalik ka piltides (ja kui ei ole, siis tuleb need Git'ist eemaldada);<\/li>\n<li> k\u00f5ik pod'id, mis on praegu Kubernetes'es v\u00e4lja t\u00f5mmatud;<\/li>\n<li> vanad ReplicaSet'id (see, mis hiljuti v\u00e4lja t\u00f5mmati), samuti plaanime skaneerida Helm-v\u00e4ljaandeid ja valida sealt viimased pildid.<\/li>\n<\/ol>\n<p>\n... ja teeme sellest komplektist whitelist \u2014 nimekirja piltidest, mida me ei kustuta. K\u00f5ik muu puhastame, p\u00e4rast mida leiame orvud stage-pildid ja kustutame need samuti.<\/p>\n<h2>Deploy'e etapp<\/h2>\n<p><\/p>\n<h3>Usaldusv\u00e4\u00e4rne deklaratiivsus<\/h3>\n<p>\nEsimene punkt, millele sooviksin t\u00e4helepanu juhtida deploy'e osas, on v\u00e4rskendatud ressursside konfiguratsiooni v\u00e4ljalatku minek, mis on kuulutatud deklaratiivselt. Originaalne YAML-dokument Kubernetes'i ressursside kirjelduseks erineb alati oluliselt tulemusest, mis tegelikult klastris t\u00f6\u00f6tab. Sest Kubernetes lisab konfiguratsiooni:<\/p>\n<ol>\n<li> tuvastid;<\/li>\n<li> teenuseteabe;<\/li>\n<li> palju vaikimisi v\u00e4\u00e4rtusi;<\/li>\n<li> osa praeguse staatuse kohta;<\/li>\n<li> muudatused, mis on tehtud vastuv\u00f5tu veebirakenduse t\u00f6\u00f6 k\u00e4igus;<\/li>\n<li> erinevate kontrollere (ja planeerija) t\u00f6\u00f6 tulemused.<\/li>\n<\/ol>\n<p>\nSeega, kui ilmub uus ressursi konfiguratsioon (<i>uus<\/i>), ei saa me lihtsalt olemasolevat, 'elavat' konfiguratsiooni (<i>live<\/i>) selle asemel kirjutada. Selleks peame me v\u00f5rdlema <i>uus<\/i> eelnevalt rakendatud konfiguratsiooniga (<i>last-applied<\/i>) ja peame peale pressima <i>live<\/i> saadud pat\u0161i.<\/p>\n<p>Seda l\u00e4henemist nimetatakse <b>2-way merge<\/b>. Seda kasutatakse n\u00e4iteks Helm'is.<\/p>\n<p>On olemas ka <b>3-way merge<\/b>, mille erinevus on see, et:<\/p>\n<ul>\n<li> v\u00f5rreldes <i>last-applied<\/i> ja <i>uus<\/i>, vaatame, mis on eemaldatud;<\/li>\n<li> v\u00f5rreldes <i>uus<\/i> ja <i>live<\/i>, vaatame, mis on lisatud v\u00f5i muudetud;<\/li>\n<li> kumulatiivne patch kantakse <i>live<\/i>.<\/li>\n<\/ul>\n<p>\nMe deploy'im 1000+ rakendust Helm'i abil, seega elame me tegelikult 2-way merge'iga. Kuid sellel on oma probleemid, mida oleme lahendanud oma pat\u0161idega, aidates Helm'il normaalselt t\u00f6\u00f6tada.<\/p>\n<h3>Tegelik v\u00e4ljalaskmise seisund<\/h3>\n<p>\nP\u00e4rast seda, kui meie CI-s\u00fcsteem on genereerinud uue konfiguratsiooni Kubernetes'ile j\u00e4rgmise s\u00fcndmuse k\u00e4igus, edastab see selle rakendamiseks <i>(apply)<\/i> klastrisse \u2014 Helm'i v\u00f5i <code>kubectl apply<\/code>abil. Edasi k\u00e4ib juba kirjeldatud N-way merge, millele Kubernetes API vastab CI-s\u00fcsteemile heakskiiduga, ja see omakorda oma kasutajale.<\/p>\n<p><img decoding=\"async\" alt=\"werf \u2014 meie t\u00f6\u00f6riist CI\/CD jaoks Kuberneteses (\u00fclevaade ja video ettekandest)\" src=\"\/wp-content\/uploads\/2019\/08\/fcc8251525f32c913f30fbcdc4296198.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nKuid on tohutu probleem: nimelt <b>edukas rakendamine ei t\u00e4henda edukat v\u00e4ljalaskmist.<\/b>Kui Kubernetes m\u00f5istis, millised muudatused rakendada, rakendab selle \u2014 me ei tea ikka veel, mis on tulemuseks. N\u00e4iteks v\u00f5ib frontend'is pod'ide uuendamine ja taask\u00e4ivitamine \u00f5nnestuda, kuid backend'is mitte, ja me saame k\u00e4ivitatud rakenduse erinevad versioonid.<\/p>\n<p>Ette, et k\u00f5ik \u00f5igesti teha, vajab see skeem t\u00e4iendavat elementi \u2014 spetsiaalset j\u00e4lgijat, mis saab Kubernetes API-lt teavet oleku kohta ja edastab selle edasiseks anal\u00fc\u00fcsiks tegeliku olukorra kohta. Oleme loonud avatud l\u00e4htekoodiga teegid Go keeles \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/kubedog\"><b>kubedog<\/b><\/a><\/noindex> <i>(vt selle teadaannet <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/434160\/\">siin<\/a><\/noindex>)<\/i>, \u2014 mis lahendab selle probleemi ja on integreeritud werf-iga.<\/p>\n<p>Selle j\u00e4lgija k\u00e4itumist werf tasemel saab seadistada annotatsioonide abil, mis on m\u00e4\u00e4ratud Deployments v\u00f5i StatefulSets. Peamine annotatsioon on <code>fail-mode<\/code> \u2014 m\u00f5istab j\u00e4rgmist v\u00e4\u00e4rtust:<\/p>\n<ul>\n<li> <code>IgnoreAndContinueDeployProcess<\/code> \u2014 ignoreerime selle komponendi juurutamise probleeme ja j\u00e4tkame juurutamist;<\/li>\n<li> <code>FailWholeDeployProcessImmediately<\/code> \u2014 vea tekkimine selles komponendis peatab juurutamisprotsessi;<\/li>\n<li> <code>HopeUntilEndOfDeployProcess<\/code> \u2014 loodame, et see komponent t\u00f6\u00f6tab juurutamise l\u00f5puks.<\/li>\n<\/ul>\n<p>\nN\u00e4iteks selline kombinatsioon ressurssidest ja annotatsiooni v\u00e4\u00e4rtustest <code>fail-mode<\/code>:<\/p>\n<p><img decoding=\"async\" alt=\"werf \u2014 meie t\u00f6\u00f6riist CI\/CD jaoks Kuberneteses (\u00fclevaade ja video ettekandest)\" src=\"\/wp-content\/uploads\/2019\/08\/40e161710e8a535cd95f1eb66ca8407b.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEsimest korda juurutades v\u00f5ib andmebaas (MongoDB) veel mitte olla valmis \u2014 Juhtumid kukuvad kokku. Kuid v\u00f5ime oodata hetke, et see k\u00e4ivituks, ja juurutamine l\u00e4heb siiski l\u00e4bi.<\/p>\n<p>Werf-is on veel kaks annotatsiooni kubedogi jaoks:<\/p>\n<ul>\n<li> <code>failures-allowed-per-replica<\/code> \u2014 lubatud kokkuvarisemiste arv iga koopia kohta;<\/li>\n<li> <code>show-logs-until<\/code> \u2014 reguleerib hetke, kuni werf n\u00e4itab (stdout-is) logisid k\u00f5ikidest juurutatavatest pod-idest. Oletuslikult on see <code>PodIsReady<\/code> (et ignoreerida s\u00f5numeid, mis t\u00f5en\u00e4oliselt ei ole meile vajalikud, kui pod hakkab liiklust saama), kuid lubatavad on ka v\u00e4\u00e4rtused <code>ControllerIsReady<\/code> ja <code>EndOfDeploy<\/code>.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Mida veel tahame juurutamiselt?<\/h3>\n<p>\nPeale juba kirjeldatud kahest punktist soovime:<\/p>\n<ul>\n<li> n\u00e4ha <b>logisid<\/b> \u2014 ja ainult vajalikke, mitte k\u00f5ikide teiste;<\/li>\n<li> v\u00e4lja selgitada <b>edusamme<\/b>, sest kui t\u00f6\u00f6 \"vaikselt\" ripub mitu minutit, on oluline m\u00f5ista, mis seal toimub;<\/li>\n<li> omada <b>automaatset tagasiv\u00f5tmist<\/b> juhtudel, kui midagi l\u00e4heb valesti (ja seega on kriitiline teada juurutamise tegelikku staatust). Juurutamine peab olema atomaarne: kas see l\u00e4heb l\u00f5puni v\u00f5i k\u00f5ik naaseb eelnevasse olekusse.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Summary<\/h2>\n<p>\nMeie ettev\u00f5ttena on nende erinevate raamistikus etappide (build, publish, deploy) l\u00e4biviimiseks piisav CI-s\u00fcsteem ja t\u00f6\u00f6riist <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/werf\">werf<\/a><\/noindex>.<\/p>\n<p>Kokkuv\u00f5tteks:<\/p>\n<p><img decoding=\"async\" alt=\"werf \u2014 meie t\u00f6\u00f6riist CI\/CD jaoks Kuberneteses (\u00fclevaade ja video ettekandest)\" src=\"\/wp-content\/uploads\/2019\/08\/bafba54f2df8740a1a12c93b3476e49a.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nWerf-i abil oleme saavutanud palju DevOps-inseneride probleemide lahendamisel ning oleksime r\u00f5\u00f5msad, kui laiem kogukond v\u00e4hemalt prooviks seda t\u00f6\u00f6riista praktikas. H\u00e4id tulemusi on koos saavutada lihtsam.<\/p>\n<h2>Videod ja slaidid<\/h2>\n<p>\nEsitluse video (~47 minutit):<\/p>\n<p><center><div class=\"youtube-placeholder\" data-id=\"cK3ackGUTLw\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/cK3ackGUTLw\/hqdefault.jpg\" alt=\"M\u00e4ngi videot\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><\/p>\n<p>Ettekande esitlemine:<\/p>\n<p><center><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"\/\/speakerdeck.com\/player\/2033277984c04900b18940588edf1161\" frameborder=\"0\" allowfullscreen><\/iframe><\/center><\/p>\n<h2>P.S.<\/h2>\n<p>\nTeised ettekanded Kubernetesest meie blogis:<\/p>\n<ul>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/459326\/\">Automaatskaladamine ja ressursihaldus Kuberneteses<\/a><\/noindex>\u00bb <i>(Dmitri Stoljarov; 27. aprill 2019 Stachka'l)<\/i>;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/449096\/\">Kubernetes'e laiendamine ja t\u00e4iendamine<\/a><\/noindex>\u00bb <i>(Andrei Polovov; 8. aprill 2019 Saint HighLoad++'s)<\/i>;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/431500\/\">Andmebaasid ja Kubernetes<\/a><\/noindex>\u00bb <i>(Dmitri Stoljarov; 8. november 2018 HighLoad++'s)<\/i>;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/412901\/\">J\u00e4relevalve ja Kubernetes<\/a><\/noindex>\u00bb <i>(Dmitri Stoljarov; 28. mai 2018 RootConf'il)<\/i>;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/345116\/\">Parimad CI\/CD praktikud Kubernetesega ja GitLabiga<\/a><\/noindex>\u00bb <i>(Dmitri Stoljarov; 7. november 2017 HighLoad++'s)<\/i>;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/331188\/\">Meie kogemus Kubernetesega v\u00e4ikestes projektides<\/a><\/noindex>\u00bb <i>(Dmitri Stoljarov; 6. juuni 2017 RootConf'il)<\/i>.<\/li>\n<\/ul>\n<p>Allikas: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/460351\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>27 \u043c\u0430\u044f \u0432 \u0433\u043b\u0430\u0432\u043d\u043e\u043c \u0437\u0430\u043b\u0435 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 DevOpsConf 2019, \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0449\u0435\u0439 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0444\u0435\u0441\u0442\u0438\u0432\u0430\u043b\u044f \u0420\u0418\u0422++ 2019, \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0441\u0435\u043a\u0446\u0438\u0438 \u00ab\u041d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u0430\u044f \u043f\u043e\u0441\u0442\u0430\u0432\u043a\u0430\u00bb, \u043f\u0440\u043e\u0437\u0432\u0443\u0447\u0430\u043b \u0434\u043e\u043a\u043b\u0430\u0434 \u00abwerf \u2014 \u043d\u0430\u0448 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f CI\/CD \u0432 Kubernetes\u00bb. \u0412 \u043d\u0451\u043c \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043e \u0442\u0435\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0445 \u0438 \u0432\u044b\u0437\u043e\u0432\u0430\u0445, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0440\u0438 \u0434\u0435\u043f\u043b\u043e\u0435 \u0432 Kubernetes, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e \u043d\u044e\u0430\u043d\u0441\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u043c\u0435\u0442\u043d\u044b \u043d\u0435 \u0441\u0440\u0430\u0437\u0443. [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":27531,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-36754","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"27 \u043c\u0430\u044f \u0432 \u0433\u043b\u0430\u0432\u043d\u043e\u043c \u0437\u0430\u043b\u0435 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 DevOpsConf 2019, \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0449\u0435\u0439 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0444\u0435\u0441\u0442\u0438\u0432\u0430\u043b\u044f \u0420\u0418\u0422++ 2019, \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0441\u0435\u043a\u0446\u0438\u0438 \u00ab\u041d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u0430\u044f \u043f\u043e\u0441\u0442\u0430\u0432\u043a\u0430\u00bb, \u043f\u0440\u043e\u0437\u0432\u0443\u0447\u0430\u043b.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/werf-nash-instrument-dlya-ci-cd-v-kubernetes-obzor-i-video-doklada\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"et_EE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47werf \u2014 \u043d\u0430\u0448 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f CI\/CD \u0432 Kubernetes (\u043e\u0431\u0437\u043e\u0440 \u0438 \u0432\u0438\u0434\u0435\u043e \u0434\u043e\u043a\u043b\u0430\u0434\u0430) | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"27 \u043c\u0430\u044f \u0432 \u0433\u043b\u0430\u0432\u043d\u043e\u043c \u0437\u0430\u043b\u0435 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 DevOpsConf 2019, \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0449\u0435\u0439 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0444\u0435\u0441\u0442\u0438\u0432\u0430\u043b\u044f \u0420\u0418\u0422++ 2019, \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0441\u0435\u043a\u0446\u0438\u0438 \u00ab\u041d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u0430\u044f \u043f\u043e\u0441\u0442\u0430\u0432\u043a\u0430\u00bb, \u043f\u0440\u043e\u0437\u0432\u0443\u0447\u0430\u043b.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/werf-nash-instrument-dlya-ci-cd-v-kubernetes-obzor-i-video-doklada\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:13:37+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:13:37+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47werf \u2014 meie t\u00f6\u00f6riist CI\/CD jaoks Kuberneteses (\u00fclevaade ja esitluse video) | ProHoster","description":"27. mai pe peamisel kohal DevOpsConf 2019, mis toimub festivali RIT++ 2019 raames, kuulutati v\u00e4lja sektsioon \"J\u00e4tkuv tarne\".","canonical_url":"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/werf-nash-instrument-dlya-ci-cd-v-kubernetes-obzor-i-video-doklada","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"et_EE","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47werf \u2014 \u043d\u0430\u0448 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f CI\/CD \u0432 Kubernetes (\u043e\u0431\u0437\u043e\u0440 \u0438 \u0432\u0438\u0434\u0435\u043e \u0434\u043e\u043a\u043b\u0430\u0434\u0430) | ProHoster","og:description":"27 \u043c\u0430\u044f \u0432 \u0433\u043b\u0430\u0432\u043d\u043e\u043c \u0437\u0430\u043b\u0435 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 DevOpsConf 2019, \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0449\u0435\u0439 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0444\u0435\u0441\u0442\u0438\u0432\u0430\u043b\u044f \u0420\u0418\u0422++ 2019, \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0441\u0435\u043a\u0446\u0438\u0438 \u00ab\u041d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u0430\u044f \u043f\u043e\u0441\u0442\u0430\u0432\u043a\u0430\u00bb, \u043f\u0440\u043e\u0437\u0432\u0443\u0447\u0430\u043b.","og:url":"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/werf-nash-instrument-dlya-ci-cd-v-kubernetes-obzor-i-video-doklada","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:13:37+00:00","article:modified_time":"2019-10-31T19:13:37+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"36754","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-22 04:44:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:39:23","updated":"2026-01-22 04:44:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts\/36754","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/comments?post=36754"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts\/36754\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/media\/27531"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/media?parent=36754"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/categories?post=36754"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/tags?post=36754"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}