Bonjour à tous sur ce blog ! Voici la troisième publication d'une série où nous montrons comment déployer des applications web modernes sur Red Hat OpenShift.

Dans les deux précédentes publications, nous avons expliqué comment déployer des applications web modernes en quelques étapes et comment utiliser une nouvelle image S2I accompagnée d'une image de serveur HTTP prête à l'emploi, comme NGINX, grâce aux builds liés pour organiser un déploiement en production.
Aujourd'hui, nous allons vous montrer comment lancer un serveur de développement pour votre application sur la plateforme OpenShift et le synchroniser avec le système de fichiers local, ainsi que discuter de ce que sont les OpenShift Pipelines et comment les utiliser comme alternative aux builds liés.
OpenShift en tant qu'environnement de développement
Flux de travail de développement
Comme déjà mentionné dans , un processus de développement typique pour les applications web modernes consiste simplement en un « serveur de développement » qui surveille les modifications des fichiers locaux. Lorsqu'une modification est détectée, une compilation de l'application est lancée, puis celle-ci est mise à jour dans le navigateur.
Dans la plupart des frameworks modernes, un tel « serveur de développement » est intégré dans les outils de ligne de commande appropriés.
Exemple local
Pour commencer, voyons comment cela fonctionne dans le cas d'un lancement local d'applications. Prenons par exemple l'application des articles précédents, bien que les mêmes concepts de flux de travail s'appliquent également à tous les autres frameworks modernes.
Donc, pour lancer un « serveur de développement » dans notre exemple avec React, nous allons entrer la commande suivante :
$ npm run start
Dans la fenêtre du terminal, nous devrions voir quelque chose comme ceci :

Et notre application s'ouvrira dans le navigateur par défaut :

Maintenant, si nous apportons des modifications au fichier, l'application devrait se mettre à jour dans le navigateur.
D'accord, le développement en mode local est clair, mais comment obtenir la même chose sur OpenShift ?
Serveur de développement sur OpenShift
Si vous vous souvenez, dans , nous avons examiné ce qu'on appelle la phase de lancement (run phase) de l'image S2I et avons vu que par défaut, le module serve se charge de notre application web.
Cependant, si vous regardez de plus près de cet exemple, il y a une variable d'environnement $NPM_RUN, qui permet d'exécuter votre propre commande.
Par exemple, vous pouvez utiliser le module nodeshift pour déployer notre application :
$ npx nodeshift --deploy.env NPM_RUN="yarn start" --dockerImage=nodeshift/ubi8-s2i-web-app
Remarque : l'exemple ci-dessus est présenté sous forme abrégée pour illustrer l'idée générale.
Ici, nous avons ajouté à notre déploiement la variable d'environnement NPM_RUN, qui indique à l'étape d'exécution qu'elle doit lancer la commande yarn start, démarrant ainsi le serveur de développement React à l'intérieur de notre pod OpenShift.
Si l'on consulte les journaux du pod en cours d'exécution, on obtiendra quelque chose de similaire :

Bien sûr, tout cela n'aura pas d'importance tant que nous ne pourrons pas synchroniser le code local avec le code qui est également contrôlé pour des changements, mais qui vit sur un serveur distant.
Synchronisation du code distant et local
Heureusement, la synchronisation est facilement facilitée par nodeshift, et pour suivre les changements, on peut utiliser la commande watch.
Ainsi, après avoir exécuté la commande pour déployer le serveur de développement de notre application, nous pouvons utiliser la commande suivante :
$ npx nodeshift watch
Cela établira une connexion avec le pod en cours d'exécution que nous avons créé un peu plus tôt, activera la synchronisation de nos fichiers locaux avec le cluster distant, et les fichiers de notre système local commenceront à être surveillés pour des changements.
Par conséquent, si nous mettons à jour le fichier src/App.js, le système réagira à ces changements, les copiera sur le cluster distant et lancera le serveur de développement, qui mettra ensuite à jour notre application dans le navigateur.
Pour compléter le tableau, montrons comment ces commandes se présentent dans leur intégralité :
$ 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
La commande watch est une abstraction au-dessus de la commande oc rsync, vous pouvez en apprendre davantage sur son fonctionnement. .
C'était un exemple pour React, mais la même méthode peut être utilisée avec d'autres frameworks, il suffit d'écrire la variable d'environnement NPM_RUN de la manière appropriée.
Pipelines OpenShift

Ensuite, nous parlerons d'un outil appelé OpenShift Pipelines et de la façon dont il peut être utilisé comme alternative aux builds liés (chained builds).
Qu'est-ce qu'OpenShift Pipelines ?
OpenShift Pipelines est un système CI/CD basé sur le cloud, conçu pour organiser des pipelines en utilisant Tekton. Tekton est un framework CI/CD natif Kubernetes flexible et open source, permettant d'automatiser le déploiement sur diverses plateformes (Kubernetes, sans serveur, machines virtuelles, etc.) en abstrahant le niveau sous-jacent.
Pour comprendre cet article, certaines connaissances sur les Pipelines sont nécessaires, nous vous conseillons donc de consulter d'abord le .
Configuration de l'environnement de travail
Pour expérimenter avec les exemples de cet article, vous devez d'abord préparer l'environnement de travail :
- Installer et configurer un cluster OpenShift 4. Dans nos exemples, nous utilisons CodeReady Containers (CRD), les instructions d'installation peuvent être trouvées .
- Après que le cluster soit prêt, vous devez installer le Pipeline Operator. Ne vous inquiétez pas, c'est facile, les instructions d'installation .
- Télécharger (tkn) .
- Lancer l'outil en ligne de commande create-react-app pour créer une application qui sera ensuite déployée (c'est une application simple ).
- (Optionnel) Cloner le dépôt pour exécuter localement l'exemple d'application avec la commande npm install puis npm start.
Dans le dépôt de l'application, il y aura également un dossier k8s, où se trouveront les YAML de Kubernetes/OpenShift utilisés pour le déploiement de l'application. Il y aura des Tasks, ClusterTasks, Resources et Pipelines que nous créerons dans ce .
Nous nous y mettons
Tout d'abord, pour notre exemple, nous devons créer un nouveau projet dans le cluster OpenShift. Nommez ce projet webapp-pipeline et créez-le avec la commande suivante :
$ oc new-project webapp-pipeline
Par la suite, ce nom de projet apparaîtra dans le code, donc si vous décidez de l'appeler différemment, n'oubliez pas d'ajuster le code des exemples en conséquence. À partir de ce point, nous allons procéder de bas en haut : c'est-à-dire, d'abord créer tous les composants du pipeline, puis le pipeline lui-même.
Donc, tout d'abord…
Tâches Tasks
Créons deux tâches (tasks) qui aideront ensuite à déployer l'application dans notre pipeline. La première tâche – apply_manifests_task – est responsable de l'application des ressources Kubernetes YAML (service, deployment et route) qui se trouvent dans le dossier k8s de notre application. La deuxième tâche – update_deployment_task – est responsable de la mise à jour de l'image déjà déployée vers celle qui est créée par notre pipeline.
Ne vous inquiétez pas si ce n'est pas très clair pour l'instant. En fait, ces tâches sont quelque chose comme des utilitaires, et nous les examinerons plus en détail un peu plus tard. Pour l’instant, créons-les simplement :
$ 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
Ensuite, vérifions que les tâches ont été créées avec la commande tkn CLI :
$ tkn task ls
NOM ÂGE
apply-manifests il y a 1 minute
update-deployment il y a 1 minute
Remarque : ce sont des tâches locales pour votre projet actuel.
Tâches de cluster (Cluster tasks)
Les tâches de cluster sont en fait les mêmes que les simples tâches. C'est-à-dire, une collection réutilisable d'étapes qui sont combinées d'une manière ou d'une autre lors de l'exécution d'une tâche spécifique. La différence est qu'une tâche de cluster est accessible partout dans le cluster. Pour voir la liste des tâches de cluster qui sont automatiquement créées lorsque l'on ajoute le Pipeline Operator, utilisons à nouveau la commande tkn CLI :
$ tkn clustertask ls
NOM ÂGE
buildah il y a 1 jour
buildah-v0-10-0 il y a 1 jour
jib-maven il y a 1 jour
kn il y a 1 jour
maven il y a 1 jour
openshift-client il y a 1 jour
openshift-client-v0-10-0 il y a 1 jour
s2i il y a 1 jour
s2i-go il y a 1 jour
s2i-go-v0-10-0 il y a 1 jour
s2i-java-11 il y a 1 jour
s2i-java-11-v0-10-0 il y a 1 jour
s2i-java-8 il y a 1 jour
s2i-java-8-v0-10-0 il y a 1 jour
s2i-nodejs il y a 1 jour
s2i-nodejs-v0-10-0 il y a 1 jour
s2i-perl il y a 1 jour
s2i-perl-v0-10-0 il y a 1 jour
s2i-php il y a 1 jour
s2i-php-v0-10-0 il y a 1 jour
s2i-python-3 il y a 1 jour
s2i-python-3-v0-10-0 il y a 1 jour
s2i-ruby il y a 1 jour
s2i-ruby-v0-10-0 il y a 1 jour
s2i-v0-10-0 il y a 1 jour
Et maintenant, créons deux tâches de cluster. La première générera une image S2I et l'enverra dans le registre interne d'OpenShift ; la deuxième exécutera la construction de notre image basée sur NGINX, en utilisant comme contenu l'application que nous avons déjà construite.
Créons et envoyons l'image
Lors de la création de la première tâche, nous allons répéter ce que nous avons déjà fait dans l'article précédent sur les builds liés. Rappelons que nous avons utilisé une image S2I (ubi8-s2i-web-app) pour « construire » notre application, et au final, nous obtenions une image stockée dans le registre interne d'OpenShift. Maintenant, nous allons utiliser cette image S2I de l'application web pour créer un DockerFile pour notre application, puis nous allons utiliser Buildah pour effectuer la véritable construction et envoyer l'image obtenue dans le registre interne d'OpenShift, car c'est exactement ce qu'OpenShift fait lorsque vous déployez vos applications avec NodeShift.
Vous vous demandez d'où nous avons tiré tout cela ? De , nous avons simplement copié cela et l'avons adapté pour nous.
Donc, maintenant, créons la tâche de cluster s2i-web-app :
$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/clustertasks/s2i-web-app-task.yaml
Nous ne détaillerons pas cela, mais nous nous attarderons sur le paramètre OUTPUT_DIR :
params:
- name: OUTPUT_DIR
description: L'emplacement du répertoire de sortie de la construction
default: build
Par défaut, ce paramètre est égal à build, c'est là que React stocke le contenu construit. D'autres frameworks utilisent d'autres chemins, par exemple, dans Ember, c'est dist. La sortie de notre première tâche de cluster sera une image contenant le HTML, JavaScript et CSS que nous avons construits.
Construire une image basée sur NGINX
En ce qui concerne notre deuxième tâche de cluster, elle doit nous construire une image basée sur NGINX, en utilisant le contenu de notre application déjà construite. En essence, c'est la partie de la section précédente où nous avons examiné les builds liés.
Pour cela, nous allons – tout comme ci-dessus – créer la tâche de cluster webapp-build-runtime :
$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/clustertasks/webapp-build-runtime-task.yaml
Si nous regardons le code de ces tâches de cluster, nous voyons qu'il n'y a pas de spécification du dépôt Git avec lequel nous travaillons, ni des noms des images que nous créons. Nous ne faisons qu'indiquer ce que nous transmettons à Git, ou bien une image dans laquelle il faut exporter l'image finale. C'est pourquoi ces tâches de cluster peuvent être réutilisées lorsque nous travaillons avec d'autres applications.
Et ici, nous passons élégamment au point suivant…
Ressources
Ainsi, comme nous venons de le dire, les tâches de cluster doivent être aussi généralisées que possible, nous devons créer des ressources qui seront utilisées en entrée (dépôt Git) et en sortie (images finales). La première ressource dont nous avons besoin est Git, où se trouve notre application, quelque chose comme cela :
# 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
Ici, PipelineResource est de type git. La clé url dans la section params indique le dépôt spécifique et définit la branche master (c'est optionnel, mais nous l'écrivons pour la complétude).
Maintenant, nous devons créer une ressource pour l'image, où seront enregistrés les résultats de l'exécution de la tâche s2i-web-app, cela se fait comme suit :
# 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
Ici, PipelineResource est de type image, et la valeur du paramètre url pointe vers le registre d'images OpenShift interne, plus précisément celui qui se trouve dans l'espace de noms webapp-pipeline. N'oubliez pas de changer ce paramètre si vous utilisez un autre espace de noms.
Et enfin, la dernière ressource dont nous aurons besoin aura également le type image et ce sera l'image finale NGINX, qui sera ensuite utilisée lors du déploiement :
# 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
Et encore une fois, notez que cette ressource enregistre l'image dans le registre interne d'OpenShift dans l'espace de noms webapp-pipeline.
Pour créer toutes ces ressources en une seule fois, utilisons la commande create :
$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/resources/resource.yaml
Vous pouvez vérifier que les ressources ont été créées comme cela :
$ tkn resource ls
Pipeline
Maintenant que nous avons tous les éléments nécessaires, construisons le pipeline à partir de ceux-ci en exécutant la commande suivante :
$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/pipelines/build-and-deploy-react.yaml
Mais avant d'exécuter cette commande, examinons ces éléments. Le premier est le nom :
apiVersion: tekton.dev/v1alpha1
kind: Pipeline
metadata:
name: build-and-deploy-react
Ensuite, dans la section spec, nous voyons la référence aux ressources que nous avons créées précédemment :
spec:
resources:
- name: web-application-repo
type: git
- name: built-web-application-image
type: image
- name: runtime-web-application-image
type: image
Ensuite, nous créons les tâches que notre pipeline doit exécuter. Premièrement, il doit exécuter la tâche s2i-web-app que nous avons déjà créée :
tasks:
- name: build-web-application
taskRef:
name: s2i-web-app
kind: ClusterTask
Cette tâche prend les paramètres d'entrée (ressource gir) et de sortie (ressource built-web-application-image). Nous lui passons également un paramètre spécial pour qu'elle ne vérifie pas le TLS, car nous utilisons des certificats auto-signés :
ressources:
entrées:
- nom: source
ressource: web-application-repo
sorties:
- nom: image
ressource: built-web-application-image
paramètres:
- nom: TLSVERIFY
valeur: "false"
La tâche suivante est presque identique, seulement ici nous appelons déjà la tâche de cluster que nous avons créée, webapp-build-runtime :
nom: build-runtime-image
taskRef:
nom: webapp-build-runtime
type: ClusterTask
Comme pour la tâche précédente, nous transférons la ressource, mais maintenant il s'agit de built-web-application-image (la sortie de notre tâche précédente). Et en tant que sortie, nous demandons à nouveau l'image. Comme cette tâche doit être exécutée après la précédente, nous ajoutons le champ runAfter :
ressources:
entrées:
- nom: image
ressource: built-web-application-image
sorties:
- nom: image
ressource: runtime-web-application-image
paramètres:
- nom: TLSVERIFY
valeur: "false"
runAfter:
- build-web-application
Les deux tâches suivantes sont responsables de l'application des fichiers YAML du service, du routage et du déploiement, qui se trouvent dans le répertoire k8s de notre application Web, ainsi que de la mise à jour de ce déploiement lors de la création de nouvelles images. Ces deux tâches de cluster ont été définies au début de l'article.
Démarrer le pipeline
Ainsi, toutes les parties de notre pipeline sont créées, et nous allons le lancer avec la commande suivante :
$ tkn pipeline start build-and-deploy-react
À ce stade, la ligne de commande est utilisée en mode interactif et il faut sélectionner les ressources appropriées en réponse à chacune de ses demandes : pour la ressource git, nous choisissons web-application-repo, ensuite pour la première image – built-web-application-image, et enfin pour la deuxième image – 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
Maintenant, vérifions l'état du pipeline avec la commande suivante :
$ tkn pipeline logs -f
Après que le pipeline a démarré et que l'application est déployée, interrogeons le route publié avec la commande suivante :
$ oc get route react-pipeline-example --template='http://{{.spec.host}}'
Pour plus de visibilité, nous pouvons voir notre pipeline en mode Developer dans la console Web dans la section Pipelines, comme indiqué à la Fig. 1.

Fig. 1. Vue d'ensemble des pipelines en cours d'exécution.
Cliquer sur le pipeline en cours d'exécution affiche des informations supplémentaires, comme indiqué à la Fig. 2.

Fig. 2. Informations supplémentaires sur le pipeline.
Après les informations supplémentaires, nous pouvons voir les applications en cours d'exécution dans la vue Topology, comme indiqué à la Fig. 3.

Fig 3. Pod en cours d'exécution.
Cliquer sur le cercle en haut à droite de l'icône ouvre notre application, comme indiqué à la Fig. 4.

Fig. 4. Application React en cours d'exécution.
Conclusion
Nous avons donc montré comment déployer un serveur de développement pour votre application sur OpenShift et le synchroniser avec le système de fichiers local. Nous avons également examiné comment simuler un modèle de chained-build à l'aide des OpenShift Pipelines. Tous les codes d'exemple de cet article peuvent être trouvés .
Ressources supplémentaires (EN)
- E-book gratuit
- D'autres articles sur le site de Red Hat
Annonces des prochains webinaires
Nous lançons une série de webinaires vendredi sur l'expérience native avec Red Hat OpenShift Container Platform et Kubernetes :
Source : habr.com
