Applicazioni moderne su OpenShift, parte 3: OpenShift come ambiente di sviluppo e pipeline OpenShift Pipelines

Ciao a tutti in questo blog! Questo è il terzo post di una serie in cui mostriamo come distribuire applicazioni web moderne su Red Hat OpenShift.

Applicazioni moderne su OpenShift, parte 3: OpenShift come ambiente di sviluppo e pipeline OpenShift Pipelines

Nei due post precedenti, abbiamo illustrato come distribuire applicazioni web moderne in pochi passaggi e come usare la nuova immagine S2I insieme a un'immagine di server HTTP predefinita, come NGINX, utilizzando build collegate (chained builds) per organizzare distribuzioni in produzione.

Oggi mostreremo come avviare un server di sviluppo per la nostra applicazione sulla piattaforma OpenShift e sincronizzarlo con il file system locale, e discuteremo anche di cosa siano le OpenShift Pipelines e come possano essere utilizzate come alternativa alle build collegate.

OpenShift come ambiente di sviluppo

Flusso di lavoro di sviluppo

Come già accennato nel primo post, il processo di sviluppo tipico per le applicazioni web moderne è essenzialmente un "server di sviluppo" che monitora le modifiche nei file locali. Quando queste si verificano, viene avviata la build dell'applicazione e poi questa viene aggiornata nel browser.

Nella maggior parte dei moderni framework, un tale "server di sviluppo" è integrato negli strumenti da riga di comando corrispondenti.

Esempio locale

Per iniziare, vediamo come funziona nel caso di un'esecuzione locale delle applicazioni. Prendiamo come esempio l'applicazione React tratta nei precedenti articoli, anche se praticamente gli stessi concetti di flusso di lavoro si applicano in tutti gli altri moderni framework.
Dunque, per avviare il "server di sviluppo" nel nostro esempio con React, inseriamo il seguente comando:

$ npm run start

Allora nella finestra del terminale vedremo qualcosa del genere:

Applicazioni moderne su OpenShift, parte 3: OpenShift come ambiente di sviluppo e pipeline OpenShift Pipelines

E la nostra applicazione si aprirà nel browser predefinito:

Applicazioni moderne su OpenShift, parte 3: OpenShift come ambiente di sviluppo e pipeline OpenShift Pipelines

Ora, se apportiamo modifiche al file, l'applicazione dovrebbe aggiornarsi nel browser.

OK, con lo sviluppo in modalità locale è tutto chiaro, ma come ottenere lo stesso su OpenShift?

Server di sviluppo su OpenShift

Se ricordate, nel post precedente, abbiamo esaminato la cosiddetta fase di esecuzione (run phase) dell'immagine S2I e abbiamo visto che per impostazione predefinita la nostra applicazione web è gestita dal modulo serve.

Tuttavia, se guardiamo più da vicino run script Da quell'esempio, c'è una variabile di ambiente $NPM_RUN che consente di eseguire anche il proprio comando.

Ad esempio, è possibile utilizzare il modulo nodeshift per distribuire la nostra applicazione:

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

Nota: l'esempio sopra è fornito in forma abbreviata per illustrare l'idea generale.

Qui abbiamo aggiunto alla nostra distribuzione la variabile di ambiente NPM_RUN, che comunica al processo di esecuzione di avviare il comando yarn start, il quale avvia il server di sviluppo React all'interno del nostro pod OpenShift.

Se esaminiamo il log del pod in esecuzione, troveremo circa il seguente output:

Applicazioni moderne su OpenShift, parte 3: OpenShift come ambiente di sviluppo e pipeline OpenShift Pipelines

Certo, tutto ciò non avrà senso fino a quando non saremo in grado di sincronizzare il codice locale con il codice che viene anch'esso monitorato per le modifiche, ma si trova su un server remoto.

Sincronizzazione del codice remoto e locale

Fortunatamente, nodeshift facilita la sincronizzazione, e per monitorare le modifiche possiamo utilizzare il comando watch.

Quindi, dopo aver eseguito il comando per distribuire il server di sviluppo per la nostra applicazione, possiamo tranquillamente usare il seguente comando:

$ npx nodeshift watch

Di conseguenza, verrà stabilita una connessione al pod in esecuzione che abbiamo creato poco prima, attivando la sincronizzazione dei nostri file locali con il cluster remoto, e i file nel nostro sistema locale inizieranno a essere monitorati per le modifiche.

