Applications modernes sur OpenShift, partie 2 : builds chaînés

Salut tout le monde! Il s'agit du deuxième article de notre série dans lequel nous montrons comment déployer des applications Web modernes sur Red Hat OpenShift.

Applications modernes sur OpenShift, partie 2 : builds chaînés

Dans l'article précédent, nous avons légèrement évoqué les capacités de la nouvelle image de création S2I (source-to-image), conçue pour créer et déployer des applications Web modernes sur la plate-forme OpenShift. Ensuite, nous nous sommes intéressés au sujet du déploiement rapide d'une application, et aujourd'hui nous verrons comment utiliser une image S2I comme image de constructeur « pure » et la combiner avec les assemblys OpenShift associés.

Image de constructeur propre

Comme nous l'avons mentionné dans la première partie, la plupart des applications Web modernes ont ce qu'on appelle une étape de construction, qui effectue généralement des opérations telles que la transpilation de code, la concaténation de plusieurs fichiers et la minification. Les fichiers obtenus à la suite de ces opérations - et il s'agit de HTML, JavaScript et CSS statiques - sont stockés dans le dossier de sortie. L'emplacement de ce dossier dépend généralement des outils de build utilisés, et pour React, ce sera le dossier ./build (nous y reviendrons plus en détail ci-dessous).

Source vers image (S2I)

Dans cet article, nous n'abordons pas le sujet « qu'est-ce que S2I et comment l'utiliser » (vous pouvez en savoir plus à ce sujet ici), mais il est important d'être clair sur les deux étapes de ce processus pour comprendre ce que fait une image Web App Builder.

Phase d'assemblage

La phase d'assemblage est de nature très similaire à ce qui se passe lorsque vous exécutez Docker build et que vous obtenez une nouvelle image Docker. En conséquence, cette étape se produit lors du démarrage d'une build sur la plateforme OpenShift.

Dans le cas d'une image Web App Builder, il est responsable de l'installation des dépendances de votre application et de l'exécution du build. assembler le script. Par défaut, l'image du générateur utilise la construction npm run build, mais celle-ci peut être remplacée via la variable d'environnement NPM_BUILD.

Comme nous l'avons dit plus tôt, l'emplacement de l'application terminée et déjà construite dépend des outils que vous utilisez. Par exemple, dans le cas de React, ce sera le dossier ./build, et pour les applications Angular, ce sera le dossier project_name/dist. Et, comme déjà montré dans l'article précédent, l'emplacement du répertoire de sortie, qui est défini sur build par défaut, peut être remplacé via la variable d'environnement OUTPUT_DIR. Eh bien, puisque l'emplacement du dossier de sortie diffère d'un framework à l'autre, vous copiez simplement la sortie générée dans le dossier standard de l'image, à savoir /opt/apt-root/output. Ceci est important pour comprendre le reste de cet article, mais pour l'instant, examinons rapidement l'étape suivante : la phase d'exécution.

phase d'exécution

Cette étape se produit lorsqu'un appel à docker run est effectué sur la nouvelle image créée lors de la phase d'assemblage. La même chose se produit lors du déploiement sur la plateforme OpenShift. Défaut script de lancement utilise module de service pour diffuser du contenu statique situé dans le répertoire de sortie standard ci-dessus.

Cette méthode convient au déploiement rapide d'applications, mais il n'est généralement pas recommandé de diffuser du contenu statique de cette manière. Eh bien, puisqu'en réalité nous ne servons que du contenu statique, nous n'avons pas besoin d'installer Node.js dans notre image - un serveur Web suffira.

En d’autres termes, lors de l’assemblage, nous avons besoin d’une chose, lors de l’exécution, nous en avons besoin d’une autre. Dans cette situation, les builds chaînés sont utiles.

Constructions enchaînées

C'est ce qu'ils écrivent constructions enchaînées dans la documentation OpenShift :

"Deux assemblys peuvent être liés entre eux, l'un générant une entité compilée et l'autre hébergeant cette entité dans une image distincte utilisée pour exécuter cette entité."

En d'autres termes, nous pouvons utiliser l'image Web App Builder pour exécuter notre build, puis utiliser l'image du serveur Web, le même NGINX, pour diffuser notre contenu.

Ainsi, nous pouvons utiliser l'image Web App Builder comme un constructeur « pur » et en même temps disposer d'une petite image d'exécution.

Voyons maintenant cela avec un exemple spécifique.

Pour la formation, nous utiliserons application React simple, créé à l'aide de l'outil de ligne de commande create-react-app.

Cela nous aidera à tout mettre en place Fichier de modèle OpenShift.

Examinons ce fichier plus en détail et commençons par la section des paramètres.

parameters:
  - name: SOURCE_REPOSITORY_URL
    description: The source URL for the application
    displayName: Source URL
    required: true
  - name: SOURCE_REPOSITORY_REF
    description: The branch name for the application
    displayName: Source Branch
    value: master
    required: true
  - name: SOURCE_REPOSITORY_DIR
    description: The location within the source repo of the application
    displayName: Source Directory
    value: .
    required: true
  - name: OUTPUT_DIR
    description: The location of the compiled static files from your web apps builder
    displayName: Output Directory
    value: build
    required: false

