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.

Î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 , 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 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:

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

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 , 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 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:

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ă. .
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

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 .
Configurarea mediului de lucru
Pentru a experimenta cu exemplele din acest articol, trebuie mai întâi să pregătiți mediul de lucru:
- Instalați și configurați un cluster OpenShift 4. În exemplele noastre, folosim CodeReady Containers (CRD), instrucțiunile de instalare pot fi găsite .
- După ce clusterul este gata, trebuie să instalați Pipeline Operator. Nu vă faceți griji, este simplu, instrucțiunile de instalare .
- Descarcă (tkn) .
- 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ă ).
- (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 .
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 , 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.

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.

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.

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.

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 .
Resurse suplimentare (EN)
- Carte electronică gratuită
- Alte articole despre pe site-ul Red Hat
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
