Aplicaciones modernas en OpenShift, parte 3: OpenShift como entorno de desarrollo y OpenShift Pipelines

¡Hola a todos en este blog! Esta es la tercera publicación de una serie en la que mostramos cómo implementar aplicaciones web modernas en Red Hat OpenShift.

Aplicaciones modernas en OpenShift, parte 3: OpenShift como entorno de desarrollo y OpenShift Pipelines

En las dos publicaciones anteriores, mostramos cómo implementar aplicaciones web modernas en solo unos pocos pasos y cómo usar una nueva imagen S2I junto con una imagen de servidor HTTP disponible en el mercado, como NGINX, usando compilaciones encadenadas para orquestar implementaciones de producción. .

Hoy mostraremos cómo ejecutar un servidor de desarrollo para su aplicación en la plataforma OpenShift y sincronizarlo con el sistema de archivos local, y también hablaremos sobre qué son OpenShift Pipelines y cómo se pueden usar como una alternativa a los ensamblajes vinculados.

OpenShift como entorno de desarrollo

Flujo de trabajo de desarrollo

Como se menciona en Primer comentario, el proceso de desarrollo típico de las aplicaciones web modernas es simplemente una especie de "servidor de desarrollo" que rastrea los cambios en los archivos locales. Cuando ocurren, se activa la compilación de la aplicación y luego se actualiza en el navegador.

En la mayoría de los marcos modernos, dicho "servidor de desarrollo" está integrado en las herramientas de línea de comandos correspondientes.

Ejemplo local

Primero, veamos cómo funciona esto cuando se ejecutan aplicaciones localmente. Tomemos la aplicación como ejemplo. Reaccionar de artículos anteriores, aunque casi los mismos conceptos de flujo de trabajo se aplican en todos los demás marcos modernos.
Entonces, para iniciar el "servidor de desarrollo" en nuestro ejemplo de React, ingresaremos el siguiente comando:

$ npm run start

Luego en la ventana de la terminal veremos algo como esto:

Aplicaciones modernas en OpenShift, parte 3: OpenShift como entorno de desarrollo y OpenShift Pipelines

Y nuestra aplicación se abrirá en el navegador predeterminado:

Aplicaciones modernas en OpenShift, parte 3: OpenShift como entorno de desarrollo y OpenShift Pipelines

Ahora, si realizamos cambios en el archivo, la aplicación debería actualizarse en el navegador.

Bien, todo está claro con el desarrollo en modo local, pero ¿cómo lograr lo mismo en OpenShift?

Servidor de desarrollo en OpenShift

Si recuerdas, en Publicación anterior, observamos la llamada fase de ejecución de la imagen S2I y vimos que, de forma predeterminada, el módulo de servicio es responsable de dar servicio a nuestra aplicación web.

Sin embargo, si miras más de cerca ejecutar guión de ese ejemplo, contiene la variable de entorno $NPM_RUN, que le permite ejecutar su comando.

Por ejemplo, podemos usar el módulo nodeshift para implementar nuestra aplicación:

$ npx nodeshift --deploy.env NPM_RUN="yarn start" --dockerImage=nodeshift/ubi8-s2i-web-app

Nota: El ejemplo anterior está abreviado para ilustrar la idea general.

Aquí agregamos la variable de entorno NPM_RUN a nuestra implementación, que le indica al tiempo de ejecución que ejecute el comando de inicio de hilo, que inicia el servidor de desarrollo React dentro de nuestro pod OpenShift.

Si observa el registro de un pod en ejecución, se verá así:

Aplicaciones modernas en OpenShift, parte 3: OpenShift como entorno de desarrollo y OpenShift Pipelines

Por supuesto, todo esto no será nada hasta que podamos sincronizar el código local con el código, que también se monitorea para detectar cambios, pero que vive en un servidor remoto.

Sincronización de código remoto y local

Afortunadamente, nodeshift puede ayudar fácilmente con la sincronización y puede usar el comando de vigilancia para realizar un seguimiento de los cambios.

Entonces, después de haber ejecutado el comando para implementar el servidor de desarrollo para nuestra aplicación, podemos usar de forma segura el siguiente comando:

$ npx nodeshift watch