Tout ici est assez clair, mais il convient de prêter attention au paramètre OUTPUT_DIR. Pour l'application React dans notre exemple, il n'y a pas de quoi s'inquiéter, puisque React utilise la valeur par défaut comme dossier de sortie, mais dans le cas d'Angular ou autre, ce paramètre devra être modifié si nécessaire.

Jetons maintenant un œil à la section ImageStreams.

- apiVersion: v1
  kind: ImageStream
  metadata:
    name: react-web-app-builder  // 1 
  spec: {}
- apiVersion: v1
  kind: ImageStream
  metadata:
    name: react-web-app-runtime  // 2 
  spec: {}
- apiVersion: v1
  kind: ImageStream
  metadata:
    name: web-app-builder-runtime // 3
  spec:
    tags:
    - name: latest
      from:
        kind: DockerImage
        name: nodeshift/ubi8-s2i-web-app:10.x
- apiVersion: v1
  kind: ImageStream
  metadata:
    name: nginx-image-runtime // 4
  spec:
    tags:
    - name: latest
      from:
        kind: DockerImage
        name: 'centos/nginx-112-centos7:latest'

Jetez un œil aux troisième et quatrième images. Elles sont toutes deux définies comme des images Docker et vous pouvez clairement voir d'où elles viennent.

La troisième image est web-app-builder et provient de nodeshift/ubi8-s2i-web-app étiqueté 10.x sur Hub Docker.

La quatrième est une image NGINX (version 1.12) avec la dernière balise sur Hub Docker.

Regardons maintenant les deux premières images. Ils sont tous deux vides au démarrage et ne sont créés que pendant la phase de construction. La première image, React-web-app-builder, sera le résultat d'une étape d'assemblage qui combinera l'image web-app-builder-runtime et notre code source. C'est pourquoi nous avons ajouté « -builder » au nom de cette image.

La deuxième image - React-web-app-runtime - sera le résultat de la combinaison de nginx-image-runtime et de certains fichiers de l'image React-Web-App-Builder. Cette image sera également utilisée lors du déploiement et contiendra uniquement le serveur web et le HTML, JavaScript, CSS statiques de notre application.

Confus? Jetons maintenant un coup d'œil aux configurations de build et cela deviendra un peu plus clair.

Notre modèle a deux configurations de construction. Voici le premier, et il est assez standard :

  apiVersion: v1
  kind: BuildConfig
  metadata:
    name: react-web-app-builder
  spec:
    output:
      to:
        kind: ImageStreamTag
        name: react-web-app-builder:latest // 1
    source:   // 2 
      git:
        uri: ${SOURCE_REPOSITORY_URL}
        ref: ${SOURCE_REPOSITORY_REF}
      contextDir: ${SOURCE_REPOSITORY_DIR}
      type: Git
    strategy:
      sourceStrategy:
        env:
          - name: OUTPUT_DIR // 3 
            value: ${OUTPUT_DIR}
        from:
          kind: ImageStreamTag
          name: web-app-builder-runtime:latest // 4
        incremental: true // 5
      type: Source
    triggers: // 6
    - github:
        secret: ${GITHUB_WEBHOOK_SECRET}
      type: GitHub
    - type: ConfigChange
    - imageChange: {}
      type: ImageChange

Comme vous pouvez le voir, la ligne avec l'étiquette 1 indique que le résultat de cette construction sera placé dans la même image React-Web-App-Builder que nous avons vue un peu plus tôt dans la section ImageStreams.

La ligne étiquetée 2 vous indique d'où obtenir le code. Dans notre cas, il s'agit d'un référentiel git, et l'emplacement, la référence et le dossier contextuel sont déterminés par les paramètres que nous avons déjà vus ci-dessus.

La ligne étiquetée 3 est ce que nous avons déjà vu dans la section paramètres. Il ajoute la variable d'environnement OUTPUT_DIR, qui dans notre exemple est build.
La ligne intitulée 4 indique d'utiliser l'image d'exécution web-app-builder-runtime, que nous avons déjà vue dans la section ImageStream.

La ligne étiquetée 5 indique que nous souhaitons utiliser une construction incrémentielle si l'image S2I la prend en charge, et l'image Web App Builder le fait. Au premier lancement, une fois la phase d'assemblage terminée, l'image enregistrera le dossier node_modules dans un fichier d'archive. Ensuite, lors des exécutions suivantes, l'image décompressera simplement ce dossier pour réduire le temps de construction.

Et enfin, la ligne intitulée 6 ne contient que quelques déclencheurs pour que la construction s'exécute automatiquement, sans intervention manuelle, lorsque quelque chose change.

Dans l’ensemble, il s’agit d’une configuration de construction assez standard.

Jetons maintenant un coup d'œil à la deuxième configuration de build. Il est très similaire au premier, mais il y a une différence importante.

apiVersion: v1
  kind: BuildConfig
  metadata:
    name: react-web-app-runtime
  spec:
    output:
      to:
        kind: ImageStreamTag
        name: react-web-app-runtime:latest // 1
    source: // 2
      type: Image
      images:                              
        - from:
            kind: ImageStreamTag
            name: react-web-app-builder:latest // 3
          paths:
            - sourcePath: /opt/app-root/output/.  // 4
              destinationDir: .  // 5
             
    strategy: // 6
      sourceStrategy:
        from:
          kind: ImageStreamTag
          name: nginx-image-runtime:latest
        incremental: true
      type: Source
    triggers:
    - github:
        secret: ${GITHUB_WEBHOOK_SECRET}
      type: GitHub
    - type: ConfigChange
    - type: ImageChange
      imageChange: {}
    - type: ImageChange
      imageChange:
        from:
          kind: ImageStreamTag
          name: react-web-app-builder:latest // 7

Ainsi, la deuxième configuration de build est React-Web-App-Runtime, et elle commence assez standard.

La ligne intitulée 1 n'a rien de nouveau - elle indique simplement que le résultat de la construction est placé dans l'image d'exécution de l'application Web React.

La ligne étiquetée 2, comme dans la configuration précédente, indique d'où récupérer le code source. Mais remarquez qu’ici nous disons qu’il est tiré de l’image. De plus, à partir de l'image que nous venons de créer - de React-Web-App-Builder (indiquée dans la ligne intitulée 3). Les fichiers que nous voulons utiliser se trouvent à l'intérieur de l'image et leur emplacement est défini sur la ligne étiquetée 4, dans notre cas, il s'agit de /opt/app-root/output/. Si vous vous en souvenez, c'est ici que sont stockés les fichiers générés sur la base des résultats de la construction de notre application.

Le dossier de destination spécifié dans le terme portant l'étiquette 5 est simplement le répertoire actuel (rappelez-vous que tout cela s'exécute dans une chose magique appelée OpenShift, et non sur votre ordinateur local).

La section stratégie – ligne intitulée 6 – est également similaire à la première configuration de build. Seulement cette fois, nous allons utiliser nginx-image-runtime, que nous avons déjà vu dans la section ImageStream.

Enfin, la ligne intitulée 7 est une section de déclencheurs qui activeront cette version à chaque fois que l'image de réaction-web-app-builder change.

Sinon, ce modèle contient une configuration de déploiement assez standard, ainsi que des éléments liés aux services et aux routes, mais nous n'entrerons pas dans les détails. Veuillez noter que l'image qui sera déployée est l'image React-Web-App-Runtime.

Déploiement d'applications

Maintenant que nous avons examiné le modèle, voyons comment l'utiliser pour déployer une application.

Nous pouvons utiliser l'outil client OpenShift appelé oc pour déployer notre modèle :

$ find . | grep openshiftio | grep application | xargs -n 1 oc apply -f

$ oc new-app --template react-web-app -p SOURCE_REPOSITORY_URL=https://github.com/lholmquist/react-web-app

La première commande dans la capture d'écran ci-dessus est un moyen délibérément technique de trouver un modèle./openshiftio/application.yaml.

La deuxième commande crée simplement une nouvelle application basée sur ce modèle.

Une fois ces commandes exécutées, nous verrons que nous avons deux assemblys :

Applications modernes sur OpenShift, partie 2 : builds chaînés

Et en revenant à l'écran Présentation, nous verrons le pod lancé :

Applications modernes sur OpenShift, partie 2 : builds chaînés

Cliquez sur le lien et nous serons redirigés vers notre application, qui est la page par défaut de l'application React :

Applications modernes sur OpenShift, partie 2 : builds chaînés

1 add-on

Pour les amateurs d'Angular, nous avons également exemple d'application.

Le modèle ici est le même, à l'exception de la variable OUTPUT_DIR.

2 add-on

Dans cet article nous avons utilisé NGINX comme serveur web, mais il est assez simple de le remplacer par Apache, il suffit de changer le modèle dans le fichier Image NGINX sur Image Apache.

Conclusion

Dans la première partie de cette série, nous avons montré comment déployer rapidement des applications Web modernes sur la plateforme OpenShift. Aujourd'hui, nous avons examiné ce que fait une image d'application Web et comment elle peut être combinée avec un serveur Web pur comme NGINX en utilisant des versions chaînées pour créer une version d'application plus prête pour la production. Dans le prochain et dernier article de cette série, nous montrerons comment exécuter un serveur de développement pour votre application sur OpenShift et assurer la synchronisation des fichiers locaux et distants.

Contenu de cette série d'articles

  • Partie 1: comment déployer des applications Web modernes en quelques étapes seulement;
  • Partie 2 : Comment utiliser une nouvelle image S2I avec une image de serveur HTTP existante, telle que NGINX, en utilisant les assemblys OpenShift associés pour le déploiement en production ;
  • Partie 3 : comment exécuter un serveur de développement pour votre application sur la plateforme OpenShift et le synchroniser avec le système de fichiers local.

Ressources additionnelles

Source: habr.com

Ajouter un commentaire