Moderne applicaties op OpenShift, deel 2: geketende builds

Dag Allemaal! Dit is de tweede post in onze serie waarin we laten zien hoe je moderne webapplicaties kunt inzetten op Red Hat OpenShift.

Moderne applicaties op OpenShift, deel 2: geketende builds

In het vorige bericht hebben we de mogelijkheden van de nieuwe S2I (source-to-image) builder-image enigszins aangeroerd, die is ontworpen voor het bouwen en implementeren van moderne webapplicaties op het OpenShift-platform. Toen waren we geïnteresseerd in het onderwerp van het snel implementeren van een applicatie, en vandaag zullen we bekijken hoe we een S2I-image kunnen gebruiken als een "puur" builder-image en deze kunnen combineren met gerelateerde OpenShift-assemblages.

Schoon bouwersimage

Zoals we in deel XNUMX hebben vermeld, hebben de meeste moderne webapplicaties een zogenaamde bouwfase, waarin doorgaans bewerkingen worden uitgevoerd zoals codetranspilatie, aaneenschakeling van meerdere bestanden en minificatie. De bestanden die als resultaat van deze bewerkingen worden verkregen (en dit zijn statische HTML, JavaScript en CSS) worden opgeslagen in de uitvoermap. De locatie van deze map hangt meestal af van welke bouwtools worden gebruikt, en voor React zal dit de map ./build zijn (we komen hier hieronder in meer detail op terug).

Bron-naar-afbeelding (S2I)

In dit bericht gaan we niet in op het onderwerp “wat is S2I en hoe gebruik je het” (hierover kun je meer lezen hier), maar het is belangrijk om duidelijk te zijn over de twee stappen in dit proces om te begrijpen wat een Web App Builder-image doet.

Montage fase

De assemblagefase lijkt qua aard sterk op wat er gebeurt als u docker build uitvoert en uiteindelijk een nieuwe Docker-image krijgt. Dienovereenkomstig vindt deze fase plaats bij het starten van een build op het OpenShift-platform.

In het geval van een Web App Builder-image is deze verantwoordelijk voor het installeren van de afhankelijkheden van uw applicatie en het uitvoeren van de build. script samenstellen. Standaard gebruikt de builderimage de npm run build-constructie, maar dit kan worden overschreven via de omgevingsvariabele NPM_BUILD.

Zoals we eerder zeiden, hangt de locatie van de voltooide, reeds gebouwde applicatie af van welke tools u gebruikt. In het geval van React is dit bijvoorbeeld de map ./build en voor Angular-toepassingen de map project_name/dist. En, zoals al in het vorige bericht is getoond, kan de locatie van de uitvoermap, die standaard is ingesteld op build, worden overschreven via de omgevingsvariabele OUTPUT_DIR. Omdat de locatie van de uitvoermap van raamwerk tot raamwerk verschilt, kopieert u eenvoudigweg de gegenereerde uitvoer naar de standaardmap in de afbeelding, namelijk /opt/apt-root/output. Dit is belangrijk voor het begrijpen van de rest van dit artikel, maar laten we nu snel naar de volgende fase kijken: de runfase.

fase uitvoeren

Deze fase vindt plaats wanneer een aanroep naar Docker Run wordt gedaan op de nieuwe image die tijdens de assemblagefase is gemaakt. Hetzelfde gebeurt bij implementatie op het OpenShift-platform. Standaard script uitvoeren toepassingen serveermodule om statische inhoud weer te geven die zich in de bovenstaande standaarduitvoermap bevindt.

Deze methode is goed voor het snel implementeren van applicaties, maar het wordt over het algemeen niet aanbevolen om statische inhoud op deze manier aan te bieden. Omdat we in werkelijkheid alleen statische inhoud aanbieden, hoeven we Node.js niet in onze image te installeren; een webserver is voldoende.

Met andere woorden: bij het assembleren hebben we het ene nodig, bij het uitvoeren hebben we iets anders nodig. In deze situatie komen geketende builds van pas.

Geketende constructies

Dit is waar ze over schrijven geketende constructies in de OpenShift-documentatie:

“Twee assemblages kunnen aan elkaar worden gekoppeld, waarbij de ene een gecompileerde entiteit genereert en de andere die entiteit host in een afzonderlijke afbeelding die wordt gebruikt om die entiteit uit te voeren.”

Met andere woorden, we kunnen de Web App Builder-image gebruiken om onze build uit te voeren en vervolgens de webserver-image, dezelfde NGINX, gebruiken om onze inhoud aan te bieden.

We kunnen dus de Web App Builder-image gebruiken als een “pure” builder en tegelijkertijd een kleine runtime-image hebben.

Laten we dit nu eens bekijken met een specifiek voorbeeld.

Voor training zullen we gebruiken eenvoudige React-applicatie, gemaakt met behulp van het opdrachtregelprogramma create-react-app.

Het zal ons helpen alles bij elkaar te brengen OpenShift-sjabloonbestand.

Laten we dit bestand in meer detail bekijken en beginnen met de parametersectie.

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

Alles is hier vrij duidelijk, maar het is de moeite waard om aandacht te besteden aan de parameter OUTPUT_DIR. Voor de React-toepassing in ons voorbeeld hoeft u zich nergens zorgen over te maken, aangezien React de standaardwaarde als uitvoermap gebruikt, maar in het geval van Angular of iets anders moet deze parameter indien nodig worden gewijzigd.

Laten we nu eens kijken naar de ImageStreams-sectie.

- 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'

Kijk eens naar de derde en vierde afbeelding. Ze zijn beide gedefinieerd als Docker-afbeeldingen en je kunt duidelijk zien waar ze vandaan komen.

De derde afbeelding is web-app-builder en komt van nodeshift/ubi8-s2i-web-app met de tag 10.x op Docker-hub.

De vierde is een NGINX-image (versie 1.12) met de nieuwste tag ingeschakeld Docker-hub.

Laten we nu naar de eerste twee afbeeldingen kijken. Ze zijn allebei leeg bij het starten en worden alleen gemaakt tijdens de bouwfase. De eerste afbeelding, react-web-app-builder, zal het resultaat zijn van een assemblagestap die de web-app-builder-runtime-afbeelding en onze broncode combineert. Daarom hebben we “-builder” toegevoegd aan de naam van deze afbeelding.

De tweede afbeelding - react-web-app-runtime - zal het resultaat zijn van het combineren van nginx-image-runtime en enkele bestanden uit de react-web-app-builder-image. Deze afbeelding wordt ook gebruikt tijdens de implementatie en bevat alleen de webserver en statische HTML, JavaScript, CSS van onze applicatie.

Verward? Laten we nu eens kijken naar de build-configuraties en het zal een beetje duidelijker worden.

Onze sjabloon heeft twee build-configuraties. Hier is de eerste, en die is vrij standaard:

  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

Zoals je kunt zien, zegt de regel met label 1 dat het resultaat van deze build in dezelfde react-web-app-builder-afbeelding zal worden geplaatst die we iets eerder in de ImageStreams-sectie zagen.

De regel met het label 2 vertelt u waar u de code vandaan kunt halen. In ons geval is dit een git-repository, en de locatie, ref en contextmap worden bepaald door de parameters die we hierboven al zagen.

De regel met het label 3 is wat we al zagen in de parametersectie. Het voegt de omgevingsvariabele OUTPUT_DIR toe, die in ons voorbeeld build is.
De regel met het label 4 zegt dat we de web-app-builder-runtime-image moeten gebruiken, die we al in de ImageStream-sectie hebben gezien.

Regel 5 zegt dat we een incrementele build willen gebruiken als de S2I-image dit ondersteunt, en de Web App Builder-image doet dat ook. Bij de eerste keer opstarten, na voltooiing van de montagefase, slaat de afbeelding de map node_modules op in een archiefbestand. Vervolgens zal de afbeelding bij volgende uitvoeringen deze map eenvoudigweg uitpakken om de bouwtijd te verkorten.

En ten slotte is de regel met het label 6 slechts een paar triggers om de build automatisch te laten draaien, zonder handmatige tussenkomst, wanneer er iets verandert.

Over het algemeen is dit een vrij standaard bouwconfiguratie.

Laten we nu eens kijken naar de tweede buildconfiguratie. Het lijkt erg op de eerste, maar er is één belangrijk verschil.

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

De tweede build-configuratie is dus react-web-app-runtime, en deze begint vrij standaard.

De regel met het label 1 is niets nieuws - er staat eenvoudigweg dat het buildresultaat in de react-web-app-runtime-image wordt geplaatst.

De regel met het label 2 geeft, net als in de vorige configuratie, aan waar de broncode vandaan moet komen. Maar merk op dat we hier zeggen dat het uit de afbeelding is gehaald. Bovendien uit de afbeelding die we zojuist hebben gemaakt - van react-web-app-builder (aangegeven in regel met het label 3). De bestanden die we willen gebruiken bevinden zich in de afbeelding en hun locatie is ingesteld in regel met het label 4, in ons geval is dit /opt/app-root/output/. Als u het zich herinnert, worden hier de bestanden opgeslagen die zijn gegenereerd op basis van de resultaten van het bouwen van onze applicatie.

De bestemmingsmap die is opgegeven in de term met label 5 is eenvoudigweg de huidige map (dit is allemaal, onthoud, het draait in een magisch ding genaamd OpenShift, en niet op uw lokale computer).

Het strategiegedeelte – regel met het label 6 – is ook vergelijkbaar met de eerste build-configuratie. Alleen deze keer gaan we nginx-image-runtime gebruiken, wat we al zagen in de ImageStream-sectie.

Ten slotte is de regel met het label 7 een sectie met triggers die deze build activeren telkens wanneer de afbeelding van de react-web-app-builder verandert.

Verder bevat deze sjabloon een vrij standaard implementatieconfiguratie, evenals zaken die betrekking hebben op services en routes, maar daar zullen we niet te veel op ingaan. Houd er rekening mee dat de afbeelding die wordt geïmplementeerd de react-web-app-runtime-afbeelding is.

Applicatie-implementatie

Nu we de sjabloon hebben bekeken, gaan we kijken hoe we deze kunnen gebruiken om een ​​applicatie te implementeren.

We kunnen de OpenShift-clienttool genaamd oc gebruiken om onze sjabloon te implementeren:

$ 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

Het eerste commando in de bovenstaande schermafbeelding is een opzettelijk technische manier om een ​​template./openshiftio/application.yaml te vinden.

Met het tweede commando wordt eenvoudigweg een nieuwe applicatie gemaakt op basis van deze sjabloon.

Nadat deze commando's werken, zullen we zien dat we twee samenstellingen hebben:

Moderne applicaties op OpenShift, deel 2: geketende builds

En als we terugkeren naar het overzichtsscherm, zien we de gelanceerde pod:

Moderne applicaties op OpenShift, deel 2: geketende builds

Klik op de link en we worden naar onze app geleid, de standaard React App-pagina:

Moderne applicaties op OpenShift, deel 2: geketende builds

Aanvulling 1

Voor Angular-liefhebbers hebben we ook voorbeeld toepassing.

Het patroon is hier hetzelfde, behalve de variabele OUTPUT_DIR.

Aanvulling 2

In dit artikel gebruikten we NGINX als webserver, maar het is vrij eenvoudig om het te vervangen door Apache, verander gewoon de sjabloon in het bestand NGINX-afbeelding op Apache-afbeelding.

Conclusie

In het eerste deel van deze serie lieten we zien hoe je snel moderne webapplicaties kunt implementeren op het OpenShift-platform. Vandaag hebben we gekeken naar wat een webapp-image doet en hoe deze kan worden gecombineerd met een pure webserver zoals NGINX met behulp van geketende builds om een ​​meer productieklare applicatie-build te creëren. In het volgende en laatste artikel in deze serie laten we zien hoe u een ontwikkelserver voor uw applicatie op OpenShift kunt draaien en hoe u de synchronisatie van lokale en externe bestanden kunt garanderen.

Inhoud van deze serie artikelen

  • Deel 1: hoe u in slechts een paar stappen moderne webapplicaties kunt implementeren;
  • Deel 2: Hoe u een nieuwe S2I-image gebruikt met een bestaande HTTP-serverimage, zoals NGINX, met behulp van bijbehorende OpenShift-assemblies voor productie-implementatie;
  • Deel 3: hoe u een ontwikkelserver voor uw applicatie op het OpenShift-platform kunt draaien en deze kunt synchroniseren met het lokale bestandssysteem.

Aanvullende bronnen

Bron: www.habr.com

Voeg een reactie