{"id":92048,"date":"2020-08-22T07:42:57","date_gmt":"2020-08-22T05:42:57","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/sovremennye-prilozheniya-na-openshift-chast-3-openshift-kak-sreda-razrabotki-i-konvejery-openshift-pipelines"},"modified":"2020-08-22T07:42:57","modified_gmt":"2020-08-22T05:42:57","slug":"sovremennye-prilozheniya-na-openshift-chast-3-openshift-kak-sreda-razrabotki-i-konvejery-openshift-pipelines","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/sovremennye-prilozheniya-na-openshift-chast-3-openshift-kak-sreda-razrabotki-i-konvejery-openshift-pipelines","title":{"rendered":"Wsp\u00f3\u0142czesne aplikacje na OpenShift, cz\u0119\u015b\u0107 3: OpenShift jako \u015brodowisko deweloperskie i pipelines OpenShift Pipelines","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Witajcie w tym blogu! To nasz trzeci post z serii, w kt\u00f3rej pokazujemy, jak wdra\u017ca\u0107 nowoczesne aplikacje webowe na platformie Red Hat OpenShift.<\/p>\n<p><img decoding=\"async\" alt=\"Wsp\u00f3\u0142czesne aplikacje na OpenShift, cz\u0119\u015b\u0107 3: OpenShift jako \u015brodowisko deweloperskie i pipelines OpenShift Pipelines\" src=\"\/wp-content\/uploads\/2020\/08\/9c3337b13a3f045d36343308ce6154cc.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nW dw\u00f3ch wcze\u015bniejszych postach opowiedzieli\u015bmy, jak wdra\u017ca\u0107 nowoczesne aplikacje webowe w zaledwie kilku krokach oraz jak wykorzysta\u0107 nowy obraz S2I razem z gotowym obrazem serwera HTTP, takim jak NGINX, za pomoc\u0105 powi\u0105zanych zbior\u00f3w (chained builds) do organizacji wdro\u017cenia produkcyjnego.<\/p>\n<p>Dzi\u015b poka\u017cemy, jak uruchomi\u0107 na platformie OpenShift serwer deweloperski dla swojej aplikacji i zsynchronizowa\u0107 go z lokalnym systemem plik\u00f3w, a tak\u017ce om\u00f3wimy, czym s\u0105 OpenShift Pipelines i jak mo\u017cna je stosowa\u0107 jako alternatyw\u0119 dla powi\u0105zanych zbior\u00f3w.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3>OpenShift jako \u015brodowisko deweloperskie<\/h3>\n<p><\/p>\n<h4>Proces pracy dewelopera (development workflow)<\/h4>\n<p>\nJak ju\u017c wspomniano w <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/redhatrussia\/blog\/511954\/\">pierwszym po\u015bcie<\/a><\/noindex>, typowy proces rozwoju nowoczesnych aplikacji webowych to po prostu pewien \u201eserwer deweloperski\u201d, kt\u00f3ry \u015bledzi zmiany w lokalnych plikach. Gdy do nich dochodzi, uruchamiana jest kompilacja aplikacji, a nast\u0119pnie jest ona aktualizowana w przegl\u0105darce.<\/p>\n<p>W wi\u0119kszo\u015bci nowoczesnych framework\u00f3w taki \u201eserwer deweloperski\u201d jest wbudowany w odpowiednie narz\u0119dzia wiersza polece\u0144.<\/p>\n<h4>Przyk\u0142ad lokalny<\/h4>\n<p>\nNa pocz\u0105tku zobaczmy, jak to dzia\u0142a w przypadku lokalnego uruchamiania aplikacji. Jako przyk\u0142ad we\u017amiemy aplikacj\u0119 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/lholmquist\/react-web-app\">React<\/a><\/noindex> z wcze\u015bniejszych artyku\u0142\u00f3w, chocia\u017c prawie te same koncepcje procesu pracy zastosowane s\u0105 tak\u017ce w innych nowoczesnych frameworkach.<br \/>\nAby uruchomi\u0107 \u201eserwer deweloperski\u201d w naszym przyk\u0142adzie z React, wprowadzamy nast\u0119puj\u0105ce polecenie:<\/p>\n<pre><code class=\"plaintext\">$ npm run start\n<\/code><\/pre>\n<p>\nWtedy w oknie terminala zobaczymy mniej wi\u0119cej to:<\/p>\n<p><img decoding=\"async\" alt=\"Wsp\u00f3\u0142czesne aplikacje na OpenShift, cz\u0119\u015b\u0107 3: OpenShift jako \u015brodowisko deweloperskie i pipelines OpenShift Pipelines\" src=\"\/wp-content\/uploads\/2020\/08\/06f84ffb4c9a6a5868b8b47b8ad1d9ec.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>A nasza aplikacja otworzy si\u0119 w przegl\u0105darce domy\u015blnej:<\/p>\n<p><img decoding=\"async\" alt=\"Wsp\u00f3\u0142czesne aplikacje na OpenShift, cz\u0119\u015b\u0107 3: OpenShift jako \u015brodowisko deweloperskie i pipelines OpenShift Pipelines\" src=\"\/wp-content\/uploads\/2020\/08\/72341bb0796352e7343bf31ceb8233cd.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Teraz, je\u015bli wprowadzimy zmiany w pliku, aplikacja powinna zaktualizowa\u0107 si\u0119 w przegl\u0105darce.<\/p>\n<p>OK, z deweloperk\u0105 w trybie lokalnym wszystko jasne, a jak osi\u0105gn\u0105\u0107 to samo na OpenShift?<\/p>\n<h4>Serwer deweloperski na OpenShift<\/h4>\n<p>\nJe\u015bli pami\u0119tasz, w <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/redhatrussia\/blog\/513948\/\">poprzednim po\u015bcie<\/a><\/noindex>, omawiali\u015bmy tzw. etap uruchamiania (run phase) obrazu S2I i zobaczyli\u015bmy, \u017ce domy\u015blnie zarz\u0105dzanie nasz\u0105 aplikacj\u0105 webow\u0105 przejmuje modu\u0142 serve.<\/p>\n<p>Jednak je\u015bli przyjrzymy si\u0119 dok\u0142adniej <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/nodeshift\/ubi8-s2i-web-app\/blob\/master\/s2i\/run#L10\">skryptowi uruchamiaj\u0105cemu (run script)<\/a><\/noindex> z tego przyk\u0142adu, to zawiera on zmienn\u0105 \u015brodowiskow\u0105 $NPM_RUN, kt\u00f3ra pozwala wykona\u0107 w\u0142asne polecenie.<\/p>\n<p>Na przyk\u0142ad, mo\u017cna u\u017cy\u0107 modu\u0142u nodeshift, aby wdro\u017cy\u0107 nasze aplikacje:<\/p>\n<pre><code class=\"plaintext\">$ npx nodeshift --deploy.env NPM_RUN=\"yarn start\" --dockerImage=nodeshift\/ubi8-s2i-web-app\n<\/code><\/pre>\n<p>\n<i>Uwaga: powy\u017cszy przyk\u0142ad podany jest w skr\u00f3conej formie, aby zilustrowa\u0107 og\u00f3ln\u0105 ide\u0119.<\/i><\/p>\n<p>Dodali\u015bmy do naszego wdro\u017cenia zmienn\u0105 \u015brodowiskow\u0105 NPM_RUN, kt\u00f3ra informuje etap wykonania, \u017ce powinien uruchomi\u0107 polecenie yarn start, kt\u00f3re uruchamia serwer deweloperski React w naszym podzie OpenShift.<\/p>\n<p>Je\u015bli spojrzymy na logi dzia\u0142aj\u0105cego poda, to b\u0119dzie wygl\u0105da\u0107 mniej wi\u0119cej tak:<\/p>\n<p><img decoding=\"async\" alt=\"Wsp\u00f3\u0142czesne aplikacje na OpenShift, cz\u0119\u015b\u0107 3: OpenShift jako \u015brodowisko deweloperskie i pipelines OpenShift Pipelines\" src=\"\/wp-content\/uploads\/2020\/08\/5b090223e08e32a3356608881068ce1a.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Oczywi\u015bcie, wszystko to nie ma sensu, dop\u00f3ki nie b\u0119dziemy mogli synchronizowa\u0107 lokalnego kodu z kodem, kt\u00f3ry r\u00f3wnie\u017c jest kontrolowany pod k\u0105tem zmian, ale znajduje si\u0119 na serwerze zdalnym.<\/p>\n<h4>Synchronizacja zdalnego i lokalnego kodu<\/h4>\n<p>\nNa szcz\u0119\u015bcie, synchronizacja jest \u0142atwa z pomoc\u0105 nodeshift, a do \u015bledzenia zmian mo\u017cemy skorzysta\u0107 z polecenia watch.<\/p>\n<p>Tak wi\u0119c, po wykonaniu polecenia do wdro\u017cenia serwera deweloperskiego dla naszej aplikacji, mo\u017cemy \u015bmia\u0142o u\u017cywa\u0107 takiego polecenia:<\/p>\n<pre><code class=\"plaintext\">$ npx nodeshift watch\n<\/code><\/pre>\n<p>\nW wyniku tego nast\u0105pi po\u0142\u0105czenie z uruchomionym pod'em, kt\u00f3ry stworzyli\u015bmy wcze\u015bniej, aktywuje synchronizacj\u0119 naszych lokalnych plik\u00f3w z zdalnym klastrem, a pliki na naszym lokalnym systemie zaczn\u0105 by\u0107 monitorowane pod k\u0105tem zmian.<\/p>\n<p>Dlatego, je\u015bli teraz zaktualizujemy plik src\/App.js, system zareaguje na te zmiany, skopiuje je do zdalnego klastra i uruchomi serwer deweloperski, kt\u00f3ry nast\u0119pnie zaktualizuje nasz\u0105 aplikacj\u0119 w przegl\u0105darce.<\/p>\n<p>Dla pe\u0142nego obrazu poka\u017cemy, jak wygl\u0105daj\u0105 te polecenia w ca\u0142o\u015bci:<\/p>\n<pre><code class=\"plaintext\">$ npx nodeshift --strictSSL=false --dockerImage=nodeshift\/ubi8-s2i-web-app --build.env YARN_ENABLED=true --expose --deploy.env NPM_RUN=\"yarn start\" --deploy.port 3000\n\n$ npx nodeshift watch --strictSSL=false\n<\/code><\/pre>\n<p>\nPolecenie watch to abstrakcja nad poleceniem oc rsync, mo\u017cna dowiedzie\u0107 si\u0119 wi\u0119cej o tym, jak to dzia\u0142a <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.okd.io\/latest\/dev_guide\/copy_files_to_container.html\">tutaj<\/a><\/noindex>.<\/p>\n<p>To by\u0142 przyk\u0142ad dla React, ale dok\u0142adnie t\u0119 sam\u0105 metod\u0119 mo\u017cna zastosowa\u0107 z innymi frameworkami, wystarczy odpowiednio okre\u015bli\u0107 zmienn\u0105 \u015brodowiskow\u0105 NPM_RUN.<br \/>\n\u2003<\/p>\n<h3>Pipelines Openshift<\/h3>\n<p><img decoding=\"async\" alt=\"Wsp\u00f3\u0142czesne aplikacje na OpenShift, cz\u0119\u015b\u0107 3: OpenShift jako \u015brodowisko deweloperskie i pipelines OpenShift Pipelines\" src=\"\/wp-content\/uploads\/2020\/08\/33b932d3591b22dd00d82509b352d489.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Teraz porozmawiamy o narz\u0119dziu, jakim s\u0105 OpenShift Pipelines, i jak mo\u017cna je wykorzysta\u0107 jako alternatyw\u0119 dla powi\u0105zanych build\u00f3w chained build.<\/p>\n<h4>Czym s\u0105 OpenShift Pipelines<\/h4>\n<p>\nOpenShift Pipelines to chmurowy system CI\/CD do ci\u0105g\u0142ej integracji i dostarczania, zaprojektowany do organizowania potok\u00f3w przy u\u017cyciu Tekton. Tekton to elastyczny, natywny dla Kubernetes framework CI\/CD z otwartym kodem \u017ar\u00f3d\u0142owym, kt\u00f3ry pozwala na automatyzacj\u0119 wdra\u017cania na r\u00f3\u017cnych platformach (Kubernetes, serverless, maszyny wirtualne itp.) poprzez abstrakcj\u0119 od poziomu bazowego.<\/p>\n<p>Aby zrozumie\u0107 ten artyku\u0142, potrzebna jest okre\u015blona wiedza na temat Pipelines, dlatego stanowczo zalecamy najpierw zapozna\u0107 si\u0119 z <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/openshift\/pipelines-tutorial\">oficjalnym podr\u0119cznikiem<\/a><\/noindex>.<\/p>\n<h4>Konfiguracja \u015brodowiska roboczego<\/h4>\n<p>\nAby m\u00f3c wypr\u00f3bowa\u0107 przyk\u0142ady z tego artyku\u0142u, najpierw musisz przygotowa\u0107 \u015brodowisko robocze:<\/p>\n<ol>\n<li>Zainstalowa\u0107 i skonfigurowa\u0107 klaster OpenShift 4. W naszych przyk\u0142adach u\u017cywamy CodeReady Containers (CRD), a instrukcje dotycz\u0105ce instalacji mo\u017cna znale\u017a\u0107 <noindex><a rel=\"nofollow\" href=\"https:\/\/cloud.redhat.com\/openshift\/install\/crc\/installer-provisioned\">tutaj<\/a><\/noindex>.<\/li>\n<li>Po przygotowaniu klastra musisz zainstalowa\u0107 Pipeline Operator. Nie martw si\u0119, to proste, instrukcje dotycz\u0105ce instalacji <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/openshift\/pipelines-tutorial\/blob\/master\/install-operator.md\">tutaj<\/a><\/noindex>.<\/li>\n<li>Pobierz <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/tektoncd\/cli#installing-tkn\">Tekton CLI<\/a><\/noindex> (tkn) <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/tektoncd\/cli#installing-tkn\">tutaj<\/a><\/noindex>.<\/li>\n<li>Uruchom narz\u0119dzie wiersza polece\u0144 create-react-app, aby stworzy\u0107 aplikacj\u0119, kt\u00f3ra nast\u0119pnie zostanie wdro\u017cona (to prosta aplikacja <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/nodeshift-starters\/react-pipeline-example\">React<\/a><\/noindex>).<\/li>\n<li>(Opcjonalnie) Skopiuj repozytorium, aby lokalnie uruchomi\u0107 przyk\u0142ad aplikacji za pomoc\u0105 polecenia npm install, a nast\u0119pnie npm start.<\/li>\n<\/ol>\n<p>\nW repozytorium aplikacji znajdziesz r\u00f3wnie\u017c folder k8s, w kt\u00f3rym znajduj\u0105 si\u0119 pliki YAML Kubernetes\/OpenShift, u\u017cywane do wdra\u017cania aplikacji. B\u0119d\u0105 tam Tasks, ClusterTasks, Resources i Pipelines, kt\u00f3re stworzymy w tym <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/nodeshift\/webapp-pipeline-tutorial\">repozytorium<\/a><\/noindex>.<\/p>\n<h4>Zaczynamy<\/h4>\n<p>\nPierwszym krokiem w naszym przyk\u0142adzie jest stworzenie nowego projektu w klastrze OpenShift. Nazwijmy ten projekt webapp-pipeline i utw\u00f3rzmy go nast\u0119puj\u0105c\u0105 komend\u0105:<\/p>\n<pre><code class=\"plaintext\">$ oc new-project webapp-pipeline\n<\/code><\/pre>\n<p>\nNast\u0119pnie ta nazwa projektu b\u0119dzie wyst\u0119powa\u0107 w kodzie, wi\u0119c je\u015bli zdecydujesz si\u0119 nazwa\u0107 go inaczej, nie zapomnij odpowiednio zmodyfikowa\u0107 kodu w przyk\u0142adach. Od tego momentu b\u0119dziemy post\u0119powa\u0107 z do\u0142u do g\u00f3ry: to znaczy, na pocz\u0105tku stworzymy wszystkie sk\u0142adniki potoku, a dopiero potem sam potok.<\/p>\n<p>Tak wi\u0119c, na pocz\u0105tek...<\/p>\n<h4>Zadania Tasks<\/h4>\n<p>\nStworzymy kilka zada\u0144 (tasks), kt\u00f3re pomog\u0105 w wdro\u017ceniu aplikacji w ramach naszego konwoju pipeline. Pierwsze zadanie \u2013 apply_manifests_task \u2013 odpowiada za zastosowanie YAML tych zasob\u00f3w Kubernetes (service, deployment i route), kt\u00f3re znajduj\u0105 si\u0119 w folderze k8s naszej aplikacji. Drugie zadanie \u2013 update_deployment_task \u2013 odpowiada za aktualizacj\u0119 ju\u017c wdro\u017conego obrazu na nowy, kt\u00f3ry jest tworzony przez nasz konw\u00f3j.<\/p>\n<p>Nie martw si\u0119, je\u015bli to na razie nie jest jasne. W rzeczywisto\u015bci, te zadania to co\u015b w rodzaju narz\u0119dzi, kt\u00f3re om\u00f3wimy bardziej szczeg\u00f3\u0142owo p\u00f3\u017aniej. Na razie po prostu je stw\u00f3rzmy:<\/p>\n<pre><code class=\"plaintext\">$ oc create -f https:\/\/raw.githubusercontent.com\/nodeshift\/webapp-pipeline-tutorial\/master\/tasks\/update_deployment_task.yaml\n$ oc create -f https:\/\/raw.githubusercontent.com\/nodeshift\/webapp-pipeline-tutorial\/master\/tasks\/apply_manifests_task.yaml\n<\/code><\/pre>\n<p>\nNast\u0119pnie za pomoc\u0105 polecenia tkn CLI sprawdzimy, czy zadania zosta\u0142y utworzone:<\/p>\n<pre><code class=\"plaintext\">$ tkn task ls\n\nNAME                AGE\napply-manifests     1 minute ago\nupdate-deployment   1 minute ago\n<\/code><\/pre>\n<p>\n<i>Uwaga: to s\u0105 lokalne zadania twojego aktualnego projektu.<\/i><\/p>\n<h4>Zadania klastra Cluster tasks<\/h4>\n<p>\nZadania klastra to zasadniczo to samo, co po prostu zadania. To znaczy, \u017ce s\u0105 to wielokrotnego u\u017cytku kolekcje krok\u00f3w, kt\u00f3re s\u0105 \u0142\u0105czone w r\u00f3\u017cny spos\u00f3b podczas uruchamiania konkretnego zadania. R\u00f3\u017cnica polega na tym, \u017ce zadanie klastra jest dost\u0119pne wsz\u0119dzie w obr\u0119bie klastra. Aby zobaczy\u0107 list\u0119 zada\u0144 klastra, kt\u00f3re automatycznie tworz\u0105 si\u0119 po dodaniu Operatora Pipeline, ponownie u\u017cyjemy polecenia tkn CLI:<\/p>\n<pre><code class=\"plaintext\">$ tkn clustertask ls\n\nNAME                       AGE\nbuildah                    1 day ago\nbuildah-v0-10-0            1 day ago\njib-maven                  1 day ago\nkn                         1 day ago\nmaven                      1 day ago\nopenshift-client           1 day ago\nopenshift-client-v0-10-0   1 day ago\ns2i                        1 day ago\ns2i-go                     1 day ago\ns2i-go-v0-10-0             1 day ago\ns2i-java-11                1 day ago\ns2i-java-11-v0-10-0        1 day ago\ns2i-java-8                 1 day ago\ns2i-java-8-v0-10-0         1 day ago\ns2i-nodejs                 1 day ago\ns2i-nodejs-v0-10-0         1 day ago\ns2i-perl                   1 day ago\ns2i-perl-v0-10-0           1 day ago\ns2i-php                    1 day ago\ns2i-php-v0-10-0            1 day ago\ns2i-python-3               1 day ago\ns2i-python-3-v0-10-0       1 day ago\ns2i-ruby                   1 day ago\ns2i-ruby-v0-10-0           1 day ago\ns2i-v0-10-0                1 day ago\n<\/code><\/pre>\n<p>\nA teraz stw\u00f3rzmy dwa zadania klastra. Pierwsze b\u0119dzie generowa\u0107 obraz S2I i wysy\u0142a\u0107 go do wewn\u0119trznego rejestru OpenShift; drugie \u2013 budowa\u0107 nasz obraz oparty na NGINX, u\u017cywaj\u0105c jako zawarto\u015bci aplikacji, kt\u00f3r\u0105 ju\u017c stworzyli\u015bmy.<\/p>\n<h4>Tworzymy i wysy\u0142amy obraz<\/h4>\n<p>\nPodczas tworzenia pierwszego zadania powt\u00f3rzymy to, co ju\u017c zrobili\u015bmy w poprzednim artykule o powi\u0105zanych kompilacjach. Przypomnijmy, \u017ce u\u017cyli\u015bmy obrazu S2I (ubi8-s2i-web-app), aby \"zbudowa\u0107\" nasz\u0105 aplikacj\u0119, a ostatecznie uzyskali\u015bmy obraz, kt\u00f3ry by\u0142 przechowywany w wewn\u0119trznym rejestrze OpenShift. Teraz u\u017cyjemy tego obrazu S2I aplikacji webowej, aby stworzy\u0107 DockerFile dla naszej aplikacji, a nast\u0119pnie skorzystamy z Buildah, aby przeprowadzi\u0107 w\u0142a\u015bciw\u0105 kompilacj\u0119 i wys\u0142a\u0107 uzyskany obraz do wewn\u0119trznego rejestru OpenShift, poniewa\u017c to w\u0142a\u015bnie OpenShift robi, gdy wdra\u017casz swoje aplikacje za pomoc\u0105 NodeShift.<\/p>\n<p>Zadajecie pytanie, sk\u0105d to wszystko wiemy? Z <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/openshift\/pipelines-catalog\/blob\/master\/s2i-nodejs\/s2i-nodejs-task.yaml\">\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 official Node.js<\/a><\/noindex>, po prostu skopiowali\u015bmy j\u0105 i dostosowali\u015bmy do siebie.<\/p>\n<p>Zatem teraz tworzymy zadanie klastra s2i-web-app:<\/p>\n<pre><code class=\"plaintext\">$ oc create -f https:\/\/raw.githubusercontent.com\/nodeshift\/webapp-pipeline-tutorial\/master\/clustertasks\/s2i-web-app-task.yaml\n<\/code><\/pre>\n<p>\nNie b\u0119dziemy tego dok\u0142adnie analizowa\u0107, a jedynie zatrzymamy si\u0119 na parametrze OUTPUT_DIR:<\/p>\n<pre><code class=\"plaintext\">params:\n      - name: OUTPUT_DIR\n        description: Lokalizacja katalogu wyj\u015bciowego kompilacji\n        default: build\n<\/code><\/pre>\n<p>\nDomy\u015blnie ten parametr wynosi build, to w\u0142a\u015bnie tam React umieszcza skompilowane tre\u015bci. W innych frameworkach u\u017cywane s\u0105 inne \u015bcie\u017cki, na przyk\u0142ad, w Ember to dist. Wynik naszego pierwszego zadania klastra b\u0119dzie stanowi\u0142 obraz zawieraj\u0105cy skompilowane przez nas HTML, JavaScript i CSS.<\/p>\n<h4>Budujemy obraz na bazie NGINX<\/h4>\n<p>\nJe\u015bli chodzi o nasze drugie zadanie klastra, powinno ono zbiera\u0107 dla nas obraz na podstawie NGINX, u\u017cywaj\u0105c tre\u015bci wcze\u015bniej skompilowanej aplikacji. W zasadzie to ta cz\u0119\u015b\u0107 poprzedniego rozdzia\u0142u, w kt\u00f3rej omawiali\u015bmy powi\u0105zane kompilacje chained builds.<\/p>\n<p>Aby to zrobi\u0107 \u2013 dok\u0142adnie tak, jak troch\u0119 wy\u017cej \u2013 stworzymy zadanie klastra webapp-build-runtime:<\/p>\n<pre><code class=\"plaintext\">$ oc create -f https:\/\/raw.githubusercontent.com\/nodeshift\/webapp-pipeline-tutorial\/master\/clustertasks\/webapp-build-runtime-task.yaml\n<\/code><\/pre>\n<p>\nJe\u015bli spojrze\u0107 na kod tych zada\u0144 klastra, wida\u0107, \u017ce nie podano konkretnego repozytorium Git, z kt\u00f3rym pracujemy, ani nazw obraz\u00f3w, kt\u00f3re tworzymy. Wskazujemy jedynie, co dok\u0142adnie przekazujemy do Git lub jakiego\u015b obrazu, w kt\u00f3ry ma zosta\u0107 wyprowadzony obraz ko\u0144cowy. Dlatego te zadania klastra mo\u017cna ponownie wykorzysta\u0107 tak\u017ce przy pracy z innymi aplikacjami.<\/p>\n<p>I tutaj w elegancki spos\u00f3b przechodzimy do nast\u0119pnego punktu\u2026<\/p>\n<h4>Resources<\/h4>\n<p>\nZatem, poniewa\u017c, jak w\u0142a\u015bnie powiedzieli\u015bmy, zadania klastrowe musz\u0105 by\u0107 jak najbardziej og\u00f3lne, musimy stworzy\u0107 zasoby, kt\u00f3re b\u0119d\u0105 u\u017cywane na wej\u015bciu (repozytorium Git) i na wyj\u015bciu (ostateczne obrazy). Pierwszym zasobem, kt\u00f3rego potrzebujemy, jest Git, gdzie znajduje si\u0119 nasza aplikacja, co\u015b takiego jak:<\/p>\n<pre><code class=\"plaintext\"># This resource is the location of the git repo with the web application source\napiVersion: tekton.dev\/v1alpha1\nkind: PipelineResource\nmetadata:\n  name: web-application-repo\nspec:\n  type: git\n  params:\n    - name: url\n      value: https:\/\/github.com\/nodeshift-starters\/react-pipeline-example\n    - name: revision\n      value: master\n<\/code><\/pre>\n<p>\nTutaj PipelineResource ma typ git. Klucz url w sekcji params wskazuje na konkretne repozytorium i ustawia ga\u0142\u0105\u017a master (to jest opcjonalne, ale piszemy to dla pe\u0142no\u015bci).<\/p>\n<p>Teraz musimy stworzy\u0107 zas\u00f3b dla obrazu, gdzie b\u0119d\u0105 przechowywane wyniki wykonania zadania s2i-web-app, robi si\u0119 to w ten spos\u00f3b:<\/p>\n<pre><code class=\"plaintext\"># This resource is the result of running &quot;npm run build&quot;,  the resulting built files will be located in \/opt\/app-root\/output\napiVersion: tekton.dev\/v1alpha1\nkind: PipelineResource\nmetadata:\n  name: built-web-application-image\nspec:\n  type: image\n  params:\n    - name: url\n      value: image-registry.openshift-image-registry.svc:5000\/webapp-pipeline\/built-web-application:latest\n<\/code><\/pre>\n<p>\nTutaj PipelineResource ma typ image, a warto\u015b\u0107 parametru url wskazuje na wewn\u0119trzny OpenShift Image Registry, konkretnie na ten, kt\u00f3ry znajduje si\u0119 w przestrzeni nazw webapp-pipeline. Nie zapomnij zmieni\u0107 tego parametru, je\u015bli u\u017cywasz innej przestrzeni nazw.<\/p>\n<p>I w ko\u0144cu, ostatni zas\u00f3b, kt\u00f3rego b\u0119dziemy potrzebowa\u0107, r\u00f3wnie\u017c b\u0119dzie mia\u0142 typ image i to b\u0119dzie ko\u0144cowy obraz NGINX, kt\u00f3ry nast\u0119pnie b\u0119dzie u\u017cywany podczas wdra\u017cania:<\/p>\n<pre><code class=\"plaintext\"># This resource is the image that will be just the static html, css, js files being run with nginx\napiVersion: tekton.dev\/v1alpha1\nkind: PipelineResource\nmetadata:\n  name: runtime-web-application-image\nspec:\n  type: image\n  params:\n    - name: url\n      value: image-registry.openshift-image-registry.svc:5000\/webapp-pipeline\/runtime-web-application:latest\n<\/code><\/pre>\n<p>\nI ponownie zwr\u00f3\u0107 uwag\u0119, \u017ce ten zas\u00f3b przechowuje obraz w wewn\u0119trznym rejestrze OpenShift w przestrzeni nazw webapp-pipeline.<\/p>\n<p>Aby jednocze\u015bnie stworzy\u0107 wszystkie te zasoby, skorzystamy z polecenia create:<\/p>\n<pre><code class=\"plaintext\">$ oc create -f https:\/\/raw.githubusercontent.com\/nodeshift\/webapp-pipeline-tutorial\/master\/resources\/resource.yaml\n<\/code><\/pre>\n<p>\nMo\u017cna sprawdzi\u0107, czy zasoby zosta\u0142y stworzone w ten spos\u00f3b:<\/p>\n<pre><code class=\"plaintext\">$ tkn resource ls\n<\/code><\/pre>\n<p><\/p>\n<h4>Ruroci\u0105g (pipeline)<\/h4>\n<p>\nTeraz, gdy mamy wszystkie niezb\u0119dne sk\u0142adniki, zbudujmy z nich ruroci\u0105g, tworz\u0105c go nast\u0119puj\u0105cym poleceniem:<\/p>\n<pre><code class=\"plaintext\">$ oc create -f https:\/\/raw.githubusercontent.com\/nodeshift\/webapp-pipeline-tutorial\/master\/pipelines\/build-and-deploy-react.yaml\n<\/code><\/pre>\n<p>\nAle zanim uruchomimy to polecenie, rozwa\u017cmy te sk\u0142adniki. Pierwszym jest nazwa:<\/p>\n<pre><code class=\"plaintext\">apiVersion: tekton.dev\/v1alpha1\nkind: Pipeline\nmetadata:\n  name: build-and-deploy-react\n<\/code><\/pre>\n<p>\nNast\u0119pnie w sekcji spec widzimy wskazanie zasob\u00f3w, kt\u00f3re stworzyli\u015bmy wcze\u015bniej:<\/p>\n<pre><code class=\"plaintext\">spec:\n  resources:\n    - name: web-application-repo\n      type: git\n    - name: built-web-application-image\n      type: image\n    - name: runtime-web-application-image\n      type: image\n<\/code><\/pre>\n<p>\nNast\u0119pnie tworzymy zadania, kt\u00f3re ma wykona\u0107 nasz ruroci\u0105g. Na pocz\u0105tku musi wykona\u0107 ju\u017c stworzone przez nas zadanie s2i-web-app:<\/p>\n<pre><code class=\"plaintext\">tasks:\n    - name: build-web-application\n      taskRef:\n        name: s2i-web-app\n        kind: ClusterTask\n<\/code><\/pre>\n<p>\nTo zadanie pobiera wej\u015bciowe (zas\u00f3b gir) i wyj\u015bciowe (zas\u00f3b built-web-application-image) parametry. Przekazujemy jej r\u00f3wnie\u017c specjalny parametr, aby nie weryfikowa\u0142a TLS, poniewa\u017c u\u017cywamy certyfikat\u00f3w samopodpisanych:<\/p>\n<pre><code class=\"plaintext\">resources:\n        inputs:\n          - name: source\n            resource: web-application-repo\n        outputs:\n          - name: image\n            resource: built-web-application-image\n      params:\n        - name: TLSVERIFY\n          value: \"false\"\n<\/code><\/pre>\n<p>\nNast\u0119pne zadanie jest prawie takie same, tylko w tym przypadku wywo\u0142ujemy ju\u017c utworzone przez nas zadanie klastra webapp-build-runtime:<\/p>\n<pre><code class=\"plaintext\">nazwa: build-runtime-image\n    odwo\u0142anieZadania:\n      nazwa: webapp-build-runtime\n      rodzaj: ClusterTask\n<\/code><\/pre>\n<p>\nPodobnie jak w poprzednim zadaniu, przekazujemy zas\u00f3b, ale teraz jest to built-web-application-image (wyj\u015bcie naszego poprzedniego zadania). A jako wyj\u015bcie ponownie okre\u015blamy obraz. Poniewa\u017c to zadanie musi by\u0107 wykonane po poprzednim, dodajemy pole runAfter:<\/p>\n<pre><code class=\"plaintext\">resources:\n        inputs:\n          - name: image\n            resource: built-web-application-image\n        outputs:\n          - name: image\n            resource: runtime-web-application-image\n        params:\n        - name: TLSVERIFY\n          value: \"false\"\n      runAfter:\n        - build-web-application\n<\/code><\/pre>\n<p>\nNast\u0119pne dwa zadania odpowiadaj\u0105 za zastosowanie plik\u00f3w YAML us\u0142ugi, trasy i wdro\u017cenia, kt\u00f3re znajduj\u0105 si\u0119 w katalogu k8s naszego aplikacji webowej, a tak\u017ce za aktualizowanie tego wdro\u017cenia przy tworzeniu nowych obraz\u00f3w. Te dwa zadania klastra zdefiniowali\u015bmy ju\u017c na pocz\u0105tku artyku\u0142u.<\/p>\n<h4>Uruchamianie potoku<\/h4>\n<p>\nWszystkie cz\u0119\u015bci naszego potoku zosta\u0142y utworzone, a my uruchomimy go nast\u0119puj\u0105c\u0105 komend\u0105:<\/p>\n<pre><code class=\"plaintext\">$ tkn pipeline start build-and-deploy-react\n<\/code><\/pre>\n<p>\nNa tym etapie wiersz polece\u0144 dzia\u0142a w trybie interaktywnym i nale\u017cy wybiera\u0107 odpowiednie zasoby w odpowiedzi na ka\u017cde jego zapytanie: dla zasobu git wybieramy web-application-repo, nast\u0119pnie dla zasobu pierwszego obrazu \u2013 built-web-application-image, a na koniec dla zasobu drugiego obrazu \u2013 runtime-web-application-image:<\/p>\n<pre><code class=\"plaintext\">? Choose the git resource to use for web-application-repo: web-application-repo (https:\/\/github.com\/nodeshift-starters\/react-pipeline-example)\n? Choose the image resource to use for built-web-application-image: built-web-application-image (image-registry.openshift-image-registry.svc:5000\/webapp-pipeline\/built-web-\napplication:latest)\n? Choose the image resource to use for runtime-web-application-image: runtime-web-application-image (image-registry.openshift-image-registry.svc:5000\/webapp-pipeline\/runtim\ne-web-application:latest)\nPipelinerun started: build-and-deploy-react-run-4xwsr\n<\/code><\/pre>\n<p>\nTeraz sprawdzimy status potoku za pomoc\u0105 nast\u0119puj\u0105cej komendy:<\/p>\n<pre><code class=\"plaintext\">$ tkn pipeline logs -f\n<\/code><\/pre>\n<p>\nPo uruchomieniu potoku i wdro\u017ceniu aplikacji, zapytamy o opublikowan\u0105 tras\u0119 nast\u0119puj\u0105c\u0105 komend\u0105:<\/p>\n<pre><code class=\"plaintext\">$ oc get route react-pipeline-example --template='http:\/\/{{.spec.host}}'\n<\/code><\/pre>\n<p>\nAby uzyska\u0107 lepsz\u0105 wizualno\u015b\u0107, mo\u017cemy zobaczy\u0107 nasz potok w trybie dewelopera w sekcji <b>Pipelines<\/b>, jak pokazano na Rys. 1.<\/p>\n<p><img decoding=\"async\" alt=\"Wsp\u00f3\u0142czesne aplikacje na OpenShift, cz\u0119\u015b\u0107 3: OpenShift jako \u015brodowisko deweloperskie i pipelines OpenShift Pipelines\" src=\"\/wp-content\/uploads\/2020\/08\/ede9b076414e389c2cd212adeda08956.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><i>Rys. 1. Przegl\u0105d uruchomionych potok\u00f3w.<\/i><\/p>\n<p>Klikni\u0119cie na uruchomiony potok wy\u015bwietla dodatkowe informacje, jak pokazano na Rys. 2.<\/p>\n<p><img decoding=\"async\" alt=\"Wsp\u00f3\u0142czesne aplikacje na OpenShift, cz\u0119\u015b\u0107 3: OpenShift jako \u015brodowisko deweloperskie i pipelines OpenShift Pipelines\" src=\"\/wp-content\/uploads\/2020\/08\/64581b1f6d8ff91aedd963019ef29be5.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><i>Rys. 2. Dodatkowe informacje o potoku.<\/i><\/p>\n<p>Po dodatkowych informacjach mo\u017cna zobaczy\u0107 uruchomione aplikacje w widoku <b>Topology<\/b>, jak pokazano na Rys. 3.<\/p>\n<p><img decoding=\"async\" alt=\"Wsp\u00f3\u0142czesne aplikacje na OpenShift, cz\u0119\u015b\u0107 3: OpenShift jako \u015brodowisko deweloperskie i pipelines OpenShift Pipelines\" src=\"\/wp-content\/uploads\/2020\/08\/d23f723e14514ff60ecfddd8eb9bf752.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><i>Rys 3. Uruchomiony pod.<\/i><\/p>\n<p>Klikni\u0119cie w k\u00f3\u0142ko w prawym g\u00f3rnym rogu ikony otwiera nasz\u0105 aplikacj\u0119, jak pokazano na Rys. 4.<\/p>\n<p><img decoding=\"async\" alt=\"Wsp\u00f3\u0142czesne aplikacje na OpenShift, cz\u0119\u015b\u0107 3: OpenShift jako \u015brodowisko deweloperskie i pipelines OpenShift Pipelines\" src=\"\/wp-content\/uploads\/2020\/08\/aa8e09d9fd9f33d5faffc7f661d84ca4.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><i>Rys. 4. Uruchomiona aplikacja React.<\/i><\/p>\n<h3>Podsumowanie<\/h3>\n<p>\nTak, pokazali\u015bmy, jak uruchomi\u0107 na OpenShift serwer deweloperski dla swojej aplikacji i zsynchronizowa\u0107 go z lokalnym systemem plik\u00f3w. Zbadali\u015bmy r\u00f3wnie\u017c, jak zasymulowa\u0107 szablon chained-build przy u\u017cyciu OpenShift Pipelines. Wszystkie kody przyk\u0142ad\u00f3w z tego artyku\u0142u mo\u017cna znale\u017a\u0107 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/nodeshift\/webapp-pipeline-tutorial\">tutaj<\/a><\/noindex>.<\/p>\n<h3>Dodatkowe zasoby (EN)<\/h3>\n<p><\/p>\n<ul>\n<li>Darmowa e-ksi\u0105\u017cka <noindex><a rel=\"nofollow\" href=\"https:\/\/developers.redhat.com\/books\/deploying-openshift\/\">\u201eRozw\u00f3j na OpenShift: przewodnik dla niecierpliwych\u201d<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/developers.redhat.com\/blog\/2018\/06\/11\/container-native-nodejs-istio-rhoar\/\">Budowanie aplikacji opartych na kontenerach Node.js z u\u017cyciem Red Hat OpenShift Application Runtimes i Istio<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/developers.redhat.com\/blog\/2018\/05\/15\/debug-your-node-js-application-on-openshift-with-chrome-devtools\/\">Debugowanie aplikacji Node.js na OpenShift przy u\u017cyciu Chrome DevTools<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/developers.redhat.com\/blog\/2018\/04\/16\/zero-express-openshift-3-commands\/\">Trzy polecenia, aby od podstaw opanowa\u0107 Express na OpenShift<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/developers.redhat.com\/blog\/2018\/03\/12\/rhoar-nodejs-annoucement\/\">Og\u0142oszenie publicznej wersji Node.js w sk\u0142adzie Red Hat OpenShift Application Runtimes<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/developers.redhat.com\/blog\/2018\/12\/21\/monitoring-node-js-applications-on-openshift-with-prometheus\/\">Monitorowanie aplikacji Node.js na OpenShift z u\u017cyciem Prometheus<\/a><\/noindex><\/li>\n<li>Inne artyku\u0142y na temat <noindex><a rel=\"nofollow\" href=\"https:\/\/developers.redhat.com\/topics\/kubernetes\/\">OpenShift i Kubernetes<\/a><\/noindex> na stronie Red Hat<\/li>\n<\/ul>\n<h3>Zapowiedzi nadchodz\u0105cych webinar\u00f3w<\/h3>\n<p>\nRozpoczynamy seri\u0119 pi\u0105tkowych webinar\u00f3w na temat natywnego do\u015bwiadczenia korzystania z Red Hat OpenShift Container Platform i Kubernetes:<\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/events.redhat.com\/profile\/form\/index.cfm?PKformID=0x232599abcd&amp;sc_cid=7013a000002gwqQAAQ\"><b>28 sierpnia, webinar Imperator \u201eOperator\u201d: Operatory w OpenShift i Kubernetes<\/b><\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/events.redhat.com\/profile\/form\/index.cfm?PKformID=0x232694abcd&amp;sc_cid=7013a000002gwrdAAA\"><b>11 wrze\u015bnia, DeploymentConfig vs Deployment \u2013 specyficzne dla OpenShift magiczne rzeczy do budowy i wdra\u017cania aplikacji<\/b><\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/events.redhat.com\/profile\/form\/index.cfm?PKformID=0x232789abcd&amp;sc_cid=7013a000002gws7AAA\"><b>25 wrze\u015bnia, Red Hat OpenShift i Machine API<\/b><\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/events.redhat.com\/profile\/form\/index.cfm?PKformID=0x232884abcd&amp;sc_cid=7013a000002gwsqAAA\"><b>9 pa\u017adziernika, Jak radzi\u0107 sobie z nag\u0142ym wzrostem obci\u0105\u017cenia<\/b><\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/events.redhat.com\/profile\/form\/index.cfm?PKformID=0x232979abcd&amp;sc_cid=7013a000002gwumAAA\"><b>23 pa\u017adziernika, Wbudowany Jenkins, Pipeline-builds, Tekton w Red Hat OpenShift Container Platform<\/b><\/a><\/noindex><\/li>\n<\/ul>\n<p>\u0179r\u00f3d\u0142o: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/redhatrussia\/blog\/515988\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u0432\u0435\u0442 \u0432\u0441\u0435\u043c \u0432 \u044d\u0442\u043e\u043c \u0431\u043b\u043e\u0433\u0435! \u0421 \u0432\u0430\u043c\u0438 \u0442\u0440\u0435\u0442\u0438\u0439 \u043f\u043e\u0441\u0442 \u0438\u0437 \u0441\u0435\u0440\u0438\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u043a\u0430\u043a \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0442\u044c \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 Red Hat OpenShift. \u0412 \u0434\u0432\u0443\u0445 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u043f\u043e\u0441\u0442\u0430\u0445 \u043c\u044b \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u043b\u0438, \u043a\u0430\u043a \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0442\u044c \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0433\u043e \u0437\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0448\u0430\u0433\u043e\u0432 \u0438 \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u0440\u0430\u0437 S2I \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0433\u043e\u0442\u043e\u0432\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c HTTP-\u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, NGINX \u0441 \u043f\u043e\u043c\u043e\u0449\u044c \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441\u0431\u043e\u0440\u043e\u043a chained [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":92049,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-92048","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=\"\u041f\u0440\u0438\u0432\u0435\u0442 \u0432\u0441\u0435\u043c \u0432 \u044d\u0442\u043e\u043c \u0431\u043b\u043e\u0433\u0435!\" \/>\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\/pl\/blog\/administrirovanie\/sovremennye-prilozheniya-na-openshift-chast-3-openshift-kak-sreda-razrabotki-i-konvejery-openshift-pipelines\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\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\udd47\u0421\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 OpenShift, \u0447\u0430\u0441\u0442\u044c 3: OpenShift \u043a\u0430\u043a \u0441\u0440\u0435\u0434\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u044b OpenShift Pipelines | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0438\u0432\u0435\u0442 \u0432\u0441\u0435\u043c \u0432 \u044d\u0442\u043e\u043c \u0431\u043b\u043e\u0433\u0435!\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/sovremennye-prilozheniya-na-openshift-chast-3-openshift-kak-sreda-razrabotki-i-konvejery-openshift-pipelines\" \/>\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=\"2020-08-22T05:42:57+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-08-22T05:42:57+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\udd47Nowoczesne aplikacje na OpenShift, cz\u0119\u015b\u0107 3: OpenShift jako \u015brodowisko deweloperskie i konwertery OpenShift Pipelines | ProHoster","description":"Cze\u015b\u0107 wszystkim na tym blogu!","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/sovremennye-prilozheniya-na-openshift-chast-3-openshift-kak-sreda-razrabotki-i-konvejery-openshift-pipelines","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pl_PL","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\udd47\u0421\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 OpenShift, \u0447\u0430\u0441\u0442\u044c 3: OpenShift \u043a\u0430\u043a \u0441\u0440\u0435\u0434\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u044b OpenShift Pipelines | ProHoster","og:description":"\u041f\u0440\u0438\u0432\u0435\u0442 \u0432\u0441\u0435\u043c \u0432 \u044d\u0442\u043e\u043c \u0431\u043b\u043e\u0433\u0435!","og:url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/sovremennye-prilozheniya-na-openshift-chast-3-openshift-kak-sreda-razrabotki-i-konvejery-openshift-pipelines","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":"2020-08-22T05:42:57+00:00","article:modified_time":"2020-08-22T05:42:57+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"92048","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":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 12:16:43","updated":"2022-10-02 02:53:55","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/92048","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=92048"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/92048\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media\/92049"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=92048"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=92048"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=92048"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}