
Nos dois posts anteriores, cobrimos como implantar aplicativos da web modernos em apenas algumas etapas e como usar uma nova imagem S2I junto com uma imagem de servidor HTTP pronta, como NGINX, usando compilações encadeadas para implantação de produção.
Hoje vamos mostrar como executar um servidor de desenvolvimento para seu aplicativo na plataforma OpenShift e sincronizá-lo com o sistema de arquivos local, além de falar sobre o que é o OpenShift Pipelines e como você pode usá-lo como alternativa aos assemblies vinculados.
OpenShift como um ambiente de desenvolvimento
Fluxo de trabalho de desenvolvimento
Conforme discutido no primeiro post , um fluxo de trabalho de desenvolvimento típico para aplicativos da web modernos é simplesmente um "servidor de desenvolvimento" que monitora as alterações em arquivos locais. Quando eles acontecem, o build do aplicativo é iniciado e então atualizado para o navegador.
Na maioria das estruturas modernas, esse "servidor de desenvolvimento" é integrado às ferramentas de linha de comando correspondentes.
Exemplo local
Primeiro, vamos ver como isso funciona no caso de execução de aplicativos localmente. Vamos pegar o aplicativo React dos artigos anteriores como exemplo , embora muitos dos mesmos conceitos de fluxo de trabalho se apliquem a todas as outras estruturas modernas.
Portanto, para iniciar o "servidor de desenvolvimento" em nosso exemplo React, emitimos o seguinte comando:
$ npm run start
Então, na janela do terminal, veremos algo como o seguinte:

E nosso aplicativo será aberto no navegador padrão:

Agora, se fizermos alterações no arquivo, o aplicativo deve ser atualizado no navegador.
Ok, com desenvolvimento local tudo fica claro, mas como conseguir o mesmo no OpenShift?
Servidor de desenvolvimento em OpenShift
Se você se lembra, no post anterior , analisamos a chamada fase de execução da imagem S2I e vimos que por padrão o módulo de serviço é responsável por servir nossa aplicação web.
No entanto, se você der uma olhada mais de perto no script de execução desse exemplo, verá que ele contém a variável de ambiente $ NPM_RUN, que permite executar seu próprio comando.
Por exemplo, podemos usar o módulo nodeshift para implantar nosso aplicativo:
$ npx nodeshift --deploy.env NPM_RUN="yarn start" --dockerImage=nodeshift/ubi8-s2i-web-app
Nota: O exemplo acima é abreviado para ilustrar a ideia geral.
Aqui, adicionamos a variável de ambiente NPM_RUN à nossa implantação, que informa ao tempo de execução para executar o comando yarn start, que inicia o servidor de desenvolvimento React dentro de nosso pod OpenShift.
Se você olhar o log de um pod em execução, verá algo como o seguinte:

Claro, tudo isso não terá nada a ver até que possamos sincronizar o código local com o código que também é monitorado para alterações, mas reside em um servidor remoto.
Sincronizando código remoto e local
Felizmente, nodeshift pode facilmente ajudar na sincronização e você pode usar o comando watch para rastrear as alterações.
Então, depois de executar o comando para implantar o servidor de desenvolvimento para nosso aplicativo, podemos usar com segurança o seguinte comando:
$ npx nodeshift watch
Como resultado, uma conexão será feita com o pod em execução, que criamos um pouco antes, a sincronização de nossos arquivos locais com o cluster remoto será ativada e os arquivos em nosso sistema local serão monitorados para alterações.
Portanto, se agora atualizarmos o arquivo src / App.js, o sistema irá reagir a essas mudanças, copiá-las para o cluster remoto e iniciar o servidor de desenvolvimento, que irá atualizar nosso aplicativo no navegador.
Para completar, vamos mostrar a aparência desses comandos em sua totalidade:
$ 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
$ npx nodeshift watch --strictSSL=false
O comando watch é uma abstração do comando oc rsync, você pode aprender mais sobre como ele funciona aqui .
Este foi um exemplo para React, mas o mesmo método exato pode ser usado com outras estruturas, basta definir a variável de ambiente NPM_RUN conforme necessário.
Pipelines Openshift

A seguir, falaremos sobre uma ferramenta como OpenShift Pipelines e como ela pode ser usada como uma alternativa para compilações encadeadas.
O que é OpenShift Pipelines
OpenShift Pipelines é um sistema de integração e entrega contínua de CI / CD baseado em nuvem para organizar pipelines usando Tekton. Tekton é uma estrutura CI / CD flexível e de código aberto nativo do Kubernetes que automatiza implantações em plataformas (Kubernetes, sem servidor, máquinas virtuais etc.) abstraindo da camada subjacente.
É necessário algum conhecimento de Pipelines para entender este artigo, portanto, recomendamos que você leia o tutorial oficial primeiro .
Configurando o ambiente de trabalho
Para brincar com os exemplos neste artigo, primeiro você precisa preparar seu ambiente de produção:
- OpenShift 4. CodeReady Containers (CRD), .
- , , Pipeline Operator. , , .
- Tekton CLI (tkn) .
- create-react-app, , ( React).
- () , npm install npm start.
O repositório do aplicativo também terá uma pasta k8s, onde os YAMLs Kubernetes / OpenShift usados para implantar o aplicativo estarão localizados. Haverá Tasks, ClusterTasks, Resources e Pipelines que criaremos neste repositório .
Vamos começar
A primeira etapa do nosso exemplo é criar um novo projeto no cluster OpenShift. Vamos chamar esse projeto webapp-pipeline e criá-lo com o seguinte comando:
$ oc new-project webapp-pipeline
Além disso, este nome do projeto aparecerá no código, portanto, se você decidir nomeá-lo de outra forma, não se esqueça de editar o código dos exemplos de acordo. Partindo deste ponto, iremos não de cima para baixo, mas de baixo para cima: ou seja, primeiro iremos criar todos os componentes do transportador e só depois ele mesmo.
Então, antes de tudo ...
Tarefas
Vamos criar algumas tarefas que nos ajudarão a implantar o aplicativo por meio de nosso pipeline. A primeira tarefa - apply_manifests_task - é responsável por aplicar YAML aos recursos do Kubernetes (serviço, implantação e rota) que estão localizados na pasta k8s de nosso aplicativo. A segunda tarefa - update_deployment_task - é responsável por atualizar uma imagem já implantada para aquela criada por nosso pipeline.
Não se preocupe se ainda não estiver claro. Na verdade, essas tarefas são como utilitários, e as discutiremos com mais detalhes um pouco mais tarde. Por enquanto, vamos apenas criá-los:
$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/tasks/update_deployment_task.yaml
$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/tasks/apply_manifests_task.yaml
Em seguida, usando o comando tkn da CLI, verifique se as tarefas foram criadas:
$ tkn task ls
NAME AGE
apply-manifests 1 minute ago
update-deployment 1 minute ago
Nota: essas são tarefas locais do seu projeto atual.
Tarefas de cluster
Tarefas agrupadas são basicamente iguais às tarefas simples. Ou seja, é uma coleção reutilizável de etapas que são combinadas de uma forma ou de outra ao iniciar uma tarefa específica. A diferença é que a tarefa de cluster está disponível em todos os lugares do cluster. Para ver uma lista de tarefas de cluster que são criadas automaticamente quando o Pipeline Operator é adicionado, use novamente o comando tkn da CLI:
$ tkn clustertask ls
NAME AGE
buildah 1 day ago
buildah-v0-10-0 1 day ago
jib-maven 1 day ago
kn 1 day ago
maven 1 day ago
openshift-client 1 day ago
openshift-client-v0-10-0 1 day ago
s2i 1 day ago
s2i-go 1 day ago
s2i-go-v0-10-0 1 day ago
s2i-java-11 1 day ago
s2i-java-11-v0-10-0 1 day ago
s2i-java-8 1 day ago
s2i-java-8-v0-10-0 1 day ago
s2i-nodejs 1 day ago
s2i-nodejs-v0-10-0 1 day ago
s2i-perl 1 day ago
s2i-perl-v0-10-0 1 day ago
s2i-php 1 day ago
s2i-php-v0-10-0 1 day ago
s2i-python-3 1 day ago
s2i-python-3-v0-10-0 1 day ago
s2i-ruby 1 day ago
s2i-ruby-v0-10-0 1 day ago
s2i-v0-10-0 1 day ago
Agora vamos criar duas tarefas de cluster. O primeiro irá gerar uma imagem S2I e enviá-la para o registro interno do OpenShift; a segunda é construir nossa imagem baseada em NGINX usando o aplicativo que já montamos como conteúdo.
Crie e envie a imagem
Ao criar a primeira tarefa, repetiremos o que já fizemos no artigo anterior sobre montagens vinculadas. Lembre-se de que usamos a imagem S2I (ubi8-s2i-web-app) para "construir" nosso aplicativo e acabamos com a imagem armazenada no registro interno do OpenShift. Agora usaremos esta imagem S2I do aplicativo da web para criar um DockerFile para nosso aplicativo e, em seguida, usaremos Buildah para fazer a compilação real e enviar a imagem resultante para o registro OpenShift interno, pois isso é exatamente o que o OpenShift faz quando você implanta o seu. aplicativos usando NodeShift.
Como é que sabemos de tudo isso, você pergunta? Da versão oficial do Node.js oficial , nós apenas copiamos e terminamos por nós mesmos.
Então, agora criamos a tarefa de cluster s2i-web-app:
$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/clustertasks/s2i-web-app-task.yaml
Não entraremos em detalhes sobre isso, mas apenas nos deteremos no parâmetro OUTPUT_DIR:
params:
- name: OUTPUT_DIR
description: The location of the build output directory
default: build
Por padrão, este parâmetro é definido como build, que é onde o React coloca o conteúdo coletado. Outros frameworks usam caminhos diferentes, por exemplo, em Ember it is dist. A saída de nossa primeira tarefa de cluster será uma imagem contendo o HTML, JavaScript e CSS que coletamos.
Construindo uma imagem baseada em NGINX
Quanto à nossa segunda tarefa de cluster, ela deve coletar uma imagem baseada em NGINX para nós usando o conteúdo do aplicativo que já coletamos. Basicamente, esta é a parte da seção anterior onde vimos as compilações encadeadas.
Para fazer isso, nós - da mesma forma que um pouco acima - criamos uma tarefa de cluster webapp-build-runtime:
$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/clustertasks/webapp-build-runtime-task.yaml
Se você olhar o código dessas tarefas de cluster, verá que o repositório Git com o qual estamos trabalhando ou os nomes das imagens que criamos não estão especificados lá. Nós apenas especificamos o que exatamente transferimos para o Git, ou uma determinada imagem, onde a imagem final deve ser exibida. É por isso que essas tarefas de cluster podem ser reutilizadas ao trabalhar com outros aplicativos.
E aqui passamos graciosamente para o próximo ponto ...
Recursos
Portanto, como, como acabamos de dizer, as tarefas de cluster devem ser o mais generalizadas possível, precisamos criar recursos que serão usados na entrada (repositório Git) e na saída (imagens finais). O primeiro recurso de que precisamos é o Git, onde nosso aplicativo reside, algo assim:
# This resource is the location of the git repo with the web application source
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
name: web-application-repo
spec:
type: git
params:
- name: url
value: https://github.com/nodeshift-starters/react-pipeline-example
- name: revision
value: master
Aqui, PipelineResource é do tipo git. A chave url na seção params aponta para um repositório específico e define o branch master (isso é opcional, mas nós o escrevemos para ser completo).
Agora precisamos criar um recurso para a imagem, onde os resultados da tarefa s2i-web-app serão salvos, isso é feito assim:
# This resource is the result of running "npm run build", the resulting built files will be located in /opt/app-root/output
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
name: built-web-application-image
spec:
type: image
params:
- name: url
value: image-registry.openshift-image-registry.svc:5000/webapp-pipeline/built-web-application:latest
Aqui, o PipelineResource é do tipo imagem e o valor do parâmetro url aponta para o OpenShift Image Registry interno, especificamente para aquele no namespace webapp-pipeline. Lembre-se de alterar este parâmetro se estiver usando um namespace diferente.
E, finalmente, o último recurso de que precisamos também será do tipo imagem e esta será a imagem NGINX final, que será usada durante a implantação:
# This resource is the image that will be just the static html, css, js files being run with nginx
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
name: runtime-web-application-image
spec:
type: image
params:
- name: url
value: image-registry.openshift-image-registry.svc:5000/webapp-pipeline/runtime-web-application:latest
Novamente, observe que este recurso armazena a imagem no registro OpenShift interno no namespace webapp-pipeline.
Para criar todos esses recursos de uma vez, use o comando create:
$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/resources/resource.yaml
Você pode ter certeza de que os recursos foram criados assim:
$ tkn resource ls
Pipeline pipeline
Agora que temos todos os componentes necessários, montaremos um pipeline a partir deles, criando-o com o seguinte comando:
$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/pipelines/build-and-deploy-react.yaml
Mas, antes de executar este comando, vamos dar uma olhada nesses componentes. O primeiro é o nome:
apiVersion: tekton.dev/v1alpha1
kind: Pipeline
metadata:
name: build-and-deploy-react
Em seguida, na seção de especificações, vemos uma indicação dos recursos que criamos anteriormente:
spec:
resources:
- name: web-application-repo
type: git
- name: built-web-application-image
type: image
- name: runtime-web-application-image
type: image
Em seguida, criamos tarefas para o nosso pipeline concluir. Em primeiro lugar, ele deve executar a tarefa s2i-web-app que já criamos:
tasks:
- name: build-web-application
taskRef:
name: s2i-web-app
kind: ClusterTask
Esta tarefa leva os parâmetros de entrada (recurso gir) e saída (recurso de imagem do aplicativo da web integrado). Também passamos a ele um parâmetro especial para que não verifique o TLS, pois estamos usando certificados autoassinados:
resources:
inputs:
- name: source
resource: web-application-repo
outputs:
- name: image
resource: built-web-application-image
params:
- name: TLSVERIFY
value: "false"
A próxima tarefa é quase a mesma, só que aqui a tarefa de cluster webapp-build-runtime já criada é chamada:
name: build-runtime-image
taskRef:
name: webapp-build-runtime
kind: ClusterTask
Como na tarefa anterior, estamos transmitindo o recurso, mas agora é uma imagem de aplicativo da web integrada (a saída de nossa tarefa anterior). E como saída, definimos novamente a imagem. Como esta tarefa deve ser realizada após a anterior, adicionamos o campo runAfter:
resources:
inputs:
- name: image
resource: built-web-application-image
outputs:
- name: image
resource: runtime-web-application-image
params:
- name: TLSVERIFY
value: "false"
runAfter:
- build-web-application
As próximas duas tarefas são responsáveis por aplicar os arquivos YAML de serviço, rota e implantação que residem no diretório k8s de nosso aplicativo da web, e também por atualizar essa implantação ao criar novas imagens. Definimos essas duas tarefas de cluster no início do artigo.
Executando o transportador
Assim, todas as partes do nosso pipeline são criadas e vamos iniciá-lo com o seguinte comando:
$ tkn pipeline start build-and-deploy-react
Neste estágio, a linha de comando é usada interativamente e você precisa selecionar os recursos apropriados em resposta a cada uma de suas solicitações: para o recurso git, selecione o repo do aplicativo da web, em seguida, para o recurso da primeira imagem, selecione a imagem do aplicativo da web integrada e, finalmente, para o segundo recurso de imagem –runtime-web-application-image:
? Choose the git resource to use for web-application-repo: web-application-repo (https://github.com/nodeshift-starters/react-pipeline-example)
? 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-
application:latest)
? 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
e-web-application:latest)
Pipelinerun started: build-and-deploy-react-run-4xwsr
Agora vamos verificar o status do pipeline com o seguinte comando:
$ tkn pipeline logs -f
Depois que o pipeline é iniciado e o aplicativo implantado, solicitamos a rota publicada com o seguinte comando:
$ oc get route react-pipeline-example --template='http://{{.spec.host}}'
Para obter mais visibilidade, você pode visualizar nosso pipeline no modo Desenvolvedor do console da web na seção Pipelines , conforme mostrado na Fig. 1

Figura 1. Visão geral dos pipelines em execução.
Clicar em um pipeline em execução exibe informações adicionais, conforme mostrado na Figura 2.

Figura: 2. Mais informações sobre o pipeline.
Após mais detalhes, você pode ver os aplicativos em execução na visualização Topology , conforme mostrado na Figura 3.

Fig 3. Pod em execução.
Clicar no círculo no canto superior direito do ícone abre nosso aplicativo, conforme mostrado na Figura 4.

Figura: 4. Executando o aplicativo React.
Conclusão
Portanto, mostramos como executar um servidor de desenvolvimento para seu aplicativo no OpenShift e sincronizá-lo com o sistema de arquivos local. Também vimos como imitar o modelo de construção encadeada usando OpenShift Pipelines. Todos os códigos de amostra deste artigo podem ser encontrados aqui .
Recursos adicionais (EN)
- E-book grátis "Developing with OpenShift: A Guide for the Impacient"
- Crie aplicativos Node.js orientados a contêiner usando Red Hat OpenShift Application Runtimes e Istio
- Depuração de aplicativos Node.js no OpenShift com Chrome DevTools
- Três comandos para dominar o Express no OpenShift do zero
- Anúncio de uma versão pública do Node.js como parte do Red Hat OpenShift Application Runtimes
- Monitorando aplicativos Node.js em OpenShift com Prometheus
- Mais artigos sobre OpenShift e Kubernetes no Red Hat
Anúncios dos próximos webinars
Estamos dando início a uma série de webinars nas sextas-feiras sobre a experiência nativa de usar a plataforma Red Hat OpenShift Container e o Kubernetes:
- 28 de agosto, webinar Emperor "Operator": Operadores em OpenShift e Kubernetes
- 11 de setembro, DeploymentConfig vs Deployment - mágica específica do OpenShift para construir e implantar aplicativos
- 25 de setembro, Red Hat OpenShift e API de máquina
- 9 de outubro, Como lidar com um crescimento repentino de carga
- 23 de outubro, Embedded Jenkins, Pipeline-builds, Tekton na Red Hat OpenShift Container Platform