Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift

Olá a todos neste blog! Este é o terceiro post de uma série onde mostramos como implantar aplicações web modernas no Red Hat OpenShift.

Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift

Nos dois posts anteriores, falamos sobre como implantar aplicações 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ção em produção.

Hoje, mostraremos como iniciar na plataforma OpenShift um servidor de desenvolvimento para sua aplicação e sincronizá-lo com o sistema de arquivos local, além de discutir o que são os OpenShift Pipelines e como podem ser aplicados como uma alternativa aos builds encadeados.

OpenShift como ambiente de desenvolvimento

Fluxo de trabalho de desenvolvimento

Como mencionado no primeiro post, o processo típico de desenvolvimento para aplicações web modernas é simplesmente um "servidor de desenvolvimento" que monitora mudanças nos arquivos locais. Quando ocorrem, uma nova build da aplicação é iniciada e, em seguida, ela é atualizada no navegador.

Na maioria dos frameworks modernos, um "servidor de desenvolvimento" está embutido nas ferramentas de linha de comando apropriadas.

Exemplo local

Para começar, vamos ver como isso funciona no caso de uma execução local de aplicações. Como exemplo, usaremos a aplicação React dos artigos anteriores, embora praticamente os mesmos conceitos de fluxo de trabalho se apliquem a todos os outros frameworks modernos.
Então, para iniciar o "servidor de desenvolvimento" em nosso exemplo com React, digitamos o seguinte comando:

$ npm run start

Então, na janela do terminal, veremos algo como o seguinte:

Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift

E nossa aplicação será aberta no navegador padrão:

Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift

Agora, se fizermos alterações no arquivo, a aplicação deverá ser atualizada no navegador.

OK, o desenvolvimento em modo local está claro, mas como obter o mesmo no OpenShift?

Servidor de desenvolvimento no OpenShift

Se você se lembra, no post anterior, discutimos a fase de execução (run phase) da imagem S2I e vimos que, por padrão, o módulo serve é responsável por atender nossa aplicação web.

No entanto, se olharmos mais de perto script run No exemplo, há 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 é apresentado de forma resumida para ilustrar a ideia geral.

Aqui, adicionamos à nossa implantação a variável de ambiente NPM_RUN, que informa à etapa de execução que deve iniciar o comando yarn start, que inicia o servidor de desenvolvimento React dentro do nosso pod no OpenShift.

Se olharmos os logs do pod em execução, veremos algo como:

Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift

Claro, isso não terá valor até que possamos sincronizar o código local com o código que também está sob controle de alterações, mas reside em um servidor remoto.

Sincronização do código remoto e local

Felizmente, a sincronização é facilitada pelo nodeshift, e para rastrear alterações, podemos usar o comando watch.

Assim, após executarmos o comando para implantar o servidor de desenvolvimento do nosso aplicativo, podemos usar o seguinte comando:

$ npx nodeshift watch

Como resultado, será estabelecida uma conexão com o pod em execução que criamos anteriormente, 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 agora atualizarmos o arquivo src/App.js, o sistema reagirá a essas alterações, copiará para o cluster remoto e iniciará o servidor de desenvolvimento, que então atualizará nosso aplicativo no navegador.

Para completar o quadro, vamos mostrar como esses comandos se parecem na íntegra:

$ 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 sobre o comando oc rsync; mais detalhes sobre como isso funciona podem ser encontrados. aqui.

Este foi um exemplo para React, mas o mesmo método pode ser usado com outros frameworks, basta definir a variável de ambiente NPM_RUN corretamente.
 

Pipelines do OpenShift

Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift

A seguir, falaremos sobre uma ferramenta chamada OpenShift Pipelines e como ela pode ser usada como uma alternativa às compilações encadeadas.

O que são OpenShift Pipelines

OpenShift Pipelines é um sistema de CI/CD baseado na nuvem, projetado para organizar pipelines utilizando Tekton. Tekton é um framework CI/CD flexível, nativo do Kubernetes e de código aberto, que permite automatizar a implementação em várias plataformas (Kubernetes, serverless, máquinas virtuais etc.) ao abstrair o nível subjacente.

Para entender este artigo, são necessários alguns conhecimentos sobre Pipelines, portanto, recomendamos fortemente que você comece consultando o manual oficial.

Configurando o ambiente de trabalho

Para experimentar os exemplos deste artigo, primeiro você precisa preparar o ambiente de trabalho:

  1. Instalar e configurar um cluster OpenShift 4. Em nossos exemplos, utilizamos o CodeReady Containers (CRD), cujas instruções de instalação podem ser encontradas aqui.
  2. Depois que o cluster estiver pronto, você deve instalar o Pipeline Operator. Não se preocupe, é fácil, as instruções para instalação estão aqui.
  3. Baixar Tekton CLI (tkn) aqui.
  4. Executar a ferramenta de linha de comando create-react-app para criar um aplicativo que será implantado depois (este é um aplicativo simples React).
  5. (Opcional) Clonar o repositório para executar localmente o exemplo do aplicativo com o comando npm install e, em seguida, npm start.

No repositório do aplicativo também haverá uma pasta k8s, onde estarão os YAMLs do Kubernetes/OpenShift usados para a implantação do aplicativo. Haverá Tasks, ClusterTasks, Resources e Pipelines que criaremos neste repositório.

Vamos começar

Primeiramente, para nosso exemplo, precisamos criar um novo projeto no cluster OpenShift. Vamos chamar este projeto de webapp-pipeline e criar com o seguinte comando:

$ oc new-project webapp-pipeline

A partir de agora, esse nome de projeto aparecerá no código, então, se você decidir nomeá-lo de forma diferente, não se esqueça de ajustar o código 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óprio.

Então, primeiro...

Tarefas Tasks

Vamos criar duas tarefas (tasks), que depois ajudarão a implantar o aplicativo dentro do nosso pipeline. A primeira tarefa – apply_manifests_task – é responsável por aplicar os recursos YAML do Kubernetes (service, deployment e route) que estão na pasta k8s do nosso aplicativo. A segunda tarefa – update_deployment_task – é responsável por atualizar a imagem já implantada para a que está sendo criada pelo nosso pipeline.

Não se preocupe se ainda não estiver muito claro. Na verdade, essas tarefas são como utilitários, e nós as exploraremos com mais detalhes mais tarde. Por enquanto, apenas vamos criá-las:

$ 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, usaremos o comando tkn CLI para verificar se as tarefas foram criadas:

$ tkn task ls

NOME                IDADE
apply-manifests     1 minuto atrás
update-deployment   1 minuto atrás

Nota: estas são tarefas locais do seu projeto atual.

Tarefas do Cluster

Tarefas do Cluster são basicamente a mesma coisa que apenas tarefas. Ou seja, é uma coleção reutilizável de etapas que são combinadas de uma forma ou de outra ao executar uma tarefa específica. A diferença é que a tarefa do cluster está disponível em toda a extensão do cluster. Para ver a lista de tarefas do cluster que são criadas automaticamente ao adicionar o Pipeline Operator, novamente usaremos o comando tkn CLI:

$ tkn clustertask ls

NOME                       IDADE
buildah                    1 dia atrás
buildah-v0-10-0            1 dia atrás
jib-maven                  1 dia atrás
kn                         1 dia atrás
maven                      1 dia atrás
openshift-client           1 dia atrás
openshift-client-v0-10-0   1 dia atrás
s2i                        1 dia atrás
s2i-go                     1 dia atrás
s2i-go-v0-10-0             1 dia atrás
s2i-java-11                1 dia atrás
s2i-java-11-v0-10-0        1 dia atrás
s2i-java-8                 1 dia atrás
s2i-java-8-v0-10-0         1 dia atrás
s2i-nodejs                 1 dia atrás
s2i-nodejs-v0-10-0         1 dia atrás
s2i-perl                   1 dia atrás
s2i-perl-v0-10-0           1 dia atrás
s2i-php                    1 dia atrás
s2i-php-v0-10-0            1 dia atrás
s2i-python-3               1 dia atrás
s2i-python-3-v0-10-0       1 dia atrás
s2i-ruby                   1 dia atrás
s2i-ruby-v0-10-0           1 dia atrás
s2i-v0-10-0                1 dia atrás