Como resultado, se establecerá una conexión con el pod en ejecución que creamos un poco antes, se activará la sincronización de nuestros archivos locales con el clúster remoto y los archivos en nuestro sistema local comenzarán a ser monitoreados para detectar cambios.

Por lo tanto, si ahora actualizamos el archivo src/App.js, el sistema reaccionará a estos cambios, los copiará al clúster remoto e iniciará el servidor de desarrollo, que luego actualizará nuestra aplicación en el navegador.

Para completar la imagen, mostremos cómo se ven estos comandos completos:

$ 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

El comando watch es una abstracción además del comando oc rsync; puede obtener más información sobre cómo funciona aquí.

Este fue un ejemplo para React, pero se puede usar exactamente el mismo método con otros marcos, simplemente configure la variable de entorno NPM_RUN según sea necesario.

Tuberías de cambio abierto

Aplicaciones modernas en OpenShift, parte 3: OpenShift como entorno de desarrollo y OpenShift Pipelines

A continuación hablaremos sobre una herramienta como OpenShift Pipelines y cómo se puede utilizar como alternativa a las compilaciones encadenadas.

¿Qué son las canalizaciones de OpenShift?

OpenShift Pipelines es un sistema de entrega e integración continua de CI/CD nativo de la nube diseñado para organizar tuberías utilizando Tekton. Tekton es un marco de CI/CD nativo de Kubernetes de código abierto flexible que le permite automatizar la implementación en varias plataformas (Kubernetes, sin servidor, máquinas virtuales, etc.) al abstraerse de la capa subyacente.

Comprender este artículo requiere algunos conocimientos de Pipelines, por lo que le recomendamos encarecidamente que primero lea libro de texto oficial.

Configurando tu ambiente de trabajo

Para jugar con los ejemplos de este artículo, primero debe preparar su entorno de trabajo:

  1. Instale y configure un clúster OpenShift 4. Nuestros ejemplos utilizan CodeReady Containers (CRD) para esto, cuyas instrucciones de instalación se pueden encontrar aquí.
  2. Una vez que el clúster esté listo, deberá instalar Pipeline Operador en él. No tengas miedo, es fácil, instrucciones de instalación. aquí.
  3. Descargar Tekton CLI (gracias) aquí.
  4. Ejecute la herramienta de línea de comando create-react-app para crear una aplicación que luego implementará (esta es una aplicación simple Reaccionar).
  5. (Opcional) Clone el repositorio para ejecutar la aplicación de ejemplo localmente con npm install y luego npm start.

El repositorio de aplicaciones también tendrá una carpeta k8s, que contendrá los YAML de Kubernetes/OpenShift utilizados para implementar la aplicación. Habrá tareas, tareas de clúster, recursos y canalizaciones que crearemos en este repositorios.

Bajando

El primer paso de nuestro ejemplo es crear un nuevo proyecto en el clúster de OpenShift. Llamemos a este proyecto webapp-pipeline y creémoslo con el siguiente comando:

$ oc new-project webapp-pipeline

El nombre de este proyecto aparecerá en el código más adelante, por lo que si decide ponerle otro nombre, no olvide editar el código de ejemplo en consecuencia. A partir de este punto, no iremos de arriba hacia abajo, sino de abajo hacia arriba: es decir, primero crearemos todos los componentes del transportador, y solo luego el transportador en sí.

Entonces, antes que nada...

Tareas

Creemos un par de tareas, que luego ayudarán a implementar la aplicación dentro de nuestra canalización. La primera tarea, apply_manifests_task, se encarga de aplicar el YAML de aquellos recursos de Kubernetes (servicio, implementación y ruta) que se encuentran en la carpeta k8s de nuestra aplicación. La segunda tarea, update_deployment_task, es responsable de actualizar una imagen ya implementada a la creada por nuestra canalización.

No te preocupes si aún no está muy claro. De hecho, estas tareas son algo así como utilidades y las veremos con más detalle un poco más adelante. Por ahora, simplemente creémoslos:

$ 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

Luego, mediante el comando tkn CLI comprobaremos que se han creado las tareas:

$ tkn task ls

NAME                AGE
apply-manifests     1 minute ago
update-deployment   1 minute ago

Nota: Estas son tareas locales para su proyecto actual.

Tareas de clúster

Las tareas de clúster son básicamente las mismas que las tareas simples. Es decir, es una colección reutilizable de pasos que se combinan de una forma u otra al ejecutar una tarea específica. La diferencia es que una tarea de clúster está disponible en todas partes dentro del clúster. Para ver la lista de tareas de clúster que se crean automáticamente al agregar el operador de canalización, usaremos nuevamente el comando CLI tkn:

$ 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

Ahora creemos dos tareas de clúster. El primero generará la imagen S2I y la enviará al registro interno de OpenShift; el segundo es construir nuestra imagen basada en NGINX, usando la aplicación que ya hemos creado como contenido.

Crear y enviar la imagen.

Al crear la primera tarea, repetiremos lo que ya hicimos en el artículo anterior sobre ensamblajes vinculados. Recuerde que usamos la imagen S2I (ubi8-s2i-web-app) para "construir" nuestra aplicación y terminamos con una imagen almacenada en el registro interno de OpenShift. Ahora usaremos esta imagen de la aplicación web S2I para crear un DockerFile para nuestra aplicación y luego usaremos Buildah para hacer la compilación real y enviar la imagen resultante al registro interno de OpenShift, ya que eso es exactamente lo que hace OpenShift cuando implementas tus aplicaciones usando NodeShift. .

¿Cómo supimos todo esto, preguntas? De versión oficial de Node.js oficial, simplemente lo copiamos y lo modificamos nosotros mismos.

Entonces, ahora creemos la tarea del clúster s2i-web-app:

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

No analizaremos esto en detalle, solo nos centraremos en el parámetro OUTPUT_DIR:

params:
      - name: OUTPUT_DIR
        description: The location of the build output directory
        default: build

De forma predeterminada, este parámetro es igual a compilación, que es donde React coloca el contenido ensamblado. Otros frameworks usan diferentes caminos, por ejemplo, en Ember es dist. El resultado de nuestra primera tarea de clúster será una imagen que contendrá el HTML, JavaScript y CSS que recopilamos.

Construya una imagen basada en NGINX

En cuanto a nuestra segunda tarea de clúster, debería crearnos una imagen basada en NGINX, utilizando el contenido de la aplicación que ya hemos creado. Básicamente, esta es la parte de la sección anterior donde analizamos las compilaciones encadenadas.

Para hacer esto, exactamente igual que arriba, crearemos una tarea de clúster webapp-build-runtime:

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

Si observa el código de estas tareas del clúster, puede ver que no especifica el repositorio Git con el que estamos trabajando ni los nombres de las imágenes que estamos creando. Solo especificamos qué estamos transfiriendo exactamente a Git, o una imagen determinada donde se debe generar la imagen final. Es por eso que estas tareas del clúster se pueden reutilizar cuando se trabaja con otras aplicaciones.

Y aquí pasamos con gracia al siguiente punto...

Recursos

Entonces, dado que, como acabamos de decir, las tareas del clúster deben ser lo más generales posible, necesitamos crear recursos que se utilizarán como entrada (el repositorio Git) y como salida (las imágenes finales). El primer recurso que necesitamos es Git, donde reside nuestra aplicación, algo como esto:

# 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

Aquí PipelineResource es de tipo git. La clave de URL en la sección de parámetros apunta a un repositorio específico y especifica la rama maestra (esto es opcional, pero lo escribimos para que esté completo).

Ahora necesitamos crear un recurso para la imagen donde se guardarán los resultados de la tarea s2i-web-app, esto se hace así:

# 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

Aquí, PipelineResource es de tipo imagen y el valor del parámetro URL apunta al Registro de imágenes interno de OpenShift, específicamente al que se encuentra en el espacio de nombres webapp-pipeline. No olvide cambiar esta configuración si está utilizando un espacio de nombres diferente.

Y finalmente, el último recurso que necesitamos también será de tipo imagen y esta será la imagen NGINX final que luego se usará durante la implementación:

# 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

Nuevamente, tenga en cuenta que este recurso almacena la imagen en el registro interno de OpenShift en el espacio de nombres webapp-pipeline.

Para crear todos estos recursos a la vez, usamos el comando crear:

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

Puede asegurarse de que los recursos se hayan creado así:

$ tkn resource ls

Tubería transportadora

Ahora que tenemos todos los componentes necesarios, armemos una tubería a partir de ellos creándola con el siguiente comando:

$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/pipelines/build-and-deploy-react.yaml

Pero antes de ejecutar este comando, veamos estos componentes. El primero es el nombre:

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

Luego, en la sección de especificaciones vemos una indicación de los recursos que creamos anteriormente:

spec:
  resources:
    - name: web-application-repo
      type: git
    - name: built-web-application-image
      type: image
    - name: runtime-web-application-image
      type: image

Luego creamos las tareas que nuestra canalización debe completar. En primer lugar se debe ejecutar la tarea s2i-web-app que ya hemos creado:

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

Esta tarea toma parámetros de entrada (recurso gir) y salida (recurso de imagen de aplicación web incorporada). También le pasamos un parámetro especial para que no verifique TLS ya que estamos usando certificados autofirmados:

resources:
        inputs:
          - name: source
            resource: web-application-repo
        outputs:
          - name: image
            resource: built-web-application-image
      params:
        - name: TLSVERIFY
          value: "false"

La siguiente tarea es casi la misma, solo que aquí se llama la tarea de clúster webapp-build-runtime que ya hemos creado:

name: build-runtime-image
    taskRef:
      name: webapp-build-runtime
      kind: ClusterTask

Al igual que con la tarea anterior, pasamos un recurso, pero ahora es una imagen de aplicación web integrada (el resultado de nuestra tarea anterior). Y como salida volvemos a configurar la imagen. Dado que esta tarea debe ejecutarse después de la anterior, agregamos el 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

Las siguientes dos tareas son responsables de utilizar los archivos YAML de servicio, ruta e implementación que se encuentran en el directorio k8s de nuestra aplicación web, y también de actualizar esta implementación al crear nuevas imágenes. Definimos estas dos tareas de clúster al principio del artículo.

Iniciando el transportador

Entonces, se crean todas las partes de nuestra canalización y la ejecutaremos con el siguiente comando:

$ tkn pipeline start build-and-deploy-react

En esta etapa, la línea de comando se usa de forma interactiva y debe seleccionar los recursos apropiados en respuesta a cada una de sus solicitudes: para el recurso git, seleccione web-application-repo, luego para el primer recurso de imagen, build-web-application -image, y finalmente, para el segundo recurso de imagen –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

Ahora verifiquemos el estado de la tubería usando el siguiente comando:

$ tkn pipeline logs -f

Una vez iniciado el pipeline y desplegada la aplicación, podemos solicitar la ruta publicada con el siguiente comando:

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

Para una mayor visualización, puede visualizar nuestro pipeline en el modo Desarrollador de la consola web en la sección Pipelines, como se muestra en la Fig. 1.

Aplicaciones modernas en OpenShift, parte 3: OpenShift como entorno de desarrollo y OpenShift Pipelines

Figura 1. Revisión de ductos en funcionamiento.

Al hacer clic en una canalización en ejecución se muestran detalles adicionales, como se muestra en la Figura 2.

Aplicaciones modernas en OpenShift, parte 3: OpenShift como entorno de desarrollo y OpenShift Pipelines

Arroz. 2. Información adicional sobre el oleoducto.

Después de obtener más información, puede ver las aplicaciones en ejecución en la vista. topología, como se muestra en la Fig.3.

Aplicaciones modernas en OpenShift, parte 3: OpenShift como entorno de desarrollo y OpenShift Pipelines

Fig 3. Cápsula lanzada.

Al hacer clic en el círculo en la esquina superior derecha del icono se abre nuestra aplicación, como se muestra en la Fig. 4.

Aplicaciones modernas en OpenShift, parte 3: OpenShift como entorno de desarrollo y OpenShift Pipelines

Arroz. 4. Ejecutando la aplicación React.

Conclusión

Entonces, mostramos cómo ejecutar un servidor de desarrollo para su aplicación en OpenShift y sincronizarlo con el sistema de archivos local. También vimos cómo simular una plantilla de compilación encadenada usando OpenShift Pipelines. Todos los códigos de ejemplo de este artículo se pueden encontrar aquí.

Recursos adicionales (ES)

Anuncios de próximos seminarios web

Estamos comenzando una serie de seminarios web los viernes sobre la experiencia nativa con Red Hat OpenShift Container Platform y Kubernetes:

Fuente: habr.com

Añadir un comentario