Dans les deux articles précédents, nous avons expliqué comment déployer des applications Web modernes en quelques étapes seulement et comment utiliser une nouvelle image S2I avec une image de serveur HTTP prête à l'emploi telle que NGINX à l'aide de versions chaînées pour le déploiement en production.
Aujourd'hui, nous allons vous montrer comment exécuter un serveur de développement pour votre application sur la plate-forme OpenShift et le synchroniser avec le système de fichiers local, ainsi que parler de ce qu'est OpenShift Pipelines et comment vous pouvez l'utiliser comme alternative aux assemblys liés.
OpenShift comme environnement de développement
Workflow de développement
Comme indiqué dans le premier article , un flux de travail de développement typique pour les applications Web modernes est simplement un «serveur de développement» qui surveille les modifications des fichiers locaux. Quand ils se produisent, la construction de l'application est lancée, puis elle est mise à jour dans le navigateur.
Dans la plupart des frameworks modernes, ce "serveur de développement" est intégré aux outils de ligne de commande correspondants.
Exemple local
Voyons d'abord comment cela fonctionne dans le cas de l'exécution d'applications localement. Prenons comme exemple l'application React des articles précédents, bien que la plupart des mêmes concepts de flux de travail s'appliquent à tous les autres frameworks modernes.
Ainsi, pour démarrer le "serveur de développement" dans notre exemple React, nous émettons la commande suivante:
$ npm run start
Ensuite, dans la fenêtre du terminal, nous verrons quelque chose comme ce qui suit:
Et notre application s'ouvrira dans le navigateur par défaut:
Maintenant, si nous apportons des modifications au fichier, l'application doit se mettre à jour dans le navigateur.
OK, avec le développement local, tout est clair, mais comment faire la même chose sur OpenShift?
Serveur de développement sur OpenShift
Si vous vous souvenez, dans le post précédent , nous avons analysé la phase dite d'exécution de l'image S2I et avons vu que par défaut, le module de service est chargé de servir notre application Web.
Cependant, si vous regardez de plus près le script d'exécution de cet exemple, vous verrez qu'il contient la variable d'environnement $ NPM_RUN, qui vous permet d'exécuter votre propre commande.
Par exemple, nous pouvons 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 abrégé pour illustrer l'idée générale.
Ici, nous avons ajouté la variable d'environnement NPM_RUN à notre déploiement, qui indique au runtime d'exécuter la commande yarn start, qui démarre le serveur de développement React dans notre pod OpenShift.
Si vous regardez le journal d'un pod en cours d'exécution, il y aura quelque chose comme ce qui suit:
Bien sûr, tout cela ne sera rien tant que nous ne pourrons pas synchroniser le code local avec du code qui est également surveillé pour les changements, mais qui vit sur un serveur distant.
Synchronisation du code distant et local
Heureusement, nodeshift peut facilement aider à la synchronisation et vous pouvez utiliser la commande watch pour suivre les modifications.
Ainsi, après avoir exécuté la commande pour déployer le serveur de développement pour notre application, nous pouvons utiliser en toute sécurité la commande suivante:
$ npx nodeshift watch
En conséquence, une connexion sera établie avec le pod en cours d'exécution, que nous avons créé un peu plus tôt, la synchronisation de nos fichiers locaux avec le cluster distant sera activée et les fichiers sur notre système local seront surveillés pour les changements.
Par conséquent, si nous mettons maintenant à jour le fichier src / App.js, le système réagira à ces modifications, les copiera dans le cluster distant et démarrera le serveur de développement, qui mettra ensuite à jour notre application dans le navigateur.
Pour être complet, montrons à quoi ressemblent ces commandes 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 par dessus la commande oc rsync, vous pouvez en savoir plus sur son fonctionnement ici .
C'était un exemple pour React, mais la même méthode peut être utilisée avec d'autres frameworks, il suffit de définir la variable d'environnement NPM_RUN si nécessaire.
Pipelines OpenShift
Ensuite, nous parlerons d'un outil comme OpenShift Pipelines et de la manière dont il peut être utilisé comme alternative aux builds chaînés.
Qu'est-ce que les pipelines OpenShift?
OpenShift Pipelines est un système d'intégration et de livraison continue CI / CD basé sur le cloud pour organiser les pipelines à l'aide de Tekton. Tekton est un framework CI / CD natif Kubernetes flexible et open source qui automatise les déploiements sur les plates-formes (Kubernetes, sans serveur, machines virtuelles, etc.) en faisant abstraction de la couche sous-jacente.
Une certaine connaissance de Pipelines est nécessaire pour comprendre cet article, nous vous conseillons donc vivement de lire d'abord le tutoriel officiel .
Mise en place de l'environnement de travail
Pour jouer avec les exemples de cet article, vous devez d'abord préparer votre environnement de production:
- OpenShift 4. CodeReady Containers (CRD), .
- , , Pipeline Operator. , , .
- Tekton CLI (tkn) .
- create-react-app, , ( React).
- () , npm install npm start.
Le référentiel d'applications aura également un dossier k8s, dans lequel se trouveront les YAML Kubernetes / OpenShift utilisés pour déployer l'application. Il y aura des tâches, des tâches de cluster, des ressources et des pipelines que nous créerons dans ce référentiel .
Commençons
La première étape de notre exemple consiste à créer un nouveau projet dans le cluster OpenShift. Appelons ce projet webapp-pipeline et créons-le avec la commande suivante:
$ oc new-project webapp-pipeline
De plus, ce nom de projet apparaîtra dans le code, donc si vous décidez de lui donner un autre nom, n'oubliez pas de modifier le code des exemples en conséquence. À partir de là, nous n'irons pas de haut en bas, mais de bas en haut: c'est-à-dire que nous allons d'abord créer tous les composants du convoyeur, et seulement ensuite lui-même.
Alors, tout d'abord ...
Tâches
Créons quelques tâches qui nous aideront ensuite à déployer l'application via notre pipeline. La première tâche, apply_manifests_task, est chargée d'appliquer YAML aux ressources Kubernetes (service, déploiement 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 d'une image déjà déployée vers celle créée par notre pipeline.
Ne vous inquiétez pas si ce n'est pas encore clair. En fait, ces tâches sont quelque chose comme des utilitaires, et nous les discuterons 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, à l'aide de la commande CLI tkn, vérifiez que les tâches ont été créées:
$ tkn task ls
NAME AGE
apply-manifests 1 minute ago
update-deployment 1 minute ago
Remarque: ce sont des tâches locales de votre projet actuel.
Tâches de cluster
Les tâches groupées sont fondamentalement les mêmes que les tâches simples. Autrement dit, il s'agit d'une collection réutilisable d'étapes qui sont combinées d'une manière ou d'une autre lors du démarrage d'une tâche spécifique. La différence est que la tâche de cluster est disponible partout dans le cluster. Pour afficher une liste des tâches de cluster qui sont automatiquement créées lors de l'ajout de l'opérateur de pipeline, utilisez à nouveau la commande 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
Créons maintenant deux tâches de cluster. Le premier va générer une image S2I et l'envoyer au registre interne OpenShift; la seconde est de construire notre image basée sur NGINX en utilisant l'application que nous avons déjà assemblée comme contenu.
Créer et envoyer l'image
Lors de la création de la première tâche, nous répéterons ce que nous avons déjà fait dans l'article précédent sur les assemblys liés. Rappelons que nous avons utilisé l'image S2I (ubi8-s2i-web-app) pour «construire» notre application et que nous avons fini avec l'image stockée dans le registre interne d'OpenShift. Nous allons maintenant utiliser cette image S2I de l'application Web pour créer un DockerFile pour notre application, puis utiliser Buildah pour faire la construction réelle et pousser l'image résultante dans le registre OpenShift interne, car c'est exactement ce que fait OpenShift lorsque vous déployez le vôtre. applications utilisant NodeShift.
Comment savions-nous tout cela, demandez-vous? À partir de la version officielle de Node.js officiel , nous venons de le copier et de le terminer nous-mêmes.
Nous créons donc maintenant 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 n'entrerons pas dans les détails à ce sujet, mais nous attarderons simplement sur le paramètre OUTPUT_DIR:
params:
- name: OUTPUT_DIR
description: The location of the build output directory
default: build
Par défaut, ce paramètre est défini sur build, c'est là que React place le contenu collecté. D'autres frameworks utilisent des chemins différents, par exemple Ember utilise dist. La sortie de notre première tâche de cluster sera une image contenant le HTML, le JavaScript et le CSS que nous avons collectés.
Construire une image basée sur NGINX
Quant à notre deuxième tâche de cluster, elle devrait nous collecter une image basée sur NGINX, en utilisant le contenu de l'application que nous avons déjà collecté. Fondamentalement, c'est la partie de la section précédente où nous avons examiné les versions chaînées.
Pour ce faire, nous créons - de la même manière qu'un peu ci-dessus - une 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 vous regardez le code de ces tâches de cluster, vous pouvez voir que le référentiel Git avec lequel nous travaillons ou les noms des images que nous créons n'y sont pas spécifiés. Nous spécifions uniquement ce que nous transférons exactement vers Git, ou une certaine image, où l'image finale doit être affichée. C'est pourquoi ces tâches de cluster peuvent être réutilisées lorsque vous travaillez avec d'autres applications.
Et ici, nous passons gracieusement au point suivant ...
Ressources
Ainsi, puisque, comme nous venons de le dire, les tâches de cluster doivent être aussi génériques que possible, nous devons créer des ressources qui seront utilisées en entrée (référentiel Git) et en sortie (images finales). La première ressource dont nous avons besoin est Git où réside notre application, quelque chose comme ceci:
# 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 pointe vers un référentiel spécifique et définit la branche master (c'est facultatif, mais nous l'écrivons par souci d'exhaustivité).
Maintenant, nous devons créer une ressource pour l'image, où les résultats de la tâche s2i-web-app seront enregistrés, ceci se fait comme ceci:
# 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 interne d'images OpenShift, en particulier vers celui de l'espace de noms webapp-pipeline. N'oubliez pas de modifier ce paramètre si vous utilisez un espace de noms différent.
Et enfin, la dernière ressource dont nous avons besoin sera également de type image et ce sera l'image NGINX finale, 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
Encore une fois, notez que cette ressource stocke l'image dans le registre OpenShift interne dans l'espace de noms webapp-pipeline.
Pour créer toutes ces ressources à la fois, utilisez la commande create:
$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/resources/resource.yaml
Vous pouvez vous assurer que les ressources ont été créées comme ceci:
$ tkn resource ls
Pipeline
Maintenant que nous avons tous les composants nécessaires, nous allons assembler un pipeline à partir d'eux, en le créant avec 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, jetons un coup d'œil à ces composants. Le premier est le nom:
apiVersion: tekton.dev/v1alpha1
kind: Pipeline
metadata:
name: build-and-deploy-react
Ensuite, dans la section spec, nous voyons une indication des 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 des tâches que notre pipeline doit terminer. Tout d'abord, 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 d'image d'application Web intégrée). Nous lui passons également un paramètre spécial afin qu'il ne vérifie pas TLS puisque nous utilisons des certificats auto-signés:
resources:
inputs:
- name: source
resource: web-application-repo
outputs:
- name: image
resource: built-web-application-image
params:
- name: TLSVERIFY
value: "false"
La tâche suivante est presque la même, mais ici, la tâche de cluster webapp-build-runtime déjà créée est appelée:
name: build-runtime-image
taskRef:
name: webapp-build-runtime
kind: ClusterTask
Comme pour la tâche précédente, nous transmettons la ressource, mais il s'agit maintenant d'une image d'application Web intégrée (la sortie de notre tâche précédente). Et en sortie, nous définissons à nouveau l'image. Puisque cette tâche doit être effectuée après la précédente, nous ajoutons le champ 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
Les deux tâches suivantes sont chargées d'appliquer les fichiers YAML de service, de routage et de déploiement qui résident dans le répertoire k8s de notre application Web, ainsi que de mettre à jour ce déploiement lors de la création de nouvelles images. Nous définissons ces deux tâches de cluster au début de l'article.
Faire fonctionner le convoyeur
Ainsi, toutes les parties de notre pipeline sont créées et nous allons le démarrer avec la commande suivante:
$ tkn pipeline start build-and-deploy-react
A ce stade, la ligne de commande est utilisée de manière interactive et vous devez sélectionner les ressources appropriées en réponse à chacune de ses requêtes: pour la ressource git, sélectionnez le repo-application-web, puis pour la ressource de la première image, sélectionnez l'image-application-web-intégrée, et enfin pour deuxième ressource 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
Une fois le pipeline démarré et l'application déployée, nous demandons la route publiée avec la commande suivante:
$ oc get route react-pipeline-example --template='http://{{.spec.host}}'
Pour plus de visibilité, vous pouvez afficher notre pipeline en mode développeur de la console Web dans la section Pipelines , comme illustré à la Fig. 1.
Fig. 1. Vue d'ensemble des pipelines en cours d'exécution.
Cliquez sur un pipeline en cours d'exécution pour afficher des informations supplémentaires, comme illustré à la figure 2.
Figure: 2. Plus d'informations sur le pipeline.
Après plus d'informations, vous pouvez voir les applications en cours d'exécution dans la vue Topologie , comme illustré à la figure 3.
Fig 3. Pod en marche.
Cliquez sur le cercle dans le coin supérieur droit de l'icône pour ouvrir notre application, comme le montre la figure 4.
Figure: 4. Lancement de l'application React.
Conclusion
Nous avons donc montré comment exécuter 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 imiter le modèle de construction en chaîne à l'aide d'OpenShift Pipelines. Tous les exemples de codes de cet article peuvent être trouvés ici .
Ressources supplémentaires (EN)
- Livre électronique gratuit "Développer avec OpenShift: un guide pour les impatients"
- Créez des applications Node.js orientées conteneur à l'aide de Red Hat OpenShift Application Runtimes et Istio
- Débogage des applications Node.js sur OpenShift avec Chrome DevTools
- Trois commandes pour maîtriser Express sur OpenShift à partir de zéro
- Annonce d'une version publique de Node.js dans le cadre des Runtimes d'application Red Hat OpenShift
- Surveillance des applications Node.js sur OpenShift avec Prometheus
- Plus d'articles sur OpenShift et Kubernetes sur Red Hat
Annonces de webinaires à venir
Nous lançons une série de webinaires du vendredi sur l'expérience native de l'utilisation de Red Hat OpenShift Container Platform et de Kubernetes:
- 28 août, webinaire Emperor "Operator": Operators in OpenShift et Kubernetes
- 11 septembre, DeploymentConfig vs Deployment - Magie spécifique à OpenShift pour la création et le déploiement d'applications
- 25 septembre, Red Hat OpenShift et Machine API
- 9 octobre, Comment faire face à une croissance soudaine de la charge
- 23 octobre, Jenkins intégré, builds de pipeline, Tekton à Red Hat OpenShift Container Platform