Agora vamos criar duas tarefas do cluster. A primeira irá gerar uma imagem S2I e enviá-la para o registro interno do OpenShift; a segunda irá realizar a compilação da nossa imagem baseada no NGINX, utilizando como conteúdo o aplicativo que já construímos.

Criando e enviando a imagem

Ao criar a primeira tarefa, iremos repetir o que já 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ção real e enviar a imagem resultante ao registro interno do OpenShift, pois é isso que o OpenShift faz ao implantar seus aplicativos com o NodeShift.

Pergunta-se de onde sabemos tudo isso? De официальной версии official Node.js, simplesmente copiamos e ajustamos para nossas necessidades.

Então, vamos criar 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 vamos analisar isso em detalhes, apenas nos deteremos no parâmetro OUTPUT_DIR:

params:
      - name: OUTPUT_DIR
        description: O local do diretório de saída da construção
        default: build

Por padrão, este parâmetro é definido como build; é para lá que o React armazena o conteúdo compilado. 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 compilamos.

Construindo uma imagem baseada no NGINX

Quanto à nossa segunda tarefa de cluster, ela deve compilar uma imagem baseada no NGINX, usando o conteúdo do aplicativo que já compilamos. Na verdade, esta é a parte da seção anterior onde discutimos builds encadeados.

Para isso, assim como fizemos acima, criaremos a tarefa de cluster webapp-build-runtime:

$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/clustertasks/webapp-build-runtime-task.yaml

Ao olhar o código dessas tarefas de cluster, é visível que não há especificação do repositório 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. É por isso que essas tarefas de cluster podem ser reutilizadas ao trabalhar com outros aplicativos.

E aqui elegantemente passamos para o próximo ponto...

Recursos

Assim, já que, como dissemos, as tarefas em cluster devem ser maximizadas em sua generalidade, precisamos criar recursos que serão utilizados na entrada (repositório Git) e na saída (imagens finais). O primeiro recurso que precisamos é o Git, onde nosso aplicativo está localizado, algo como isto:

# 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 o PipelineResource tem o tipo git. A chave url na seção params indica o repositório específico e define o ramo master (opcional, mas incluímos para completude).

Agora precisamos criar um recurso para a imagem, onde os resultados da execução 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 tem o tipo image, e o valor do parâmetro url aponta para o registro de imagens interno do OpenShift, especificamente para aquele que está no namespace webapp-pipeline. Não se esqueça de alterar esse parâmetro se você estiver usando outro namespace.

E, finalmente, o último recurso que precisamos também terá o tipo image e será a imagem final do NGINX, que será utilizada 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

E novamente, observe que este recurso salva a imagem no registro interno do OpenShift no namespace webapp-pipeline.

Para criar todos esses recursos de uma vez, usaremos o comando create:

$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/resources/resource.yaml

Você pode verificar se os recursos foram criados assim:

$ tkn resource ls

Pipeline

Agora que temos todos os componentes necessários, vamos montá-los em um pipeline, 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 esse comando, vamos analisar esses componentes. O primeiro é o nome:

apiVersion: tekton.dev/v1alpha1
kind: Pipeline
metadata:
  name: build-and-deploy-react

Em seguida, na seção spec, vemos a especificaçã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

Depois criamos as tarefas que nosso pipeline deve executar. Primeiro, ele deve executar a tarefa s2i-web-app que já criamos:

tasks:
    - name: build-web-application
      taskRef:
        name: s2i-web-app
        kind: ClusterTask

Essa tarefa pega os parâmetros de entrada (recurso gir) e de saída (recurso built-web-application-image). Também passamos um parâmetro especial para que ela não verifique o TLS, uma vez que estamos usando certificados autoassinados:

recursos:
        entradas:
          - nome: fonte
            recurso: repositório-de-aplicações-web
        saídas:
          - nome: imagem
            recurso: imagem-de-aplicação-web-construída
      parâmetros:
        - nome: TLSVERIFY
          valor: "false"

A próxima tarefa é quase a mesma, só que aqui chamamos a tarefa de cluster já criada, webapp-build-runtime:

nome: construir-imagem-runtime
    referênciaTarefa:
      nome: webapp-build-runtime
      tipo: TarefaDeCluster

Assim como na tarefa anterior, passamos o recurso, mas agora é a imagem-de-aplicação-web-construída (saída da nossa tarefa anterior). E como saída, novamente especificamos a imagem. Como esta tarefa deve ser executada após a anterior, adicionamos o campo runAfter:

recursos:
        entradas:
          - nome: imagem
            recurso: imagem-de-aplicação-web-construída
        saídas:
          - nome: imagem
            recurso: imagem-de-aplicação-web-runtime
        parâmetros:
        - nome: TLSVERIFY
          valor: "false"
      runAfter:
        - construir-aplicação-web

As duas próximas tarefas são responsáveis pela aplicação dos arquivos YAML do serviço, rota e implantação, que estão no diretório k8s da nossa aplicação web, bem como pela atualização dessa implantação ao criar novas imagens. Essas duas tarefas de cluster foram definidas no início do artigo.

Execução do pipeline

Então, todas as partes do nosso pipeline foram criadas, e nós o iniciaremos com o seguinte comando:

$ tkn pipeline start build-and-deploy-react

Nesta etapa, a linha de comando é usada em modo interativo e é necessário escolher os recursos correspondentes em resposta a cada solicitação: para o recurso git escolhemos repositório-de-aplicações-web, em seguida, para o recurso da primeira imagem – imagem-de-aplicação-web-construída, e, finalmente, para o recurso da segunda imagem – imagem-de-aplicação-web-runtime:

? 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

Após o início do pipeline e a aplicação ser implantada, solicitamos a rota publicada com o seguinte comando:

$ oc get route react-pipeline-example --template='http://{{.spec.host}}'

Para uma melhor visualização, podemos ver nosso pipeline no Modo Desenvolvedor do console web na seção Pipelines, como mostrado na Fig. 1.

Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift

Fig.1. Visão geral dos pipelines em execução.

Um clique no pipeline em execução exibe informações adicionais, como mostrado na Fig.2.

Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift

Fig. 2. Informações adicionais sobre o pipeline.

Após as informações adicionais, é possível ver as aplicações em execução na visão Topologia, como mostrado na Fig.3.

Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift

Fig 3. Pod em execução.

Um clique no círculo no canto superior direito do ícone abre nossa aplicação, como mostrado na Fig.4.

Aplicativos modernos no OpenShift, parte 3: OpenShift como ambiente de desenvolvimento e pipelines do OpenShift

Fig. 4. Aplicação React em execução.

Conclusão

Assim, mostramos como iniciar um servidor de desenvolvimento para seu aplicativo no OpenShift e sincronizá-lo com o sistema de arquivos local. Também abordamos como simular um template de construção encadeada usando OpenShift Pipelines. Todo o código de exemplos deste artigo pode ser encontrado aqui.

Recursos adicionais (EN)

Anúncios de webinars futuros

Iniciaremos uma série de webinars às sextas-feiras sobre a experiência nativa de uso da Red Hat OpenShift Container Platform e Kubernetes:

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster