Aplicații moderne în OpenShift, partea 3: OpenShift ca mediu de dezvoltare și canale OpenShift Pipelines

Salut tuturor pe acest blog! Asta este a treia postare dintr-o serie în care arătăm cum să implementăm aplicații web moderne pe Red Hat OpenShift.

Aplicații moderne în OpenShift, partea 3: OpenShift ca mediu de dezvoltare și canale OpenShift Pipelines

În ultimele două postări, am explicat cum să implementăm aplicații web moderne în doar câteva etape și cum să folosim o nouă imagine S2I împreună cu o imagine de server HTTP pregătită, cum ar fi NGINX, cu ajutorul construcțiilor legate pentru a organiza implementări în producție.

Astăzi vom arăta cum să lansăm pe platforma OpenShift un server de dezvoltare pentru aplicația noastră și să-l sincronizăm cu sistemul de fișiere local, precum și să vorbim despre ce sunt OpenShift Pipelines și cum pot fi utilizate ca alternativă la construcțiile legate.

OpenShift ca mediu de dezvoltare

Flux de lucru de dezvoltare

După cum s-a menționat în prima postare, procesul tipic de dezvoltare pentru aplicațiile web moderne este simplu un "server de dezvoltare" care monitorizează modificările din fișierele locale. Când acestea au loc, se declanșează o construcție a aplicației, care este apoi actualizată în browser.

În majoritatea cadrelor moderne, un astfel de "server de dezvoltare" este integrat în instrumentele corespunzătoare de linie de comandă.

Exemplu local

Începem prin a vedea cum funcționează în cazul unui launch local al aplicațiilor. Ca exemplu, vom lua aplicația React din articolele anterioare, deși practic aceleași concepte de lucru se aplică și în alte cadre moderne.
Așadar, pentru a lansa "serverul de dezvoltare" în exemplul nostru cu React, vom introduce următoarea comandă:

$ npm run start

Atunci, în fereastra terminalului, vom vedea aproximativ următoarele:

Aplicații moderne în OpenShift, partea 3: OpenShift ca mediu de dezvoltare și canale OpenShift Pipelines

Și aplicația noastră se va deschide în browserul implicit:

Aplicații moderne în OpenShift, partea 3: OpenShift ca mediu de dezvoltare și canale OpenShift Pipelines

Acum, dacă facem modificări în fișier, aplicația ar trebui să se actualizeze în browser.

OK, cu dezvoltarea în modul local totul este clar, dar cum obținem același lucru pe OpenShift?

Server de dezvoltare pe OpenShift

Dacă vă amintiți, în postarea anterioară, am analizat așa numita etapă de lansare a imaginii S2I și am văzut că, în mod implicit, întreținerea aplicației noastre web este realizată de modulul serve.

Cu toate acestea, dacă ne uităm mai atent scriptul de execuție din acel exemplu, există o variabilă de mediu $NPM_RUN care permite să executăm comanda noastră.

De exemplu, putem folosi modulul nodeshift pentru a desfășura aplicația noastră:

$ npx nodeshift --deploy.env NPM_RUN="yarn start" --dockerImage=nodeshift/ubi8-s2i-web-app

Notă: exemplul de mai sus este prezentat într-o formă scurtă pentru a ilustra ideea generală.

Aici am adăugat în desfășurarea noastră variabila de mediu NPM_RUN, care îi spune etapelor de execuție să ruleze comanda yarn start, care pornește serverul de dezvoltare React în interiorul pod-ului nostru OpenShift.

Dacă ne uităm în log-ul pod-ului care rulează, acesta va arăta aproximativ așa:

Aplicații moderne în OpenShift, partea 3: OpenShift ca mediu de dezvoltare și canale OpenShift Pipelines

Desigur, toate acestea nu vor conta până nu putem sincroniza codul local cu codul, care este, de asemenea, monitorizat pentru modificări, dar se află pe un server remote.

Sincronizarea codului remote și local

Din fericire, sincronizarea este simplificată de nodeshift, iar pentru a urmări modificările, putem folosi comanda watch.

Așa că, după ce am executat comanda pentru desfășurarea serverului de dezvoltare pentru aplicația noastră, putem să folosim cu încredere această comandă:

$ npx nodeshift watch

Ca rezultat, se va stabili o conexiune cu pod-ul care a fost creat anterior, se va activa sincronizarea fișierelor noastre locale cu cluster-ul remote, iar fișierele de pe sistemul nostru local vor începe să fie urmărite pentru modificări.