Quindi, se ora aggiorniamo il file src/App.js, il sistema reagirà a queste modifiche, copierà le modifiche sul cluster remoto e avvierà il server di sviluppo, il quale aggiornerà quindi la nostra applicazione nel browser.

Per completezza, mostriamo come appaiono questi comandi nella loro interezza:

$ 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

Il comando watch è un'astrazione sopra il comando oc rsync, per maggiori informazioni su come funziona, si può leggere qui.

Questo è stato un esempio per React, ma la stessa metodologia può essere utilizzata anche con altri framework, basta impostare la variabile di ambiente NPM_RUN nel modo corretto.

Pipeline di OpenShift Pipelines

Applicazioni moderne su OpenShift, parte 3: OpenShift come ambiente di sviluppo e pipeline OpenShift Pipelines

Successivamente parleremo di uno strumento chiamato OpenShift Pipelines e di come può essere utilizzato come alternativa alle build concatenate.

Che cos'è OpenShift Pipelines

OpenShift Pipelines è un sistema CI/CD basato sul cloud per l'integrazione continua e la consegna, progettato per organizzare pipeline utilizzando Tekton. Tekton è un framework CI/CD nativo Kubernetes flessibile e open source, che consente di automatizzare il deployment su varie piattaforme (Kubernetes, serverless, macchine virtuali, ecc.) astrarre rispetto al livello sottostante.

Per capire questo articolo è necessaria una certa familiarità con i Pipelines, quindi ti consigliamo vivamente di iniziare consultando il manuale ufficiale.

Configurazione dell'ambiente di lavoro

Per sperimentare con gli esempi di questo articolo, devi prima preparare l'ambiente di lavoro:

  1. Installa e configura un cluster OpenShift 4. Nei nostri esempi utilizziamo CodeReady Containers (CRD), le istruzioni per l'installazione possono essere trovate qui.
  2. Una volta che il cluster è pronto, sarà necessario installare il Pipeline Operator. Non preoccuparti, è facile, le istruzioni per l'installazione qui.
  3. Scarica Tekton CLI (tkn) qui.
  4. Esegui lo strumento da riga di comando create-react-app per creare un'applicazione che verrà poi distribuita (si tratta di un'app semplice React).
  5. (Facoltativo) Clona il repository per eseguire localmente l'esempio dell'app con il comando npm install e poi npm start.

Nel repository dell'applicazione ci sarà anche una cartella k8s, dove si troveranno i file YAML di Kubernetes/OpenShift utilizzati per il deployment dell'applicazione. Ci saranno Tasks, ClusterTasks, Resources e Pipelines che creeremo in questo repository.

Iniziamo

Per prima cosa, per il nostro esempio, è necessario creare un nuovo progetto nel cluster OpenShift. Chiamiamo questo progetto webapp-pipeline e lo creiamo con il seguente comando:

$ oc new-project webapp-pipeline

In seguito questo nome del progetto apparirà nel codice, quindi, se decidi di dargli un nome diverso, non dimenticare di modificare di conseguenza il codice degli esempi. Da questo punto in poi procederemo dal basso verso l'alto: prima creeremo tutti i componenti della pipeline e solo successivamente la pipeline stessa.

Quindi, prima di tutto…

Tasks

Creeremo un paio di attività (tasks) che poi aiuteranno a implementare l'applicazione nel nostro pipeline. La prima attività – apply_manifests_task – si occupa dell'applicazione dei YAML dei risorse Kubernetes (service, deployment e route) che si trovano nella cartella k8s della nostra applicazione. La seconda attività – update_deployment_task – è responsabile dell'aggiornamento dell'immagine già implementata a quella creata dal nostro pipeline.

Non preoccuparti se non è ancora molto chiaro. In realtà, queste attività sono una sorta di utilità e le esamineremo più in dettaglio tra poco. Ma per ora, creiamole semplicemente:

$ 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

Poi, usando il comando tkn CLI, verifichiamo che le attività siano state create:

$ tkn task ls

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

Nota: queste sono attività locali del tuo progetto attuale.

Attività cluster (Cluster tasks)

Le attività cluster sono fondamentalmente le stesse delle normali attività. Cioè, sono una collezione riutilizzabile di passaggi che vengono combinati in vari modi quando si esegue una specifica attività. La differenza è che un'attività cluster è disponibile ovunque all'interno del cluster. Per vedere l'elenco delle attività cluster, che vengono create automaticamente quando si aggiunge il Pipeline Operator, utilizziamo di nuovo il comando 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

