{"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\/pt\/blog\/administrirovanie\/sovremennye-prilozheniya-na-openshift-chast-3-openshift-kak-sreda-razrabotki-i-konvejery-openshift-pipelines","title":{"rendered":"Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Ol\u00e1 a todos neste blog! Este \u00e9 o terceiro post de uma s\u00e9rie onde mostramos como implantar aplica\u00e7\u00f5es web modernas no Red Hat OpenShift.<\/p>\n<p><img decoding=\"async\" alt=\"Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift\" src=\"\/wp-content\/uploads\/2020\/08\/9c3337b13a3f045d36343308ce6154cc.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNos dois posts anteriores, falamos sobre como implantar aplica\u00e7\u00f5es web modernas em apenas alguns passos e como utilizar a nova imagem S2I junto com uma imagem pronta de servidor HTTP, como o NGINX, com a ajuda de builds encadeados (chained builds) para organizar a implanta\u00e7\u00e3o em produ\u00e7\u00e3o.<\/p>\n<p>Hoje, mostraremos como iniciar na plataforma OpenShift um servidor de desenvolvimento para sua aplica\u00e7\u00e3o e sincroniz\u00e1-lo com o sistema de arquivos local, al\u00e9m de discutir o que s\u00e3o os OpenShift Pipelines e como podem ser aplicados como uma alternativa aos builds encadeados.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3>OpenShift como ambiente de desenvolvimento<\/h3>\n<p><\/p>\n<h4>Fluxo de trabalho de desenvolvimento<\/h4>\n<p>\nComo mencionado no <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/redhatrussia\/blog\/511954\/\">primeiro post<\/a><\/noindex>, o processo t\u00edpico de desenvolvimento para aplica\u00e7\u00f5es web modernas \u00e9 simplesmente um \"servidor de desenvolvimento\" que monitora mudan\u00e7as nos arquivos locais. Quando ocorrem, uma nova build da aplica\u00e7\u00e3o \u00e9 iniciada e, em seguida, ela \u00e9 atualizada no navegador.<\/p>\n<p>Na maioria dos frameworks modernos, um \"servidor de desenvolvimento\" est\u00e1 embutido nas ferramentas de linha de comando apropriadas.<\/p>\n<h4>Exemplo local<\/h4>\n<p>\nPara come\u00e7ar, vamos ver como isso funciona no caso de uma execu\u00e7\u00e3o local de aplica\u00e7\u00f5es. Como exemplo, usaremos a aplica\u00e7\u00e3o <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/lholmquist\/react-web-app\">React<\/a><\/noindex> dos artigos anteriores, embora praticamente os mesmos conceitos de fluxo de trabalho se apliquem a todos os outros frameworks modernos.<br \/>\nEnt\u00e3o, para iniciar o \"servidor de desenvolvimento\" em nosso exemplo com React, digitamos o seguinte comando:<\/p>\n<pre><code class=\"plaintext\">$ npm run start\n<\/code><\/pre>\n<p>\nEnt\u00e3o, na janela do terminal, veremos algo como o seguinte:<\/p>\n<p><img decoding=\"async\" alt=\"Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift\" src=\"\/wp-content\/uploads\/2020\/08\/06f84ffb4c9a6a5868b8b47b8ad1d9ec.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>E nossa aplica\u00e7\u00e3o ser\u00e1 aberta no navegador padr\u00e3o:<\/p>\n<p><img decoding=\"async\" alt=\"Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift\" src=\"\/wp-content\/uploads\/2020\/08\/72341bb0796352e7343bf31ceb8233cd.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Agora, se fizermos altera\u00e7\u00f5es no arquivo, a aplica\u00e7\u00e3o dever\u00e1 ser atualizada no navegador.<\/p>\n<p>OK, o desenvolvimento em modo local est\u00e1 claro, mas como obter o mesmo no OpenShift?<\/p>\n<h4>Servidor de desenvolvimento no OpenShift<\/h4>\n<p>\nSe voc\u00ea se lembra, no <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/redhatrussia\/blog\/513948\/\">post anterior<\/a><\/noindex>, discutimos a fase de execu\u00e7\u00e3o (run phase) da imagem S2I e vimos que, por padr\u00e3o, o m\u00f3dulo serve \u00e9 respons\u00e1vel por atender nossa aplica\u00e7\u00e3o web.<\/p>\n<p>No entanto, se olharmos mais de perto <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/nodeshift\/ubi8-s2i-web-app\/blob\/master\/s2i\/run#L10\">script run<\/a><\/noindex> No exemplo, h\u00e1 a vari\u00e1vel de ambiente $NPM_RUN, que permite executar seu pr\u00f3prio comando.<\/p>\n<p>Por exemplo, podemos usar o m\u00f3dulo nodeshift para implantar nosso aplicativo:<\/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>Nota: o exemplo acima \u00e9 apresentado de forma resumida para ilustrar a ideia geral.<\/i><\/p>\n<p>Aqui, adicionamos \u00e0 nossa implanta\u00e7\u00e3o a vari\u00e1vel de ambiente NPM_RUN, que informa \u00e0 etapa de execu\u00e7\u00e3o que deve iniciar o comando yarn start, que inicia o servidor de desenvolvimento React dentro do nosso pod no OpenShift.<\/p>\n<p>Se olharmos os logs do pod em execu\u00e7\u00e3o, veremos algo como:<\/p>\n<p><img decoding=\"async\" alt=\"Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift\" src=\"\/wp-content\/uploads\/2020\/08\/5b090223e08e32a3356608881068ce1a.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Claro, isso n\u00e3o ter\u00e1 valor at\u00e9 que possamos sincronizar o c\u00f3digo local com o c\u00f3digo que tamb\u00e9m est\u00e1 sob controle de altera\u00e7\u00f5es, mas reside em um servidor remoto.<\/p>\n<h4>Sincroniza\u00e7\u00e3o do c\u00f3digo remoto e local<\/h4>\n<p>\nFelizmente, a sincroniza\u00e7\u00e3o \u00e9 facilitada pelo nodeshift, e para rastrear altera\u00e7\u00f5es, podemos usar o comando watch.<\/p>\n<p>Assim, ap\u00f3s executarmos o comando para implantar o servidor de desenvolvimento do nosso aplicativo, podemos usar o seguinte comando:<\/p>\n<pre><code class=\"plaintext\">$ npx nodeshift watch\n<\/code><\/pre>\n<p>\nComo resultado, ser\u00e1 estabelecida uma conex\u00e3o com o pod em execu\u00e7\u00e3o que criamos anteriormente, a sincroniza\u00e7\u00e3o de nossos arquivos locais com o cluster remoto ser\u00e1 ativada e os arquivos em nosso sistema local come\u00e7ar\u00e3o a ser monitorados quanto a altera\u00e7\u00f5es.<\/p>\n<p>Portanto, se agora atualizarmos o arquivo src\/App.js, o sistema reagir\u00e1 a essas altera\u00e7\u00f5es, copiar\u00e1 para o cluster remoto e iniciar\u00e1 o servidor de desenvolvimento, que ent\u00e3o atualizar\u00e1 nosso aplicativo no navegador.<\/p>\n<p>Para completar o quadro, vamos mostrar como esses comandos se parecem na \u00edntegra:<\/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>\nO comando watch \u00e9 uma abstra\u00e7\u00e3o sobre o comando oc rsync; mais detalhes sobre como isso funciona podem ser encontrados. <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.okd.io\/latest\/dev_guide\/copy_files_to_container.html\">aqui<\/a><\/noindex>.<\/p>\n<p>Este foi um exemplo para React, mas o mesmo m\u00e9todo pode ser usado com outros frameworks, basta definir a vari\u00e1vel de ambiente NPM_RUN corretamente.<br \/>\n\u2003<\/p>\n<h3>Pipelines do OpenShift<\/h3>\n<p><img decoding=\"async\" alt=\"Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift\" src=\"\/wp-content\/uploads\/2020\/08\/33b932d3591b22dd00d82509b352d489.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>A seguir, falaremos sobre uma ferramenta chamada OpenShift Pipelines e como ela pode ser usada como uma alternativa \u00e0s compila\u00e7\u00f5es encadeadas.<\/p>\n<h4>O que s\u00e3o OpenShift Pipelines<\/h4>\n<p>\nOpenShift Pipelines \u00e9 um sistema de CI\/CD baseado na nuvem, projetado para organizar pipelines utilizando Tekton. Tekton \u00e9 um framework CI\/CD flex\u00edvel, nativo do Kubernetes e de c\u00f3digo aberto, que permite automatizar a implementa\u00e7\u00e3o em v\u00e1rias plataformas (Kubernetes, serverless, m\u00e1quinas virtuais etc.) ao abstrair o n\u00edvel subjacente.<\/p>\n<p>Para entender este artigo, s\u00e3o necess\u00e1rios alguns conhecimentos sobre Pipelines, portanto, recomendamos fortemente que voc\u00ea comece consultando o <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/openshift\/pipelines-tutorial\">manual oficial<\/a><\/noindex>.<\/p>\n<h4>Configurando o ambiente de trabalho<\/h4>\n<p>\nPara experimentar os exemplos deste artigo, primeiro voc\u00ea precisa preparar o ambiente de trabalho:<\/p>\n<ol>\n<li>Instalar e configurar um cluster OpenShift 4. Em nossos exemplos, utilizamos o CodeReady Containers (CRD), cujas instru\u00e7\u00f5es de instala\u00e7\u00e3o podem ser encontradas <noindex><a rel=\"nofollow\" href=\"https:\/\/cloud.redhat.com\/openshift\/install\/crc\/installer-provisioned\">aqui<\/a><\/noindex>.<\/li>\n<li>Depois que o cluster estiver pronto, voc\u00ea deve instalar o Pipeline Operator. N\u00e3o se preocupe, \u00e9 f\u00e1cil, as instru\u00e7\u00f5es para instala\u00e7\u00e3o est\u00e3o <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/openshift\/pipelines-tutorial\/blob\/master\/install-operator.md\">aqui<\/a><\/noindex>.<\/li>\n<li>Baixar <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\">aqui<\/a><\/noindex>.<\/li>\n<li>Executar a ferramenta de linha de comando create-react-app para criar um aplicativo que ser\u00e1 implantado depois (este \u00e9 um aplicativo simples <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/nodeshift-starters\/react-pipeline-example\">React<\/a><\/noindex>).<\/li>\n<li>(Opcional) Clonar o reposit\u00f3rio para executar localmente o exemplo do aplicativo com o comando npm install e, em seguida, npm start.<\/li>\n<\/ol>\n<p>\nNo reposit\u00f3rio do aplicativo tamb\u00e9m haver\u00e1 uma pasta k8s, onde estar\u00e3o os YAMLs do Kubernetes\/OpenShift usados para a implanta\u00e7\u00e3o do aplicativo. Haver\u00e1 Tasks, ClusterTasks, Resources e Pipelines que criaremos neste <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/nodeshift\/webapp-pipeline-tutorial\">reposit\u00f3rio<\/a><\/noindex>.<\/p>\n<h4>Vamos come\u00e7ar<\/h4>\n<p>\nPrimeiramente, para nosso exemplo, precisamos criar um novo projeto no cluster OpenShift. Vamos chamar este projeto de webapp-pipeline e criar com o seguinte comando:<\/p>\n<pre><code class=\"plaintext\">$ oc new-project webapp-pipeline\n<\/code><\/pre>\n<p>\nA partir de agora, esse nome de projeto aparecer\u00e1 no c\u00f3digo, ent\u00e3o, se voc\u00ea decidir nome\u00e1-lo de forma diferente, n\u00e3o se esque\u00e7a de ajustar o c\u00f3digo dos exemplos apropriadamente. A partir daqui, iremos de baixo para cima: ou seja, primeiro criaremos todos os componentes do pipeline antes de criar o pr\u00f3prio.<\/p>\n<p>Ent\u00e3o, primeiro...<\/p>\n<h4>Tarefas Tasks<\/h4>\n<p>\nVamos criar duas tarefas (tasks), que depois ajudar\u00e3o a implantar o aplicativo dentro do nosso pipeline. A primeira tarefa \u2013 apply_manifests_task \u2013 \u00e9 respons\u00e1vel por aplicar os recursos YAML do Kubernetes (service, deployment e route) que est\u00e3o na pasta k8s do nosso aplicativo. A segunda tarefa \u2013 update_deployment_task \u2013 \u00e9 respons\u00e1vel por atualizar a imagem j\u00e1 implantada para a que est\u00e1 sendo criada pelo nosso pipeline.<\/p>\n<p>N\u00e3o se preocupe se ainda n\u00e3o estiver muito claro. Na verdade, essas tarefas s\u00e3o como utilit\u00e1rios, e n\u00f3s as exploraremos com mais detalhes mais tarde. Por enquanto, apenas vamos cri\u00e1-las:<\/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>\nEm seguida, usaremos o comando tkn CLI para verificar se as tarefas foram criadas:<\/p>\n<pre><code class=\"plaintext\">$ tkn task ls\n\nNOME                IDADE\napply-manifests     1 minuto atr\u00e1s\nupdate-deployment   1 minuto atr\u00e1s\n<\/code><\/pre>\n<p>\n<i>Nota: estas s\u00e3o tarefas locais do seu projeto atual.<\/i><\/p>\n<h4>Tarefas do Cluster<\/h4>\n<p>\nTarefas do Cluster s\u00e3o basicamente a mesma coisa que apenas tarefas. Ou seja, \u00e9 uma cole\u00e7\u00e3o reutiliz\u00e1vel de etapas que s\u00e3o combinadas de uma forma ou de outra ao executar uma tarefa espec\u00edfica. A diferen\u00e7a \u00e9 que a tarefa do cluster est\u00e1 dispon\u00edvel em toda a extens\u00e3o do cluster. Para ver a lista de tarefas do cluster que s\u00e3o criadas automaticamente ao adicionar o Pipeline Operator, novamente usaremos o comando tkn CLI:<\/p>\n<pre><code class=\"plaintext\">$ tkn clustertask ls\n\nNOME                       IDADE\nbuildah                    1 dia atr\u00e1s\nbuildah-v0-10-0            1 dia atr\u00e1s\njib-maven                  1 dia atr\u00e1s\nkn                         1 dia atr\u00e1s\nmaven                      1 dia atr\u00e1s\nopenshift-client           1 dia atr\u00e1s\nopenshift-client-v0-10-0   1 dia atr\u00e1s\ns2i                        1 dia atr\u00e1s\ns2i-go                     1 dia atr\u00e1s\ns2i-go-v0-10-0             1 dia atr\u00e1s\ns2i-java-11                1 dia atr\u00e1s\ns2i-java-11-v0-10-0        1 dia atr\u00e1s\ns2i-java-8                 1 dia atr\u00e1s\ns2i-java-8-v0-10-0         1 dia atr\u00e1s\ns2i-nodejs                 1 dia atr\u00e1s\ns2i-nodejs-v0-10-0         1 dia atr\u00e1s\ns2i-perl                   1 dia atr\u00e1s\ns2i-perl-v0-10-0           1 dia atr\u00e1s\ns2i-php                    1 dia atr\u00e1s\ns2i-php-v0-10-0            1 dia atr\u00e1s\ns2i-python-3               1 dia atr\u00e1s\ns2i-python-3-v0-10-0       1 dia atr\u00e1s\ns2i-ruby                   1 dia atr\u00e1s\ns2i-ruby-v0-10-0           1 dia atr\u00e1s\ns2i-v0-10-0                1 dia atr\u00e1s\n<\/code><\/pre>\n<p>\nAgora vamos criar duas tarefas do cluster. A primeira ir\u00e1 gerar uma imagem S2I e envi\u00e1-la para o registro interno do OpenShift; a segunda ir\u00e1 realizar a compila\u00e7\u00e3o da nossa imagem baseada no NGINX, utilizando como conte\u00fado o aplicativo que j\u00e1 constru\u00edmos.<\/p>\n<h4>Criando e enviando a imagem<\/h4>\n<p>\nAo criar a primeira tarefa, iremos repetir o que j\u00e1 fizemos no artigo anterior sobre builds relacionados. Lembre-se de que utilizamos a imagem S2I (ubi8-s2i-web-app) para 'compilar' nosso aplicativo, e no final obtivemos uma imagem armazenada no registro interno do OpenShift. Agora, usaremos esta imagem S2I do aplicativo web para criar um DockerFile para nosso aplicativo e, em seguida, utilizaremos o Buildah para realizar a constru\u00e7\u00e3o real e enviar a imagem resultante ao registro interno do OpenShift, pois \u00e9 isso que o OpenShift faz ao implantar seus aplicativos com o NodeShift.<\/p>\n<p>Pergunta-se de onde sabemos tudo isso? De <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>, simplesmente copiamos e ajustamos para nossas necessidades.<\/p>\n<p>Ent\u00e3o, vamos criar a tarefa de cluster 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>\nN\u00e3o vamos analisar isso em detalhes, apenas nos deteremos no par\u00e2metro OUTPUT_DIR:<\/p>\n<pre><code class=\"plaintext\">params:\n      - name: OUTPUT_DIR\n        description: O local do diret\u00f3rio de sa\u00edda da constru\u00e7\u00e3o\n        default: build\n<\/code><\/pre>\n<p>\nPor padr\u00e3o, este par\u00e2metro \u00e9 definido como build; \u00e9 para l\u00e1 que o React armazena o conte\u00fado compilado. Outros frameworks usam caminhos diferentes, por exemplo, no Ember \u00e9 dist. A sa\u00edda da nossa primeira tarefa de cluster ser\u00e1 uma imagem contendo o HTML, JavaScript e CSS que compilamos.<\/p>\n<h4>Construindo uma imagem baseada no NGINX<\/h4>\n<p>\nQuanto \u00e0 nossa segunda tarefa de cluster, ela deve compilar uma imagem baseada no NGINX, usando o conte\u00fado do aplicativo que j\u00e1 compilamos. Na verdade, esta \u00e9 a parte da se\u00e7\u00e3o anterior onde discutimos builds encadeados.<\/p>\n<p>Para isso, assim como fizemos acima, criaremos a tarefa de cluster 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>\nAo olhar o c\u00f3digo dessas tarefas de cluster, \u00e9 vis\u00edvel que n\u00e3o h\u00e1 especifica\u00e7\u00e3o do reposit\u00f3rio Git com o qual estamos trabalhando ou dos nomes das imagens que estamos criando. Apenas definimos o que exatamente estamos passando para o Git ou alguma imagem para a qual o resultado final deve ser enviado. \u00c9 por isso que essas tarefas de cluster podem ser reutilizadas ao trabalhar com outros aplicativos.<\/p>\n<p>E aqui elegantemente passamos para o pr\u00f3ximo ponto...<\/p>\n<h4>Recursos<\/h4>\n<p>\nAssim, j\u00e1 que, como dissemos, as tarefas em cluster devem ser maximizadas em sua generalidade, precisamos criar recursos que ser\u00e3o utilizados na entrada (reposit\u00f3rio Git) e na sa\u00edda (imagens finais). O primeiro recurso que precisamos \u00e9 o Git, onde nosso aplicativo est\u00e1 localizado, algo como isto:<\/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>\nAqui o PipelineResource tem o tipo git. A chave url na se\u00e7\u00e3o params indica o reposit\u00f3rio espec\u00edfico e define o ramo master (opcional, mas inclu\u00edmos para completude).<\/p>\n<p>Agora precisamos criar um recurso para a imagem, onde os resultados da execu\u00e7\u00e3o da tarefa s2i-web-app ser\u00e3o salvos, isso \u00e9 feito assim:<\/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>\nAqui o PipelineResource tem o tipo image, e o valor do par\u00e2metro url aponta para o registro de imagens interno do OpenShift, especificamente para aquele que est\u00e1 no namespace webapp-pipeline. N\u00e3o se esque\u00e7a de alterar esse par\u00e2metro se voc\u00ea estiver usando outro namespace.<\/p>\n<p>E, finalmente, o \u00faltimo recurso que precisamos tamb\u00e9m ter\u00e1 o tipo image e ser\u00e1 a imagem final do NGINX, que ser\u00e1 utilizada durante a implanta\u00e7\u00e3o:<\/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>\nE novamente, observe que este recurso salva a imagem no registro interno do OpenShift no namespace webapp-pipeline.<\/p>\n<p>Para criar todos esses recursos de uma vez, usaremos o comando 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>\nVoc\u00ea pode verificar se os recursos foram criados assim:<\/p>\n<pre><code class=\"plaintext\">$ tkn resource ls\n<\/code><\/pre>\n<p><\/p>\n<h4>Pipeline<\/h4>\n<p>\nAgora que temos todos os componentes necess\u00e1rios, vamos mont\u00e1-los em um pipeline, criando-o com o seguinte comando:<\/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>\nMas, antes de executar esse comando, vamos analisar esses componentes. O primeiro \u00e9 o nome:<\/p>\n<pre><code class=\"plaintext\">apiVersion: tekton.dev\/v1alpha1\nkind: Pipeline\nmetadata:\n  name: build-and-deploy-react\n<\/code><\/pre>\n<p>\nEm seguida, na se\u00e7\u00e3o spec, vemos a especifica\u00e7\u00e3o dos recursos que criamos anteriormente:<\/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>\nDepois criamos as tarefas que nosso pipeline deve executar. Primeiro, ele deve executar a tarefa s2i-web-app que j\u00e1 criamos:<\/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>\nEssa tarefa pega os par\u00e2metros de entrada (recurso gir) e de sa\u00edda (recurso built-web-application-image). Tamb\u00e9m passamos um par\u00e2metro especial para que ela n\u00e3o verifique o TLS, uma vez que estamos usando certificados autoassinados:<\/p>\n<pre><code class=\"plaintext\">recursos:\n        entradas:\n          - nome: fonte\n            recurso: web-application-repo\n        sa\u00eddas:\n          - nome: imagem\n            recurso: built-web-application-image\n      par\u00e2metros:\n        - nome: TLSVERIFY\n          valor: \"false\"\n<\/code><\/pre>\n<p>\nA pr\u00f3xima tarefa \u00e9 quase a mesma, s\u00f3 que aqui chamamos a tarefa de cluster j\u00e1 criada, webapp-build-runtime:<\/p>\n<pre><code class=\"plaintext\">nome: construir-imagem-runtime\n    refer\u00eanciaTarefa:\n      nome: webapp-build-runtime\n      tipo: TarefaDeCluster\n<\/code><\/pre>\n<p>\nAssim como na tarefa anterior, passamos o recurso, mas agora \u00e9 a imagem-de-aplica\u00e7\u00e3o-web-constru\u00edda (sa\u00edda da nossa tarefa anterior). E como sa\u00edda, novamente especificamos a imagem. Como esta tarefa deve ser executada ap\u00f3s a anterior, adicionamos o campo runAfter:<\/p>\n<pre><code class=\"plaintext\">recursos:\n        entradas:\n          - nome: imagem\n            recurso: built-web-application-image\n        sa\u00eddas:\n          - nome: imagem\n            recurso: runtime-web-application-image\n        par\u00e2metros:\n        - nome: TLSVERIFY\n          valor: \"false\"\n      executarAp\u00f3s:\n        - build-web-application\n<\/code><\/pre>\n<p>\nAs duas pr\u00f3ximas tarefas s\u00e3o respons\u00e1veis pela aplica\u00e7\u00e3o dos arquivos YAML do servi\u00e7o, rota e implanta\u00e7\u00e3o, que est\u00e3o no diret\u00f3rio k8s da nossa aplica\u00e7\u00e3o web, bem como pela atualiza\u00e7\u00e3o dessa implanta\u00e7\u00e3o ao criar novas imagens. Essas duas tarefas de cluster foram definidas no in\u00edcio do artigo.<\/p>\n<h4>Execu\u00e7\u00e3o do pipeline<\/h4>\n<p>\nEnt\u00e3o, todas as partes do nosso pipeline foram criadas, e n\u00f3s o iniciaremos com o seguinte comando:<\/p>\n<pre><code class=\"plaintext\">$ tkn pipeline start build-and-deploy-react\n<\/code><\/pre>\n<p>\nNesta etapa, a linha de comando \u00e9 usada em modo interativo e \u00e9 necess\u00e1rio escolher os recursos correspondentes em resposta a cada solicita\u00e7\u00e3o: para o recurso git escolhemos reposit\u00f3rio-de-aplica\u00e7\u00f5es-web, em seguida, para o recurso da primeira imagem \u2013 imagem-de-aplica\u00e7\u00e3o-web-constru\u00edda, e, finalmente, para o recurso da segunda imagem \u2013 imagem-de-aplica\u00e7\u00e3o-web-runtime:<\/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>\nAgora vamos verificar o status do pipeline com o seguinte comando:<\/p>\n<pre><code class=\"plaintext\">$ tkn pipeline logs -f\n<\/code><\/pre>\n<p>\nAp\u00f3s o in\u00edcio do pipeline e a aplica\u00e7\u00e3o ser implantada, solicitamos a rota publicada com o seguinte comando:<\/p>\n<pre><code class=\"plaintext\">$ oc get route react-pipeline-example --template='http:\/\/{{.spec.host}}'\n<\/code><\/pre>\n<p>\nPara uma melhor visualiza\u00e7\u00e3o, podemos ver nosso pipeline no Modo Desenvolvedor do console web na se\u00e7\u00e3o <b>Pipelines<\/b>, como mostrado na Fig. 1.<\/p>\n<p><img decoding=\"async\" alt=\"Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift\" src=\"\/wp-content\/uploads\/2020\/08\/ede9b076414e389c2cd212adeda08956.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><i>Fig.1. Vis\u00e3o geral dos pipelines em execu\u00e7\u00e3o.<\/i><\/p>\n<p>Um clique no pipeline em execu\u00e7\u00e3o exibe informa\u00e7\u00f5es adicionais, como mostrado na Fig.2.<\/p>\n<p><img decoding=\"async\" alt=\"Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift\" src=\"\/wp-content\/uploads\/2020\/08\/64581b1f6d8ff91aedd963019ef29be5.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><i>Fig. 2. Informa\u00e7\u00f5es adicionais sobre o pipeline.<\/i><\/p>\n<p>Ap\u00f3s as informa\u00e7\u00f5es adicionais, \u00e9 poss\u00edvel ver as aplica\u00e7\u00f5es em execu\u00e7\u00e3o na vis\u00e3o <b>Topologia<\/b>, como mostrado na Fig.3.<\/p>\n<p><img decoding=\"async\" alt=\"Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift\" src=\"\/wp-content\/uploads\/2020\/08\/d23f723e14514ff60ecfddd8eb9bf752.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><i>Fig 3. Pod em execu\u00e7\u00e3o.<\/i><\/p>\n<p>Um clique no c\u00edrculo no canto superior direito do \u00edcone abre nossa aplica\u00e7\u00e3o, como mostrado na Fig.4.<\/p>\n<p><img decoding=\"async\" alt=\"Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift\" src=\"\/wp-content\/uploads\/2020\/08\/aa8e09d9fd9f33d5faffc7f661d84ca4.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><i>Fig. 4. Aplica\u00e7\u00e3o React em execu\u00e7\u00e3o.<\/i><\/p>\n<h3>Conclus\u00e3o<\/h3>\n<p>\nAssim, mostramos como iniciar um servidor de desenvolvimento para seu aplicativo no OpenShift e sincroniz\u00e1-lo com o sistema de arquivos local. Tamb\u00e9m abordamos como simular um template de constru\u00e7\u00e3o encadeada usando OpenShift Pipelines. Todo o c\u00f3digo de exemplos deste artigo pode ser encontrado <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/nodeshift\/webapp-pipeline-tutorial\">aqui<\/a><\/noindex>.<\/p>\n<h3>Recursos adicionais (EN)<\/h3>\n<p><\/p>\n<ul>\n<li>E-book gratuito <noindex><a rel=\"nofollow\" href=\"https:\/\/developers.redhat.com\/books\/deploying-openshift\/\">\u00abDesenvolvimento no OpenShift: um guia para os impacientes\u00bb<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/developers.redhat.com\/blog\/2018\/06\/11\/container-native-nodejs-istio-rhoar\/\">Constru\u00e7\u00e3o de aplicativos orientados a cont\u00eaineres Node.js usando Red Hat OpenShift Application Runtimes e 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\/\">Depura\u00e7\u00e3o de aplicativos Node.js no OpenShift com 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\/\">Tr\u00eas comandos para dominar o Express no OpenShift a partir do zero<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/developers.redhat.com\/blog\/2018\/03\/12\/rhoar-nodejs-annoucement\/\">An\u00fancio da vers\u00e3o p\u00fablica do Node.js como parte do 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\/\">Monitoramento de aplicativos Node.js no OpenShift com Prometheus<\/a><\/noindex><\/li>\n<li>Outros artigos sobre <noindex><a rel=\"nofollow\" href=\"https:\/\/developers.redhat.com\/topics\/kubernetes\/\">OpenShift e Kubernetes<\/a><\/noindex> no site da Red Hat<\/li>\n<\/ul>\n<h3>An\u00fancios de webinars futuros<\/h3>\n<p>\nIniciaremos uma s\u00e9rie de webinars \u00e0s sextas-feiras sobre a experi\u00eancia nativa de uso da Red Hat OpenShift Container Platform e 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 de agosto, webinar Imperador \u201cOperador\u201d: Operadores no OpenShift e 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 de setembro, DeploymentConfig vs Deployment \u2013 Coisas m\u00e1gicas espec\u00edficas do OpenShift para constru\u00e7\u00e3o e implementa\u00e7\u00e3o de aplicativos<\/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 de setembro, Red Hat OpenShift e 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 de outubro, Como lidar com um aumento repentino na carga<\/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 de outubro, Jenkins embutido, Pipeline-builds, Tekton na Red Hat OpenShift Container Platform<\/b><\/a><\/noindex><\/li>\n<\/ul>\n<p>Fonte: <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.3 - 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\/pt\/blog\/administrirovanie\/sovremennye-prilozheniya-na-openshift-chast-3-openshift-kak-sreda-razrabotki-i-konvejery-openshift-pipelines\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"pt_PT\" \/>\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\/pt\/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\udd47Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines OpenShift Pipelines | ProHoster","description":"Ol\u00e1 a todos neste blog!","canonical_url":"https:\/\/prohoster.info\/pt\/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":"pt_PT","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\/pt\/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\/pt\/wp-json\/wp\/v2\/posts\/92048","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=92048"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/92048\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media\/92049"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=92048"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=92048"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=92048"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}