Așadar, dacă acum actualizăm fișierul src/App.js, sistemul va reacționa la aceste modificări, le va copia pe cluster-ul remote și va porni serverul de dezvoltare, care va actualiza apoi aplicația noastră în browser.

Pentru a completa imaginea, vom arăta cum apar aceste comenzi în întregime:

$ 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

Comanda watch este o abstracție deasupra comenzii oc rsync, poți afla mai multe despre cum funcționează. aici.

Acesta a fost un exemplu pentru React, dar aceeași metodă poate fi utilizată și cu alte framework-uri, doar specificați corespunzător variabila de mediu NPM_RUN.
 

Pipelines OpenShift

Aplicații moderne în OpenShift, partea 3: OpenShift ca mediu de dezvoltare și canale OpenShift Pipelines

Mai departe, vom discuta despre un instrument numit OpenShift Pipelines și despre cum poate fi folosit ca o alternativă la construcții legate de chaîne.

Ce sunt OpenShift Pipelines

OpenShift Pipelines este un sistem CI/CD orientat spre cloud pentru integrarea și livrarea continuă, destinat organizării de conducte utilizând Tekton. Tekton este un cadru CI/CD flexibil și nativ Kubernetes, cu sursă deschisă, care permite automatizarea desfășurării pe diverse platforme (Kubernetes, serverless, mașini virtuale etc.) prin abstractizarea nivelului de bază.

Pentru a înțelege acest articol, sunt necesare anumite cunoștințe despre Pipelines, așadar vă recomandăm cu tărie să începeți prin a citi manualul oficial.

Configurarea mediului de lucru

Pentru a experimenta cu exemplele din acest articol, trebuie mai întâi să pregătiți mediul de lucru:

  1. Instalați și configurați un cluster OpenShift 4. În exemplele noastre, folosim CodeReady Containers (CRD), instrucțiunile de instalare pot fi găsite aici.
  2. După ce clusterul este gata, trebuie să instalați Pipeline Operator. Nu vă faceți griji, este simplu, instrucțiunile de instalare aici.
  3. Descarcă Tekton CLI (tkn) aici.
  4. Rulați instrumentul de linie de comandă create-react-app pentru a crea o aplicație care va fi desfășurată ulterior (aceasta este o aplicație simplă React).
  5. (Opțional) Clonati repository-ul pentru a rula local exemplul aplicației cu comanda npm install și apoi npm start.

În repository-ul aplicației va exista, de asemenea, un folder k8s, unde vor fi stocate YAML-urile Kubernetes/OpenShift utilizate pentru desfășurarea aplicației. Acolo vor fi Tasks, ClusterTasks, Resources și Pipelines pe care le vom crea în acest repository.

Să începem

Mai întâi, pentru exemplul nostru, trebuie să creăm un nou proiect în clusterul OpenShift. Vom numi acest proiect webapp-pipeline și îl vom crea cu următoarea comandă:

$ oc new-project webapp-pipeline

Mai departe, acest nume de proiect va apărea în cod, așadar, dacă decideți să-l numiți altfel, nu uitați să modificați corespunzător codul din exemple. Începând de aici, vom proceda de jos în sus: mai întâi vom crea toate componentele conductei, iar apoi însăși conducta.

Așa că, mai întâi…

Tasks

Vom crea două sarcini (tasks) care ne vor ajuta ulterior să desfășurăm aplicația în cadrul pipeline-ului nostru. Prima sarcină – apply_manifests_task – se ocupă cu aplicarea YAML-urilor resurselor Kubernetes (service, deployment și route) care se află în folderul k8s al aplicației noastre. A doua sarcină – update_deployment_task – se ocupă cu actualizarea imaginii deja desfășurate la cea care este creată de pipeline-ul nostru.

Nu vă faceți griji dacă nu este foarte clar pentru moment. De fapt, aceste sarcini sunt ceva de genul utilitare și le vom examina în detaliu puțin mai târziu. Dar deocamdată să le creăm:

$ 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

Apoi, cu ajutorul comenzii tkn CLI, vom verifica dacă sarcinile au fost create:

$ tkn task ls

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

Notă: acestea sunt sarcini locale ale proiectului dumneavoastră curent.

Sarcini de cluster Cluster tasks

Sarcinile de cluster sunt, în esență, același lucru cu sarcinile obișnuite. Adică, sunt o colecție reutilizabilă de pași care sunt combinați într-un fel sau altul la desfășurarea unei sarcini specifice. Diferența este că sarcina de cluster este disponibilă oriunde în cadrul clusterului. Pentru a vedea lista sarcinilor de cluster care sunt create automat la adăugarea Operatorului Pipeline, vom folosi din nou comanda 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