Ora creiamo due attività cluster. La prima genererà un'immagine S2I e la invierà al registry interno di OpenShift; la seconda eseguirà la costruzione della nostra immagine basata su NGINX, utilizzando come contenuto l'applicazione già costruita da noi.

Creiamo e inviamo l'immagine

Nella creazione della prima attività, ripeteremo ciò che abbiamo già fatto nell'articolo precedente sulle build collegate. Ricordiamo che abbiamo utilizzato l'immagine S2I (ubi8-s2i-web-app) per "compilare" la nostra applicazione, ottenendo infine un'immagine memorizzata nel registro interno di OpenShift. Ora utilizzeremo questa immagine S2I dell'app web per creare un DockerFile per la nostra applicazione, e quindi utilizzeremo Buildah per eseguire una compilazione reale e inviare l'immagine risultante al registro interno di OpenShift, poiché è esattamente ciò che OpenShift fa quando distribuisci le tue applicazioni utilizzando NodeShift.

Ti chiedi da dove abbiamo preso tutte queste informazioni? Da официальной версии official Node.js, l'abbiamo semplicemente copiata e adattata a noi.

Ora creiamo l'attività cluster s2i-web-app:

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

Non entreremo nei dettagli, ma ci fermeremo sul parametro OUTPUT_DIR:

params:
      - name: OUTPUT_DIR
        description: La posizione della directory di output della build
        default: build

Per impostazione predefinita, questo parametro è uguale a build, ed è lì che React colloca il contenuto compilato. In altri framework si utilizzano percorsi diversi, ad esempio in Ember si usa dist. L'output della nostra prima attività cluster sarà un'immagine contenente l'HTML, il JavaScript e il CSS che abbiamo compilato.

Compiliamo un'immagine basata su NGINX

Per quanto riguarda la nostra seconda attività cluster, questa deve costruire un'immagine basata su NGINX, utilizzando il contenuto della nostra applicazione già compilata. In sostanza, questa è la parte della sezione precedente in cui abbiamo esaminato le build collegate.

A tal fine, proprio come sopra, creeremo l'attività cluster webapp-build-runtime:

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

Se guardiamo il codice di queste attività cluster, vediamo che non viene specificato il repository Git con cui stiamo lavorando, né i nomi delle immagini che stiamo creando. Stiamo solo specificando cosa vogliamo passare in Git, o un'immagine in cui deve essere prodotto l'immagine finale. È per questo che queste attività cluster possono essere riutilizzate anche quando si lavora con altre applicazioni.

E qui passiamo elegantemente al punto successivo…

Risorse

Quindi, poiché, come abbiamo appena detto, i task di cluster devono essere il più generali possibile, dobbiamo creare risorse che saranno utilizzate in input (repository Git) e in output (immagini finali). La prima risorsa di cui abbiamo bisogno è Git, dove si trova la nostra applicazione, qualcosa del genere:

# 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

Qui PipelineResource è di tipo git. La chiave url nella sezione params punta a un repository specifico e imposta il branch master (questo è facoltativo, ma lo scriviamo per completezza).

Ora dobbiamo creare una risorsa per l'immagine, dove saranno salvati i risultati dell'esecuzione del task s2i-web-app, si fa così:

# 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

Qui PipelineResource è di tipo image, e il valore del parametro url punta al registro delle immagini interno di OpenShift, specificamente a quello che si trova nello spazio dei nomi webapp-pipeline. Non dimenticare di cambiare questo parametro se utilizzi un altro spazio dei nomi.

E, infine, l'ultima risorsa di cui avremo bisogno avrà anch'essa il tipo image e sarà l'immagine finale di NGINX, che verrà utilizzata durante il deployment:

# 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

E ancora, nota che questa risorsa salva l'immagine nel registro interno di OpenShift nello spazio dei nomi webapp-pipeline.

Per creare tutte queste risorse in una volta, utilizziamo il comando create:

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

Puoi controllare che le risorse siano state create in questo modo:

$ tkn resource ls

Pipeline del pipeline

Ora che abbiamo tutti gli elementi necessari, creiamo il pipeline utilizzando il seguente comando:

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

Ma prima di eseguire questo comando, diamo un'occhiata a questi elementi. Il primo è il nome:

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

Poi, nella sezione spec vediamo l'indicazione delle risorse che abbiamo creato in precedenza:

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

Successivamente, creiamo i task che il nostro pipeline deve eseguire. Per prima cosa deve eseguire il task s2i-web-app che abbiamo già creato:

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

Questo task prende i parametri di input (risorsa gir) e di output (risorsa built-web-application-image). Inoltre, le passiamo un parametro speciale per evitare la verifica di TLS, poiché utilizziamo certificati self-signed:

risorse:
        input:
          - nome: sorgente
            risorsa: web-application-repo
        output:
          - nome: immagine
            risorsa: built-web-application-image
      parametri:
        - nome: TLSVERIFY
          valore: "false"

Il prossimo compito è quasi identico, solo che qui viene chiamato il compito cluster webapp-build-runtime già creato da noi:

nome: build-runtime-image
    taskRef:
      nome: webapp-build-runtime
      tipo: ClusterTask

Come per il compito precedente, stiamo passando una risorsa, ma ora si tratta di built-web-application-image (l'output del nostro compito precedente). E come output impostiamo di nuovo un'immagine. Poiché questo compito deve essere eseguito dopo il precedente, aggiungiamo il campo runAfter:

risorse:
        input:
          - nome: immagine
            risorsa: built-web-application-image
        output:
          - nome: immagine
            risorsa: runtime-web-application-image
        parametri:
        - nome: TLSVERIFY
          valore: "false"
      runAfter:
        - build-web-application

I prossimi due compiti sono responsabili dell'applicazione dei file YAML del servizio, del percorso e del deployment, che si trovano nella cartella k8s della nostra applicazione web, e anche di aggiornare questo deployment quando vengono creati nuovi modelli. Questi due compiti cluster li abbiamo definiti all'inizio dell'articolo.

Avvio della pipeline

Quindi, tutte le parti della nostra pipeline sono state create, e la avvieremo con il seguente comando:

$ tkn pipeline start build-and-deploy-react

A questo punto, la riga di comando viene utilizzata in modalità interattiva e bisogna selezionare le risorse corrispondenti in risposta a ciascuna sua richiesta: per la risorsa git scegliamo web-application-repo, quindi per la risorsa della prima immagine – built-web-application-image, e infine per la risorsa della seconda immagine – 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

Ora controlliamo lo stato della pipeline con il seguente comando:

$ tkn pipeline logs -f

Dopo che la pipeline è stata avviata e l'applicazione è stata distribuita, richiediamo il percorso pubblicato con il seguente comando:

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

Per una maggiore visibilità, possiamo visualizzare la nostra pipeline in modalità Developer nella web console nella sezione Pipelines, come mostrato nella Fig. 1.

Applicazioni moderne su OpenShift, parte 3: OpenShift come ambiente di sviluppo e pipeline OpenShift Pipelines

Fig.1. Panoramica delle pipeline in esecuzione.

Cliccando sulla pipeline in esecuzione si visualizzano ulteriori informazioni, come mostrato nella Fig.2.

Applicazioni moderne su OpenShift, parte 3: OpenShift come ambiente di sviluppo e pipeline OpenShift Pipelines

Fig. 2. Ulteriori informazioni sulla pipeline.

Dopo ulteriori informazioni, possiamo visualizzare le applicazioni in esecuzione nella vista Topology, come mostrato nella Fig.3.

Applicazioni moderne su OpenShift, parte 3: OpenShift come ambiente di sviluppo e pipeline OpenShift Pipelines

Fig 3. Pod in esecuzione.

Cliccando sul cerchio nell'angolo in alto a destra dell'icona si apre la nostra applicazione, come mostrato nella Fig.4.

Applicazioni moderne su OpenShift, parte 3: OpenShift come ambiente di sviluppo e pipeline OpenShift Pipelines

Fig. 4. Applicazione React in esecuzione.

Conclusione

Quindi, abbiamo mostrato come avviare un server di sviluppo su OpenShift per la propria applicazione e sincronizzarlo con il sistema di file locale. Abbiamo anche esaminato come simulare un modello di chained-build utilizzando OpenShift Pipelines. Tutti i codici di esempio di questo articolo possono essere trovati qui.

Risorse aggiuntive (EN)

Annunci di prossimi webinar

Iniziamo una serie di webinar del venerdì sull'esperienza nativa di utilizzo di Red Hat OpenShift Container Platform e Kubernetes:

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster