ProHoster > Blog > administração > Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e OpenShift Pipelines
Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e OpenShift Pipelines
Olá a todos deste blog! Este é o terceiro post de uma série em que mostramos como implantar aplicações web modernas no Red Hat OpenShift.
Nas duas postagens anteriores, mostramos como implantar aplicações web modernas em apenas algumas etapas e como usar uma nova imagem S2I junto com uma imagem de servidor HTTP pronta para uso, como NGINX, usando construções encadeadas para orquestrar implantações de produção .
Hoje mostraremos como executar um servidor de desenvolvimento para sua aplicação na plataforma OpenShift e sincronizá-lo com o sistema de arquivos local, e também falar sobre o que são OpenShift Pipelines e como eles podem ser usados como alternativa aos assemblies vinculados.
OpenShift como ambiente de desenvolvimento
Fluxo de trabalho de desenvolvimento
Como mencionado em primeiro post, o processo típico de desenvolvimento de aplicativos da Web modernos é simplesmente algum tipo de “servidor de desenvolvimento” que rastreia alterações em arquivos locais. Quando eles ocorrem, a construção do aplicativo é acionada e, em seguida, atualizada no 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 ao executar aplicativos localmente. Vamos pegar o aplicativo como exemplo Reagir de artigos anteriores, embora quase os mesmos conceitos de fluxo de trabalho se apliquem a todas as outras estruturas modernas.
Portanto, para iniciar o “servidor dev” em nosso exemplo React, inseriremos o seguinte comando:
$ npm run start
Então, na janela do terminal, veremos algo assim:
E nosso aplicativo será aberto no navegador padrão:
Agora, se fizermos alterações no arquivo, o aplicativo deverá ser atualizado no navegador.
OK, tudo fica claro com o desenvolvimento em modo local, mas como conseguir o mesmo no OpenShift?
Servidor de desenvolvimento em OpenShift
Se você se lembra, em postagem anterior, analisamos a chamada fase de execução da imagem S2I e vimos que, por padrão, o módulo serve é responsável por atender nossa aplicação web.
No entanto, se você olhar mais de perto executar script desse exemplo, ele contém a variável de ambiente $NPM_RUN, que permite executar seu comando.
Por exemplo, podemos usar o módulo nodeshift para implantar nosso aplicativo:
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ê observar o log de um pod em execução, ele será parecido com isto:
Claro, tudo isso não será nada até que possamos sincronizar o código local com o código, que também é monitorado em busca de alterações, mas reside em um servidor remoto.
Sincronizando código remoto e local
Felizmente, o nodeshift pode ajudar facilmente na sincronização e você pode usar o comando watch para rastrear alterações.
Portanto, depois de executarmos o comando para implantar o servidor de desenvolvimento para nosso aplicativo, podemos usar com segurança o seguinte comando:
$ npx nodeshift watch
Como resultado, será feita uma conexão 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 começarão a ser monitorados quanto a alterações.
Portanto, se atualizarmos agora o arquivo src/App.js, o sistema reagirá a essas alterações, copiará-as para o cluster remoto e iniciará o servidor de desenvolvimento, que então atualizará nossa aplicação no navegador.
Para completar a imagem, vamos mostrar como são esses comandos inteiros:
O comando watch é uma abstração acima do comando oc rsync, você pode aprender mais sobre como ele funciona aqui.
Este foi um exemplo para React, mas exatamente o mesmo método pode ser usado com outros frameworks, basta definir a variável de ambiente NPM_RUN conforme necessário.
Pipelines Openshift
A seguir falaremos sobre uma ferramenta como o OpenShift Pipelines e como ela pode ser usada como alternativa às compilações encadeadas.
O que são pipelines OpenShift
OpenShift Pipelines é um sistema de integração e entrega contínua de CI/CD nativo da nuvem projetado para organizar pipelines usando Tekton. Tekton é uma estrutura de CI/CD flexível e de código aberto nativa do Kubernetes que permite automatizar a implantação em várias plataformas (Kubernetes, sem servidor, máquinas virtuais, etc.) abstraindo da camada subjacente.
A compreensão deste artigo requer algum conhecimento sobre Pipelines, por isso recomendamos fortemente que você leia primeiro livro oficial.
Configurando seu ambiente de trabalho
Para brincar com os exemplos deste artigo, primeiro você precisa preparar seu ambiente de trabalho:
Instale e configure um cluster OpenShift 4. Nossos exemplos usam CodeReady Containers (CRD) para isso, cujas instruções de instalação podem ser encontradas aqui.
Depois que o cluster estiver pronto, você precisará instalar o Pipeline Operator nele. Não tenha medo, é fácil, instruções de instalação aqui.
Execute a ferramenta de linha de comando create-react-app para criar um aplicativo que você irá implantar (este é um aplicativo simples Reagir).
(Opcional) Clone o repositório para executar o aplicativo de exemplo localmente com npm install e depois npm start.
O repositório do aplicativo também terá uma pasta k8s, que conterá os YAMLs do Kubernetes/OpenShift usados para implantar o aplicativo. Haverá tarefas, ClusterTasks, recursos e pipelines que criaremos neste repositórios.
Descer
A primeira etapa do nosso exemplo é criar um novo projeto no cluster OpenShift. Vamos chamar este projeto de webapp-pipeline e criá-lo com o seguinte comando:
$ oc new-project webapp-pipeline
Este nome de projeto aparecerá no código mais tarde, portanto, se você decidir dar outro nome a ele, não se esqueça de editar o código de exemplo de acordo. A partir deste ponto, não iremos de cima para baixo, mas de baixo para cima: ou seja, criaremos primeiro todos os componentes do transportador e só depois o próprio transportador.
Então, antes de tudo...
Tarefas
Vamos criar algumas tarefas que ajudarão a implantar o aplicativo em nosso pipeline. A primeira tarefa - apply_manifests_task - é responsável por aplicar o YAML dos recursos do Kubernetes (serviço, implantação e rota) que estão localizados na pasta k8s da nossa aplicação. A segunda tarefa – update_deployment_task – é responsável por atualizar uma imagem já implantada para aquela criada pelo nosso pipeline.
Não se preocupe se ainda não estiver muito claro. Na verdade, essas tarefas são algo como utilitários, e as veremos com mais detalhes um pouco mais tarde. Por enquanto, vamos apenas criá-los:
Então, usando o comando tkn CLI, verificaremos se as tarefas foram criadas:
$ tkn task ls
NAME AGE
apply-manifests 1 minute ago
update-deployment 1 minute ago
Nota: Estas são tarefas locais para o seu projeto atual.
Tarefas de cluster
As tarefas de cluster são basicamente iguais às tarefas simples. Ou seja, é um conjunto reutilizável de etapas que se combinam de uma forma ou de outra ao executar uma tarefa específica. A diferença é que uma tarefa de cluster está disponível em qualquer lugar do cluster. Para ver a lista de tarefas de cluster que são criadas automaticamente ao adicionar o Pipeline Operator, usaremos novamente o comando tkn 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 a imagem S2I e enviá-la para o registro interno do OpenShift; a segunda é construir nossa imagem baseada em NGINX, usando o aplicativo que já construímos 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” nossa aplicação e acabamos com uma imagem armazenada no registro interno do OpenShift. Agora usaremos esta imagem de aplicativo da web S2I para criar um DockerFile para nosso aplicativo e, em seguida, usaremos Buildah para fazer a construção real e enviar a imagem resultante para o registro interno do OpenShift, já que é exatamente isso que o OpenShift faz quando você implanta seus aplicativos usando NodeShift .
Como sabíamos de tudo isso, você pergunta? De versão oficial do Node.js oficial, nós apenas o copiamos e modificamos para nós mesmos.
Então, agora vamos criar a tarefa de cluster s2i-web-app:
Não analisaremos isso em detalhes, mas focaremos apenas no parâmetro OUTPUT_DIR:
params:
- name: OUTPUT_DIR
description: The location of the build output directory
default: build
Por padrão, esse parâmetro é igual a build, que é onde o React coloca o conteúdo montado. Outros frameworks usam caminhos diferentes, por exemplo, no Ember é dist. A saída da nossa primeira tarefa de cluster será uma imagem contendo o HTML, JavaScript e CSS que coletamos.
Construa uma imagem baseada em NGINX
Quanto à nossa segunda tarefa de cluster, ela deve construir uma imagem baseada em NGINX para nós, usando o conteúdo do aplicativo que já construímos. Essencialmente, esta é a parte da seção anterior onde examinamos as compilações encadeadas.
Para fazer isso, nós - exatamente como acima - criaremos uma tarefa de cluster webapp-build-runtime:
Se você observar o código dessas tarefas de cluster, verá que ele não especifica o repositório Git com o qual estamos trabalhando ou os nomes das imagens que estamos criando. Especificamos apenas o que exatamente estamos transferindo para o Git, ou uma determinada imagem onde a imagem final deve ser gerada. É 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
Então, como acabamos de dizer, as tarefas do cluster devem ser o mais gerais possíveis, precisamos criar recursos que serão usados como entrada (o repositório Git) e como saída (as imagens finais). O primeiro recurso que precisamos é o Git, onde reside nossa aplicação, mais ou menos 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 especifica o branch master (isso é opcional, mas nós o escrevemos para completar).
Agora precisamos criar um recurso para a imagem onde serão salvos os resultados da tarefa s2i-web-app, 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, PipelineResource é do tipo imagem e o valor do parâmetro url aponta para o registro de imagem interno do OpenShift, especificamente aquele localizado no namespace webapp-pipeline. Não se esqueça de alterar essa configuração se estiver usando um namespace diferente.
E por fim, o último recurso 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 interno do OpenShift no namespace webapp-pipeline.
Para criar todos esses recursos de uma vez, usamos o comando create:
Esta tarefa usa parâmetros de entrada (recurso gir) e saída (recurso de imagem de aplicativo da web integrado). Também lhe passamos um parâmetro especial para que não verifique o TLS, pois estamos usando certificados autoassinados:
Assim como na tarefa anterior, passamos um recurso, mas agora ele é uma imagem de aplicativo da web construída (a saída da nossa tarefa anterior). E como saída definimos novamente a imagem. Como esta tarefa deve ser executada após a anterior, adicionamos o campo runAfter:
As próximas duas tarefas são responsáveis por usar os arquivos YAML de serviço, rota e implantação que residem no diretório k8s de nossa aplicação web, e também por atualizar esta implantação ao criar novas imagens. Definimos essas duas tarefas de cluster no início do artigo.
Iniciando o transportador
Assim, todas as partes do nosso pipeline estão criadas e iremos executá-lo com o seguinte comando:
$ tkn pipeline start build-and-deploy-react
Neste estágio, a linha de comando é usada de forma interativa e você precisa selecionar os recursos apropriados em resposta a cada uma de suas solicitações: para o recurso git selecionamos web-application-repo, depois para o primeiro recurso de imagem - built-web-application -image 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 usando o seguinte comando:
$ tkn pipeline logs -f
Depois que o pipeline for iniciado e o aplicativo implantado, podemos solicitar a rota publicada com o seguinte comando:
$ oc get route react-pipeline-example --template='http://{{.spec.host}}'
Para maior visualização, você pode visualizar nosso pipeline no modo Desenvolvedor do console web na seção Dutos, como mostrado na Fig. 1.
Figura 1. Revisão de pipelines em execução.
Clicar em um pipeline em execução exibe detalhes adicionais, conforme mostrado na Figura 2.
Arroz. 2. Informações adicionais sobre o pipeline.
Após mais informações, você pode ver os aplicativos em execução na visualização topologia, conforme mostrado na Fig.3.
Fig 3. Pod lançado.
Clicar no círculo no canto superior direito do ícone abre nosso aplicativo, conforme mostrado na Fig.
Arroz. 4. Executando o aplicativo React.
Conclusão
Assim, mostramos como executar um servidor de desenvolvimento para sua aplicação no OpenShift e sincronizá-lo com o sistema de arquivos local. Também vimos como simular um modelo de construção encadeada usando OpenShift Pipelines. Todos os códigos de exemplo deste artigo podem ser encontrados aqui.