Acum să creăm două sarcini de cluster. Prima va genera o imagine S2I și o va trimite în registrul intern OpenShift; a doua va construi imaginea noastră bazată pe NGINX, folosind ca și conținut aplicația pe care am construit-o anterior.

Creăm și trimitem imaginea

Când creăm prima sarcină, vom repeta ceea ce am făcut deja în articolul anterior despre construirea legată. Reamintim că am folosit imaginea S2I (ubi8-s2i-web-app) pentru a „construi” aplicația noastră, iar în cele din urmă am obținut o imagine stocată în registrul intern OpenShift. Acum vom folosi această imagine S2I a aplicației web pentru a crea un DockerFile pentru aplicația noastră, iar apoi vom folosi Buildah pentru a efectua construcția reală și a trimite imaginea obținută în registrul intern OpenShift, deoarece aceasta este ceea ce face OpenShift atunci când desfășurați aplicațiile folosind NodeShift.

Întrebați de unde am aflat toate acestea? Din официальной версии official Node.js, am copiat-o pur și simplu și am adaptat-o pentru nevoile noastre.

Așa că, să creăm acum sarcina cluster s2i-web-app:

$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/clustertasks/s2i-web-app-task.yaml

Nu vom detalia acest lucru, ci ne vom opri doar asupra parametrului OUTPUT_DIR:

params:
      - name: OUTPUT_DIR
        description: Locul directorului de ieșire al construcției
        default: build

În mod implicit, acest parametru este setat pe build, exact acolo unde React salvează conținutul construit. Alte cadre folosesc alte căi; de exemplu, în Ember este dist. Iesirea primei noastre sarcini de cluster va consta într-o imagine care conține HTML, JavaScript și CSS-urile construite de noi.

Construim o imagine pe bază de NGINX

În ceea ce privește a doua noastră sarcină de cluster, aceasta ar trebui să construiască o imagine bazată pe NGINX, folosind conținutul deja construit de noi. Practic, aceasta este partea din secțiunea anterioară în care am discutat despre construcțiile legate (chained builds).

Pentru aceasta, vom crea, exact ca mai sus, o sarcină de cluster webapp-build-runtime:

$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/clustertasks/webapp-build-runtime-task.yaml

Dacă observăm codul acestor sarcini de cluster, se poate observa că nu se specifică depozitul Git cu care lucrăm sau numele imaginilor pe care le creăm. Noi doar stabilim ce anume transmitem în Git sau o anumită imagine în care trebuie să ieșim cu imaginea finală. De aceea, aceste sarcini de cluster pot fi reutilizate și pentru alte aplicații.

Și aici trecem elegant la următorul punct...

Resurse

Așadar, deoarece, după cum am spus, sarcinile de cluster trebuie să fie cât mai generalizate, trebuie să creăm resurse care vor fi utilizate la intrare (repository Git) și la ieșire (imaginea finală). Prima resursă de care avem nevoie este Git, unde se află aplicația noastră, ceva de genul acesta:

# 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

Aici, PipelineResource are tipul git. Cheia url din secțiunea params indică spre repository-ul specific și stabilește ramura master (aceasta este opțională, dar o menționăm pentru completitudine).

Acum trebuie să creăm o resursă pentru imagine, unde vor fi salvate rezultatele execuției sarcinii s2i-web-app, acest lucru se face astfel:

# 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

Aici, PipelineResource are tipul image, iar valoarea parametrului url indică spre Registrul de Imagini OpenShift intern, mai exact cel care se află în spațiul de nume webapp-pipeline. Nu uitați să schimbați acest parametru dacă utilizați un alt spațiu de nume.

Și, în cele din urmă, ultima resursă de care vom avea nevoie va avea de asemenea tipul image și aceasta va fi imaginea finală NGINX, care va fi utilizată ulterior la desfășurare:

# 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

Rețineți din nou că această resursă salvează imaginea în registrul intern OpenShift din spațiul de nume webapp-pipeline.

Pentru a crea toate aceste resurse deodată, vom folosi comanda create:

$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/resources/resource.yaml

Pentru a verifica dacă resursele au fost create, se poate face astfel:

$ tkn resource ls

Conveyer pipeline

Acum, când avem toate componentele necesare, să construim conveyorul folosind următoarea comandă:

$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/pipelines/build-and-deploy-react.yaml

Dar, înainte de a rula această comandă, să detaliem aceste componente. Prima este numele:

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

Apoi, în secțiunea spec, vedem specificarea resurselor pe care le-am creat anterior:

spec:
  resources:
    - name: web-application-repo
      type: git
    - name: built-web-application-image
      type: image
    - name: runtime-web-application-image
      type: image

Apoi creăm sarcinile pe care trebuie să le execute conveyorul nostru. În primul rând, trebuie să efectueze sarcina s2i-web-app pe care am creat-o anterior:

tasks:
    - name: build-web-application
      taskRef:
        name: s2i-web-app
        kind: ClusterTask

Această sarcină preia parametrii de intrare (resursa gir) și ieșire (resursa built-web-application-image). De asemenea, îi transmitem un parametru special pentru a nu verifica TLS, deoarece folosim certificate auto-semnate:

resurse:
        intrări:
          - nume: sursă
            resursă: web-application-repo
        ieșiri:
          - nume: imagine
            resursă: built-web-application-image
      parametri:
        - nume: TLSVERIFY
          valoare: "false"

Următoarea sarcină este aproape identică, doar că aici se apelează sarcina cluster creată de noi webapp-build-runtime:

nume: build-runtime-image
    taskRef:
      nume: webapp-build-runtime
      tip: ClusterTask

La fel ca în sarcina anterioară, transmitem resursa, dar acum aceasta este built-web-application-image (ieșirea sarcinii noastre anterioare). Și ca ieșire, iarăși definim o imagine. Fiindcă această sarcină trebuie să fie executată după cea anterioară, adăugăm câmpul runAfter:

resurse:
        intrări:
          - nume: imagine
            resursă: built-web-application-image
        ieșiri:
          - nume: imagine
            resursă: runtime-web-application-image
        parametri:
        - nume: TLSVERIFY
          valoare: "false"
      runAfter:
        - build-web-application

Următoarele două sarcini se ocupă de aplicarea fișierelor YAML pentru serviciu, rută și desfășurare, care se află în directorul k8s al aplicației noastre web, precum și de actualizarea acestei desfășurări atunci când se creează imagini noi. Aceste două sarcini cluster le-am definit la începutul articolului.

Pornirea conductorului

Așadar, toate părțile conductei noastre sunt create și o vom porni cu următoarea comandă:

$ tkn pipeline start build-and-deploy-react

În această etapă, linia de comandă este utilizată în mod interactiv și trebuie să selectăm resursele corespunzătoare ca răspuns la fiecare solicitare: pentru resursa git alegem web-application-repo, apoi pentru resursa primei imagini – built-web-application-image, iar în final, pentru resursa celei de-a doua imagini – 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

Acum să verificăm starea conductei folosind următoarea comandă:

$ tkn pipeline logs -f

După ce conducta a fost pornită și aplicația a fost desfășurată, vom solicita ruta publicată cu următoarea comandă:

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

Pentru o vizualizare mai bună, putem vedea conducta noastră în modul Developer al consolei web în secțiunea Pipeline-uri, așa cum este arătat în Fig. 1.

Aplicații moderne în OpenShift, partea 3: OpenShift ca mediu de dezvoltare și canale OpenShift Pipelines

Fig.1. O privire de ansamblu asupra conductelor în execuție.

Un clic pe conducta în execuție afișează informații suplimentare, așa cum se arată în Fig. 2.

Aplicații moderne în OpenShift, partea 3: OpenShift ca mediu de dezvoltare și canale OpenShift Pipelines

Fig. 2. Informații suplimentare despre conducta.

După informațiile suplimentare, putem vizualiza aplicațiile în execuție în cadrul Topologie, așa cum este arătat în Fig.3.

Aplicații moderne în OpenShift, partea 3: OpenShift ca mediu de dezvoltare și canale OpenShift Pipelines

Fig 3. Pod în execuție.

Un clic pe cerculețul din colțul din dreapta sus al pictogramei deschide aplicația noastră, așa cum este arătat în Fig.4.

Aplicații moderne în OpenShift, partea 3: OpenShift ca mediu de dezvoltare și canale OpenShift Pipelines

Fig. 4. Aplicația React în execuție.

Concluzie

Așadar, am arătat cum să lansezi un server de dezvoltare pentru aplicația ta pe OpenShift și cum să-l sincronizezi cu sistemul de fișiere local. De asemenea, am discutat despre cum să simulezi un template de tip chained-build folosind OpenShift Pipelines. Tot codul exemplelor din acest articol poate fi găsit aici.

Resurse suplimentare (EN)

Anunțuri pentru webinarii viitoare

Începem o serie de webinare de vineri despre experiența nativă cu Red Hat OpenShift Container Platform și Kubernetes:

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster