En las dos publicaciones anteriores, cubrimos 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 lista para usar, como NGINX, usando compilaciones encadenadas para implementación de producción.
Hoy le mostraremos cómo ejecutar un servidor de desarrollo para su aplicación en la plataforma OpenShift y sincronizarlo con el sistema de archivos local, además de hablar sobre qué es OpenShift Pipelines y cómo puede usarlo como alternativa a los ensamblados vinculados.
OpenShift como entorno de desarrollo
Flujo de trabajo de desarrollo
Como se discutió en la primera publicación , un flujo de trabajo de desarrollo típico para aplicaciones web modernas es simplemente un "servidor de desarrollo" que monitorea los cambios en los archivos locales. Cuando suceden, se inicia la compilación de la aplicación y luego se actualiza en el navegador.
En la mayoría de los marcos modernos, este "servidor de desarrollo" está integrado en las herramientas de línea de comandos correspondientes.
Ejemplo local
Primero, veamos cómo funciona esto en el caso de ejecutar aplicaciones localmente. Tome la aplicación React de artículos anteriores como ejemplo , aunque muchos de los mismos conceptos de flujo de trabajo se aplican a todos los demás marcos modernos.
Entonces, para iniciar el "servidor de desarrollo" en nuestro ejemplo de React, emitimos el siguiente comando:
$ npm run start
Luego, en la ventana del terminal veremos algo como lo siguiente:
Y nuestra aplicación se abrirá en el navegador predeterminado:
Ahora, si hacemos cambios en el archivo, entonces la aplicación debería actualizarse en el navegador.
Bien, con el desarrollo local todo está claro, pero ¿cómo lograr lo mismo en OpenShift?
Servidor de desarrollo OpenShift
Si recuerdas, en el post anterior analizamos la llamada fase de ejecución de la imagen S2I y vimos que por defecto el módulo de servicio se encarga de dar servicio a nuestra aplicación web.
Sin embargo, si observa más de cerca el script de ejecución de ese ejemplo, verá que contiene la variable de entorno $ NPM_RUN, que le permite ejecutar su propio 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 se abrevia para ilustrar la idea general.
Aquí hemos agregado la variable de entorno NPM_RUN a nuestra implementación, que le dice al tiempo de ejecución que ejecute el comando yarn start, que inicia el servidor de desarrollo React dentro de nuestro pod OpenShift.
Si observa el registro de un pod en ejecución, habrá algo como lo siguiente:
Por supuesto, todo esto no se tratará de nada hasta que podamos sincronizar el código local con el código que también se supervisa para detectar cambios, pero vive en un servidor remoto.
Sincronización de código local y remoto
Afortunadamente, nodeshift puede ayudar fácilmente con la sincronización, y puede usar el comando de reloj para rastrear los cambios.
Entonces, después de haber ejecutado el comando para implementar el servidor de desarrollo para nuestra aplicación, podemos usar de manera 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 serán monitoreados para detectar cambios.
Por lo tanto, si ahora actualizamos el archivo src / App.js, el sistema reaccionará a estos cambios, los copiará en el clúster remoto e iniciará el servidor de desarrollo, que luego actualizará nuestra aplicación en el navegador.
Para completar, mostremos cómo se ven estos comandos en su totalidad:
$ 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, solo configure la variable de entorno NPM_RUN según sea necesario.
Tuberías de Openshift
A continuación, hablaremos sobre una herramienta como OpenShift Pipelines y cómo se puede utilizar como alternativa a las compilaciones encadenadas.
¿Qué es OpenShift Pipelines?
OpenShift Pipelines es un sistema de entrega e integración continua de CI / CD basado en la nube para organizar tuberías utilizando Tekton. Tekton es un marco de CI / CD nativo de Kubernetes, de código abierto y flexible que automatiza las implementaciones en todas las plataformas (Kubernetes, sin servidor, máquinas virtuales, etc.) al abstraerse de la capa subyacente.
Se requiere cierto conocimiento de Pipelines para comprender este artículo, por lo que le recomendamos encarecidamente que primero lea el tutorial oficial .
Configurar el entorno de trabajo
Para jugar con los ejemplos de este artículo, primero debe preparar su entorno de producción:
- OpenShift 4. CodeReady Containers (CRD), .
- , , Pipeline Operator. , , .
- Tekton CLI (tkn) .
- create-react-app, , ( React).
- () , npm install npm start.
El repositorio de aplicaciones también tendrá una carpeta k8s, donde se ubicarán los YAML de Kubernetes / OpenShift utilizados para implementar la aplicación. Habrá Tareas, ClusterTasks, Recursos y Pipelines que crearemos en este repositorio .
Empecemos
El primer paso para 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
Además, este nombre del proyecto aparecerá en el código, por lo que si decide ponerle otro nombre, no olvide editar el código de los ejemplos 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 entonces él mismo.
Entonces, primero que nada ...
Tareas
Creemos un par de tareas que luego nos ayudarán a implementar la aplicación a través de nuestra canalización. La primera tarea, apply_manifests_task, se encarga de aplicar YAML a esos 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 se preocupe si aún no está claro. De hecho, estas tareas son algo así como utilidades, y las discutiremos con más detalle más adelante. Por ahora, vamos a crearlos:
$ 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, usando el comando tkn CLI, verifique que se hayan creado las tareas:
$ tkn task ls
NAME AGE
apply-manifests 1 minute ago
update-deployment 1 minute ago
Nota: estas son tareas locales de su proyecto actual.
Tareas de clúster
Las tareas agrupadas 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 iniciar una tarea específica. La diferencia es que la tarea del clúster está disponible en todas partes dentro del clúster. Para ver una lista de tareas de clúster que se crean automáticamente cuando se agrega el operador de canalización, use nuevamente el 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
Ahora creemos dos tareas de clúster. El primero generará una 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 ensamblado como contenido.
Crea y envía la imagen
Al crear la primera tarea, repetiremos lo que ya hicimos en el artículo anterior sobre ensamblados vinculados. Recuerde que usamos la imagen S2I (ubi8-s2i-web-app) para "construir" nuestra aplicación y terminamos con la imagen almacenada en el registro interno de OpenShift. Ahora usaremos esta imagen S2I de la aplicación web 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 esto es exactamente lo que hace OpenShift cuando implementa el suyo. aplicaciones que utilizan NodeShift.
¿Cómo supimos todo esto, preguntas? De la versión oficial de Node.js oficial , simplemente lo copiamos y lo terminamos por nosotros mismos.
Entonces, ahora creamos la tarea de clúster s2i-web-app:
$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/clustertasks/s2i-web-app-task.yaml
No entraremos en detalles sobre esto, sino que nos detendremos 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 build, que es donde React coloca el contenido recopilado. Otros marcos usan diferentes rutas, por ejemplo, Ember usa dist. El resultado de nuestra primera tarea de clúster será una imagen que contiene el HTML, JavaScript y CSS que hemos recopilado.
Construyendo una imagen basada en NGINX
En cuanto a nuestra segunda tarea de clúster, debería recopilar una imagen basada en NGINX para nosotros utilizando el contenido de la aplicación que ya hemos recopilado. Básicamente, esta es la parte de la sección anterior en la que analizamos las compilaciones encadenadas.
Para hacer esto, nosotros, de la misma manera que un poco antes, creamos 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 de clúster, puede ver que el repositorio de Git con el que estamos trabajando o los nombres de las imágenes que creamos no están especificados allí. Solo especificamos qué es exactamente lo que transferimos a Git, o una determinada imagen, donde debe mostrarse la imagen final. Es por eso que estas tareas de 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 de clúster deben generalizarse lo más posible, necesitamos crear recursos que se usarán en la entrada (repositorio Git) y la salida (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 params apunta a un repositorio específico y establece la rama maestra (esto es opcional, pero lo escribimos para completar).
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í, el PipelineResource es de tipo image, y el valor del parámetro url apunta al registro interno de imágenes de OpenShift, específicamente al del espacio de nombres webapp-pipeline. Recuerde cambiar este parámetro si está utilizando un espacio de nombres diferente.
Y finalmente, el último recurso que necesitaremos también será del tipo imagen y esta será la imagen final de NGINX, que luego se utilizará durante el despliegue:
# 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, observe 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, use el comando create:
$ 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
Pipeline pipeline
Ahora que tenemos todos los componentes necesarios, ensamblaremos un pipeline a partir de ellos, creándolo 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, echemos un vistazo a 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 tareas para que las complete nuestra canalización. En primer lugar, 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 integrado). 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 ya creada:
name: build-runtime-image
taskRef:
name: webapp-build-runtime
kind: ClusterTask
Al igual que con la tarea anterior, estamos pasando el 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 realizarse 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 las encargadas de aplicar el servicio, ruta y despliegue de archivos YAML que viven en el directorio k8s de nuestra aplicación web, y también de actualizar este despliegue al crear nuevas imágenes. Establecemos estas dos tareas de clúster al principio del artículo.
Ejecutando el transportador
Entonces, se crean todas las partes de nuestra canalización y la comenzaremos 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: built-web-application-image y, finalmente, para 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 canalización con el siguiente comando:
$ tkn pipeline logs -f
Una vez que se inicia la canalización y se implementa la aplicación, solicitamos la ruta publicada con el siguiente comando:
$ oc get route react-pipeline-example --template='http://{{.spec.host}}'
Para obtener más visibilidad, puede ver nuestra canalización en el modo Desarrollador de la consola web en la sección Pipelines , como se muestra en la Fig. 1.
Figura 1. Descripción general de las canalizaciones en ejecución.
Al hacer clic en una canalización en ejecución, se muestra información adicional, como se muestra en la Figura 2.
Figura: 2. Más información sobre la tubería.
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 Figura 3.
Fig 3. Pod para correr.
Al hacer clic en el círculo en la esquina superior derecha del icono, se abre nuestra aplicación, como se muestra en la Figura 4.
Figura: 4. Lanzamiento de la aplicación React.
Conclusión
Entonces, hemos mostrado 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 imitar la plantilla de construcción encadenada usando OpenShift Pipelines. Todos los códigos de muestra de este artículo se pueden encontrar aquí .
Recursos adicionales (EN)
- Libro electrónico gratuito "Desarrollando con OpenShift: Una guía para los impacientes"
- Cree aplicaciones Node.js orientadas a contenedores utilizando Red Hat OpenShift Application Runtimes e Istio
- Depuración de aplicaciones Node.js en OpenShift con Chrome DevTools
- Tres comandos para dominar Express en OpenShift desde cero
- Anuncio de una versión pública de Node.js como parte de los tiempos de ejecución de la aplicación Red Hat OpenShift
- Supervisión de aplicaciones de Node.js en OpenShift con Prometheus
- Más artículos sobre OpenShift y Kubernetes en Red Hat
Próximos anuncios de seminarios web
Estamos iniciando una serie de seminarios web los viernes sobre la experiencia nativa de usar Red Hat OpenShift Container Platform y Kubernetes:
- 28 de agosto, seminario web Emperor "Operator": operadores en OpenShift y Kubernetes
- 11 de septiembre, DeploymentConfig vs Deployment: magia específica de OpenShift para crear e implementar aplicaciones
- 25 de septiembre, Red Hat OpenShift y Machine API
- 9 de octubre, cómo hacer frente a un aumento repentino de la carga
- 23 de octubre, Jenkins integrado, Pipeline-builds, Tekton en Red Hat OpenShift Container Platform