Applications modernes sur OpenShift, partie 3 : OpenShift en tant qu'environnement de développement et OpenShift Pipelines

Bonjour à tous sur ce blog ! Il s'agit du troisième article d'une série dans laquelle nous montrons comment déployer des applications Web modernes sur Red Hat OpenShift.

Applications modernes sur OpenShift, partie 3 : OpenShift en tant qu'environnement de développement et OpenShift Pipelines

Dans les deux articles précédents, nous avons montré comment déployer des applications Web modernes en quelques étapes seulement et comment utiliser une nouvelle image S2I avec une image de serveur HTTP standard, telle que NGINX, en utilisant des builds chaînés pour orchestrer les déploiements de production. .

Aujourd'hui, nous allons 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, et parler également de ce que sont les pipelines OpenShift et de la manière dont ils peuvent être utilisés comme alternative aux assemblys liés.

OpenShift comme environnement de développement

Flux de travail de développement

Comme mentionné dans premier poste, le processus de développement typique des applications Web modernes est simplement une sorte de « serveur de développement » qui suit les modifications apportées aux fichiers locaux. Lorsqu’ils se produisent, la construction de l’application est déclenchée puis mise à jour dans le navigateur.

Dans la plupart des frameworks modernes, un tel « serveur de développement » est intégré aux outils de ligne de commande correspondants.

Exemple local

Voyons d’abord comment cela fonctionne lors de l’exécution d’applications localement. Prenons l'application comme exemple Réagir des articles précédents, bien que presque les mêmes concepts de flux de travail s'appliquent dans tous les autres frameworks modernes.
Ainsi, pour démarrer le « serveur dev » dans notre exemple React, nous entrerons la commande suivante :

$ npm run start

Ensuite, dans la fenêtre du terminal, nous verrons quelque chose comme ceci :

Applications modernes sur OpenShift, partie 3 : OpenShift en tant qu'environnement de développement et OpenShift Pipelines

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

Applications modernes sur OpenShift, partie 3 : OpenShift en tant qu'environnement de développement et OpenShift Pipelines

Désormais, si nous apportons des modifications au fichier, l'application devrait se mettre à jour dans le navigateur.

OK, tout est clair avec le développement en mode local, mais comment faire la même chose sur OpenShift ?

Serveur de développement sur OpenShift

Si vous vous souvenez, dans post précédent, nous avons examiné la phase dite d'exécution de l'image S2I et avons vu que par défaut, le module serve est responsable de la maintenance de notre application Web.

Cependant, si l'on y regarde de plus près script de lancement à partir de cet exemple, il contient la variable d'environnement $NPM_RUN, qui vous permet d'exécuter votre 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 ressemblera à ceci :

Applications modernes sur OpenShift, partie 3 : OpenShift en tant qu'environnement de développement et OpenShift Pipelines

Bien sûr, tout cela ne sera rien tant que nous ne pourrons pas synchroniser le code local avec le code, qui est également surveillé pour les modifications, mais réside sur un serveur distant.

Synchronisation du code distant et local

Heureusement, nodeshift peut facilement faciliter 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 de notre système local commenceront à être surveillés pour détecter les modifications.

Par conséquent, si nous mettons maintenant à jour le fichier src/App.js, le système réagira à ces modifications, les copiera sur le cluster distant et démarrera le serveur de développement, qui mettra ensuite à jour notre application dans le navigateur.

Pour compléter le tableau, montrons à quoi ressemblent l’ensemble de ces commandes :

$ 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 savoir plus sur son fonctionnement ici.

C'était un exemple pour React, mais exactement la même méthode peut être utilisée avec d'autres frameworks, définissez simplement la variable d'environnement NPM_RUN si nécessaire.

Pipelines Openshift

Applications modernes sur OpenShift, partie 3 : OpenShift en tant qu'environnement de développement et OpenShift Pipelines

Nous parlerons ensuite d'un outil comme OpenShift Pipelines et de la manière dont il peut être utilisé comme alternative aux builds chaînés.

Que sont les pipelines OpenShift

OpenShift Pipelines est un système d'intégration et de livraison continue CI/CD natif cloud conçu pour organiser les pipelines à l'aide de Tekton. Tekton est un framework CI/CD open source flexible natif de Kubernetes qui vous permet d'automatiser le déploiement sur diverses plates-formes (Kubernetes, sans serveur, machines virtuelles, etc.) en faisant abstraction de la couche sous-jacente.

Comprendre cet article nécessite une certaine connaissance des pipelines, nous vous recommandons donc fortement de lire d'abord manuel officiel.

Mise en place de votre environnement de travail

Pour jouer avec les exemples de cet article, vous devez d’abord préparer votre environnement de travail :

  1. Installez et configurez un cluster OpenShift 4. Nos exemples utilisent pour cela CodeReady Containers (CRD), dont les instructions d'installation peuvent être trouvées ici.
  2. Une fois le cluster prêt, vous devez y installer Pipeline Operator. N'ayez pas peur, c'est simple, notice d'installation ici.
  3. Télécharger CLI Tekton (je sais) ici.
  4. Exécutez l'outil de ligne de commande create-react-app pour créer une application que vous déploierez ensuite (il s'agit d'une application simple Réagir).
  5. (Facultatif) Clonez le référentiel pour exécuter l'exemple d'application localement avec npm install puis npm start.

Le référentiel d'applications aura également un dossier k8s, qui contiendra les YAML Kubernetes/OpenShift utilisés pour déployer l'application. Il y aura des tâches, des ClusterTasks, des ressources et des pipelines que nous créerons dans ce référentiels.

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

Ce nom de projet apparaîtra plus tard dans le code, donc si vous décidez de le nommer autrement, n'oubliez pas de modifier l'exemple de code en conséquence. À partir de ce point, nous n'agirons pas de haut en bas, mais de bas en haut : c'est-à-dire que nous créerons d'abord tous les composants du convoyeur, et ensuite seulement le convoyeur lui-même.

Alors, tout d'abord...

Tâches

Créons quelques tâches, qui aideront ensuite à déployer l'application dans notre pipeline. La première tâche - apply_manifests_task - est responsable de l'application du YAML de ces 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 très clair. En fait, ces tâches sont en quelque sorte des utilitaires, et nous les examinerons plus en détail un peu plus tard. Pour l'instant, créons-les :

$ 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, nous vérifierons que les tâches ont bien été créées :

$ tkn task ls

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

Remarque : Il s'agit de tâches locales pour votre projet actuel.

Tâches de cluster

Les tâches de cluster sont fondamentalement les mêmes que les tâches simples. Autrement dit, il s’agit d’un ensemble réutilisable d’étapes 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 disponible partout dans le cluster. Pour voir la liste des tâches de cluster automatiquement créées lors de l'ajout de Pipeline Operator, nous utiliserons à nouveau la commande 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

Créons maintenant deux tâches de cluster. Le premier générera l’image S2I et l’enverra au registre interne OpenShift ; la seconde consiste à construire notre image basée sur NGINX, en utilisant l'application que nous avons déjà construite 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 nous nous sommes retrouvés avec une image stockée dans le registre interne d'OpenShift. Nous allons maintenant utiliser cette image d'application Web S2I pour créer un DockerFile pour notre application, puis utiliser Buildah pour effectuer la construction proprement dite et transférer l'image résultante vers le registre interne d'OpenShift, car c'est exactement ce que fait OpenShift lorsque vous déployez vos applications à l'aide de NodeShift. .

Comment savons-nous tout cela, demandez-vous ? Depuis version officielle de Node.js officiel, nous l'avons simplement copié et modifié pour nous-mêmes.

Alors, créons 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'analyserons pas cela en détail, mais nous concentrerons uniquement 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 égal à build, c'est là que React place le contenu assemblé. D'autres frameworks utilisent des chemins différents, par exemple, dans Ember, il s'agit de dist. Le résultat 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 créer pour nous une image basée sur NGINX, en utilisant le contenu de l'application que nous avons déjà créée. Il s’agit essentiellement de la partie de la section précédente dans laquelle nous avons examiné les builds chaînés.

Pour ce faire, nous allons - exactement comme juste ci-dessus - créer une tâche 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 qu'il ne spécifie pas le référentiel Git avec lequel nous travaillons ni les noms des images que nous créons. Nous spécifions uniquement ce que nous transférons exactement vers Git, ou une certaine image où l'image finale doit être sortie. 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, comme nous venons de le dire, les tâches du cluster doivent être les plus générales possibles, nous devons créer des ressources qui seront utilisées en entrée (le dépôt Git) et en sortie (les 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 spécifie la branche principale (ceci est facultatif, mais nous l'écrivons par souci d'exhaustivité).

Nous devons maintenant créer une ressource pour l'image où les résultats de la tâche s2i-web-app seront enregistrés, cela 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 d'images OpenShift interne, en particulier celui situé dans 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 aurons 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 d'un coup, nous utilisons 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 de convoyeur

Maintenant que nous avons tous les composants nécessaires, assemblons 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, examinons ces composants. Le premier est le nom :

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

Ensuite, dans la section des spécifications, 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

Nous créons ensuite les tâches que notre pipeline doit accomplir. 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 des 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 pour 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, sauf qu'ici la tâche de cluster webapp-build-runtime que nous avons 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 une ressource, mais il s'agit désormais d'une image d'application Web construite (la sortie de notre tâche précédente). Et en guise de sortie, nous définissons à nouveau l'image. Puisque cette tâche doit être exécutée après la précédente, on ajoute 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'utiliser les fichiers YAML de service, de route et de déploiement qui se trouvent 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 avons défini ces deux tâches de cluster au début de l'article.

Démarrage du convoyeur

Ainsi, toutes les parties de notre pipeline sont créées et nous allons l'exécuter 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 web-application-repo, puis pour la première ressource image, build-web-application -image, et enfin, pour la deuxième ressource d'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

Vérifions maintenant l'état du pipeline à l'aide de la commande suivante :

$ tkn pipeline logs -f

Une fois le pipeline démarré et l'application déployée, nous pouvons demander la route publiée avec la commande suivante :

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

Pour une meilleure visualisation, vous pouvez visualiser notre pipeline en mode Développeur de la console web dans la section Pipelines, comme le montre la fig. 1.

Applications modernes sur OpenShift, partie 3 : OpenShift en tant qu'environnement de développement et OpenShift Pipelines

Fig. 1. Examen des pipelines en cours d'exécution.

Cliquer sur un pipeline en cours d'exécution affiche des détails supplémentaires, comme le montre la figure 2.

Applications modernes sur OpenShift, partie 3 : OpenShift en tant qu'environnement de développement et OpenShift Pipelines

Riz. 2. Informations supplémentaires sur le pipeline.

Après plus d'informations, vous pouvez voir les applications en cours d'exécution dans la vue topologie, comme le montre la figure 3.

Applications modernes sur OpenShift, partie 3 : OpenShift en tant qu'environnement de développement et OpenShift Pipelines

Fig 3. Pod lancé.

En cliquant sur le cercle dans le coin supérieur droit de l'icône, notre application s'ouvre, comme le montre la Fig. 4.

Applications modernes sur OpenShift, partie 3 : OpenShift en tant qu'environnement de développement et OpenShift Pipelines

Riz. 4. Exécution 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 simuler un 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)

Annonces des prochains webinaires

Nous lançons une série de webinaires du vendredi sur l'expérience native utilisant Red Hat OpenShift Container Platform et Kubernetes :

Source: habr.com

Ajouter un commentaire