Acest post este scris deoarece angajații noștri au avut o mulțime de discuții cu clienții despre dezvoltarea aplicațiilor pe Kubernetes și despre specificul acestei dezvoltări pe OpenShift.

De obicei, începem cu teza că Kubernetes este pur și simplu Kubernetes, iar OpenShift este deja o platformă Kubernetes, la fel ca Microsoft AKS sau Amazon EKS. Fiecare dintre aceste platforme are avantajele sale, orientate către o anumită audiență țintă. După aceasta, discuția trece la compararea punctelor forte și slabe ale platformelor specifice.
În general, ne-am gândit să scriem acest post cu concluzia de genul „Ascultați, nu contează unde să rulezi codul, fie pe OpenShift, fie pe AKS, fie pe EKS, fie pe un Kubernetes personalizat, pur și simplu pe orice Kubernetes. (pentru scurt, să-i spunem KUK). Este într-adevăr simplu, atât acolo, cât și aici.
Apoi, plănuiam să luăm un simplu „Hello World” și să arătăm prin exemplul acestuia ce este comun și care sunt diferențele dintre KUK și Red Hat OpenShift Container Platform (mai departe, OCP sau pur și simplu OpenShift).
Cu toate acestea, pe parcursul scrierii acestui post, ne-am dat seama că ne-am obișnuit atât de mult să folosim OpenShift, încât pur și simplu nu realizăm cum a evoluat și s-a transformat într-o platformă uimitoare, care a devenit mult mai mult decât un simplu distribuție Kubernetes. Ne-am obișnuit să considerăm maturitatea și simplitatea OpenShift ca pe ceva normal, neglijând splendoarea sa.
În general, a venit vremea căinței active, și acum vom compara pas cu pas debutul „Hello World” pe KUK și pe OpenShift, și vom face acest lucru cât mai obiectiv posibil (dar, poate, vom exprima uneori o părere personală asupra subiectului). Dacă ești interesat de o opinie pur subiectivă pe această temă, o poți citi În acest post, însă, ne vom menține la fapte și doar fapte.
Clustere.
Așadar, pentru „Hello World” avem nevoie de clustere. Să spunem „nu” tuturor cloudurilor publice pentru a nu plăti pentru servere, registre, rețele, transfer de date etc. Prin urmare, alegem un cluster simplu pe un singur nod pe (pentru KUK) și (pentru clusterul OpenShift). Ambele opțiuni sunt realmente simple de instalat, dar vor necesita destul de multe resurse pe laptopul tău.

Construirea pe KUK.
Așadar, să începem.
Pasul 1 – construim imaginea noastră de container.
Voi începe prin a desfășura „Hello World” pe minikube. Pentru aceasta, avem nevoie de:
- 1. Docker instalat.
- 2. Git instalat.
- 3. Maven instalat (de fapt, în acest proiect se folosește binarul mvnw, așa că se poate să sărim această etapă).
- 4. De fapt, sursa, adică clonarea repo-ului
Primul lucru pe care trebuie să-l facem este să creăm un proiect Quarkus. Nu vă speriați dacă nu ați lucrat niciodată cu site-ul Quarkus.io – este simplu. Trebuie doar să selectați componentele pe care doriți să le folosiți în proiect (RestEasy, Hibernate, Amazon SQS, Camel etc.), iar apoi Quarkus configurează singur arhetipul maven și publică totul pe github. Asta înseamnă, practic, un singur click și gata. De asta iubim Quarkus.

Cea mai simplă metodă de a construi „Hello World” în imaginea de container este să folosești extensiile quarkus-maven pentru Docker, care vor face întreaga muncă necesară. Odată cu apariția Quarkus, acest lucru a devenit cu adevărat simplu: adăugați extensia container-image-docker și puteți crea imagini cu comenzile maven.
./mvnw quarkus:add-extension -Dextensions="container-image-docker"
Și, în final, executăm construcția imaginii noastre folosind Maven. Ca rezultat, codul nostru sursă se transformă într-o imagine de container care poate fi deja rulată în mediul de execuție al containerelor.

./mvnw -X clean package -Dquarkus.container-image.build=true
Iată, și asta este tot, acum putem rula containerul cu comanda docker run, mapând serviciul nostru pe portul 8080, astfel încât să poată fi accesat.
docker run -i --rm -p 8080:8080 gcolman/quarkus-hello-world

După ce instanța containerului s-a pornit, rămâne doar să verificăm cu comanda curl că serviciul nostru funcționează:
![]()
Așadar, totul funcționează, și a fost cu adevărat simplu.
Pasul 2 – trimitem containerul nostru în repository-ul de imagini de containere
Deocamdată, imaginea pe care am creat-o este stocată local, în depozitul nostru local de containere. Dacă dorim să folosim această imagine în mediul nostru K8S, trebuie să o plasăm într-un alt repository. În Kubernetes nu există astfel de funcții, așa că vom folosi dockerhub. Deoarece, pe de o parte, este gratuit, iar pe de altă parte, (aproape) toată lumea face asta.
Este, de asemenea, foarte simplu, și avem nevoie doar de un cont pe dockerhub.
Așadar, ne conectăm la dockerhub și trimitem imaginea noastră acolo.

Pasul 3 – pornim Kubernetes
Există multe modalități de a construi configurația Kubernetes pentru a rula „Hello World”, dar vom folosi cea mai simplă dintre ele, suntem așa…
Pentru început, pornim clusterul minikube:
minikube start
Pasul 4 – desfășurăm imaginea noastră de container
Acum trebuie să transformăm codul nostru și imaginea containerului în configurațiile Kubernetes. Cu alte cuvinte, avem nevoie de o definiție pod și deployment care să facă referire la imaginea noastră pe Docker Hub. Una dintre cele mai simple modalități de a face asta este să rulăm comanda create deployment, specificând imaginea noastră:

kubectl create deployment hello-quarkus --image=gcolman/quarkus-hello-world:1.0.0-SNAPSHOT
Prin această comandă am spus Kubernetes-ului nostru să creeze configurația deployment, care trebuie să conțină specificația pod-ului pentru imaginea noastră de container. Această comandă va aplica, de asemenea, această configurație în clusterul nostru Minikube și va crea un deployment care va descărca imaginea noastră de container și va porni pod-ul în cluster.
Pasul 5 – deschidem accesul la serviciul nostru
Acum, când avem imaginea de container desfășurată, este momentul să ne gândim cum putem configura accesul extern la acest serviciu RESTful, care este, de fapt, programat în codul nostru.
Există multe modalități. De exemplu, putem folosi comanda expose pentru a crea automat componentele Kubernetes corespunzătoare, cum ar fi servicii și endpoint-uri. Așa că asta vom face, executând comanda expose pentru obiectul nostru de deployment:
kubectl expose deployment hello-quarkus --type=NodePort --port=8080
Să ne oprim pentru o clipă asupra opțiunii „--type” din comanda expose.
Când facem expose și creăm componentele necesare pentru a rula serviciul nostru, trebuie, printre altele, să ne asigurăm că putem accesa din exterior serviciul hello-quarkus, care se află în interiorul rețelei noastre definite prin software. Și parametru type ne permite să creăm și să conectăm lucruri precum balansoarele de încărcare, pentru a direcționa traficul în această rețea.
De exemplu, specificând type=LoadBalancer, vom inițializa automat un balansoar de încărcare în cloud public, pentru a ne conecta la clusterul nostru Kubernetes. Desigur, asta este minunat, dar trebuie să înțelegem că o astfel de configurație va fi strâns legată de un anumit cloud public și va fi mai greu de mutat între instanțele Kubernetes în medii diferite.
În exemplul nostru type=NodePort, adică apelul către serviciul nostru se face prin adresa IP a nodului și numărul portului. Această opțiune permite să nu folosim nicio soluție cloud publică, dar necesită o serie de pași suplimentari. În primul rând, avem nevoie de un balansator de încărcare propriu, așa că vom implementa în clusterul nostru un balansator de încărcare NGINX.
Pasul 6 – instalăm balansatorul de încărcare
Minikube are o serie de funcții de platformă care facilitează crearea componentelor necesare pentru accesul extern, cum ar fi controlerele ingress. Minikube vine cu un controler ingress Nginx, iar noi trebuie doar să-l activăm și să-l configurăm.
minikube addons enable ingress
Acum, cu o singură comandă, voi crea un controler ingress Nginx care va funcționa în interiorul clusterului nostru minikube:
ingress-nginx-controller-69ccf5d9d8-j5gs9 1/1 Running 1 33m
Pasul 7 – configurăm ingress
Acum trebuie să configurăm controlerul ingress Nginx pentru a interpreta cererile hello-quarkus.


Și, în final, trebuie să aplicăm această configurație.

kubectl apply -f ingress.yml
![]()
Deoarece facem toate acestea pe computerul nostru, adăugăm pur și simplu adresa IP a nodului nostru în fișierul /etc/hosts pentru a direcționa cererile http către minikube pe balansatorul de încărcare NGINX.
192.168.99.100 hello-quarkus.info
Totul, acum serviciul nostru minikube este disponibil extern prin controlerul ingress Nginx.

Ei bine, a fost ușor, nu-i așa? Sau nu prea?

Lansare pe OpenShift (Code Ready Containers)
Acum să vedem cum se face totul pe Red Hat OpenShift Container Platform (OCP).
La fel ca în cazul minikube, alegem schema cu un cluster OpenShift pe un singur nod sub forma Code Ready Containers (CRC). În trecut, aceasta se numea minishift și se baza pe proiectul OpenShift Origin, iar acum este CRC și construită pe platforma OpenShift Container de la Red Hat.
Aici, ne cerem scuze și nu ne putem abține să nu spunem: „OpenShift este minunat!”
Inițial, am gândit să scriem că dezvoltarea pe OpenShift nu diferă de dezvoltarea pe Kubernetes. Și, în esență, așa este. Dar în timpul scrierii acestui post ne-am amintit câte mișcări suplimentare sunt necesare atunci când nu ai OpenShift, de aceea repetăm, este minunat. Ne place când totul este simplu de realizat, iar modul în care se desfășoară atât de ușor comparativ cu minikube exemplul nostru pe OpenShift, ne-a motivat să scriem acest post.
Să trecem prin proces și să vedem ce va trebui să facem.
Așadar, în exemplul cu minikube, am început cu Docker... Opriți, nu mai avem nevoie ca Docker să fie instalat pe mașină.
Și git local nu este necesar.
Și Maven nu este necesar.
Și nu trebuie să creăm manual imaginea containerului.
Și nu trebuie să căutăm un repository pentru imaginile containerelor.
Și nu trebuie să instalăm un ingress controller.
Și nici să configurăm ingress nu este necesar.
Ați înțeles, da? Pentru a desfășura și a rula aplicația noastră pe OpenShift, nu este nevoie de nimic din cele enumerate mai sus. Iar procesul arată astfel.
Pasul 1 – Pornim clusterul nostru OpenShift
Folosim Code Ready Containers de la Red Hat, care este practic același lucru cu Minikube, dar cu un cluster OpenShift cu un singur nod complet funcțional.
crc start
Pasul 2 – Construim și desfășurăm aplicația în clusterul OpenShift
În acest pas se manifestă pe deplin simplificarea și comoditatea OpenShift. Ca în toate distribuțiile Kubernetes, avem multe moduri de a lansa aplicația în cluster. Și, ca și în cazul Kubernetes, alegem în mod special cea mai simplă opțiune.
OpenShift a fost întotdeauna construit ca o platformă pentru crearea și desfășurarea aplicațiilor containerizate. Construirea containerelor a fost întotdeauna o parte esențială a acestei platforme, așa că există o mulțime de resurse Kubernetes suplimentare pentru sarcinile corespunzătoare.
Vom folosi procesul Source to Image (S2I) al OpenShift, care are mai multe modalități de a lua sursa noastră (codul sau fișierele binare) și de a o transforma într-o imagine de container care să fie rulată în clusterul OpenShift.
Pentru aceasta avem nevoie de două lucruri:
- Codul nostru sursă în repository git
- Imaginea builder, pe baza căreia va fi efectuată construcția.
Există o mulțime de astfel de imagini, susținute atât de Red Hat, cât și de comunitate, iar noi ne vom folosi de imaginea OpenJDK, deoarece construiesc o aplicație Java.
Putem lansa construcția S2I atât din consola grafică a OpenShift Developer, cât și din linia de comandă. Vom folosi comanda new-app, specificând de unde să luăm imaginea builder și codul nostru sursă.

oc new-app registry.access.redhat.com/ubi8/openjdk-11:latest~https://github.com/gcolman/quarkus-hello-world.git
Totul, aplicația noastră a fost creată. În acest proces, S2I a efectuat următoarele acțiuni:
- A creat un build-pod de serviciu pentru toate lucrurile legate de construcția aplicației.
- A creat configurația OpenShift Build.
- A descărcat imaginea builder în registrul docker intern OpenShift.
- A clonat «Hello World» în repository-ul local.
- Am observat că există un pom.xml în Maven, așa că am compilat aplicația folosind Maven.
- Am creat o nouă imagine de container care conține aplicația Java compilată și am pus această imagine în registrul intern de containere.
- Am creat un Deployment Kubernetes cu specificațiile pod-ului, serviciului etc.
- Am lansat desfășurarea imaginii de container.
- Am șters pod-ul de build temporar.
Există multe lucruri în această listă, dar principala idee este că întreaga compilare se desfășoară exclusiv în OpenShift, registrul Docker intern se află în OpenShift, iar procesul de compilare creează toate componentele Kubernetes și le rulează în cluster.
Dacă urmărim vizual lansarea S2I în consolă, putem vedea cum, în timpul compilării, se lansează pod-ul de build.

Și acum să aruncăm o privire asupra jurnalelor pod-ului builder: în primul rând, se poate observa cum Maven își face treaba și descarcă dependențele pentru compilarea aplicației noastre Java.

După ce compilarea cu Maven s-a încheiat, începe construirea imaginii de container, iar apoi această imagine compilată este trimisă în depozitul intern.

Totul, procesul de compilare s-a încheiat. Acum să ne asigurăm că pod-urile și serviciile aplicației noastre au fost lansate în cluster.
oc get service
![]()
Asta e tot. Și doar o singură comandă. Rămâne doar să facem expose al acestui serviciu pentru acces extern.
Pasul 3 – facem expose al serviciului pentru acces extern
La fel ca în cazul CUK, pe platforma OpenShift aplicației noastre «Hello World» îi trebuie un router pentru a direcționa traficul extern către serviciul din cluster. În OpenShift, acest lucru este foarte simplu. În primul rând, în cluster este instalat în mod implicit componenta de rutare HAProxy (o putem schimba cu NGINX). În al doilea rând, există resurse speciale care permit o configurare extinsă, numite Routes, care seamănă cu obiectele Ingress din vechiul Kubernetes (de fapt, Routes din OpenShift au influențat semnificativ designul obiectelor Ingress, care acum pot fi utilizate și în OpenShift), dar pentru «Hello World» și în aproape toate celelalte cazuri, ne va ajunge Route standard fără configurare suplimentară.
Pentru a crea un FQDN rutabil pentru «Hello World» (da, în OpenShift există un DNS propriu pentru rutare după numele serviciilor), trebuie doar să efectuăm un expose pentru serviciul nostru:

oc expose service quarkus-hello-world
Dacă verificăm Route-ul tocmai creat, putem găsi FQDN-ul și alte informații de rutare:
oc get route
![]()
Și în final, ne adresăm serviciului nostru din browser:

Și acum, asta a fost într-adevăr ușor!
Ne place Kubernetes și tot ce poate face această tehnologie, precum și ne place simplitatea și ușurința. Kubernetes a fost creat pentru a simplifica extraordinar exploatarea containerelor distribuite și scalabile, dar pentru a pune în funcțiune aplicațiile, simplitatea acestuia nu mai este suficientă astăzi. Și aici intervine OpenShift, care ține pasul cu vremea și oferă Kubernetes, axat în primul rând pe dezvoltatori. Au fost investite multe eforturi pentru a adapta platforma OpenShift pentru dezvoltatori, inclusiv crearea de instrumente precum S2I, ODI, Developer Portal, OpenShift Operator Framework, integrare cu IDE-uri, cataloage pentru dezvoltatori, integrare cu Helm, monitorizare și multe altele.
Sperăm că acest articol a fost interesant și util pentru voi. Puteți găsi resurse suplimentare, materiale și alte lucruri utile pentru dezvoltarea pe platforma OpenShift pe portalul .
Sursa: habr.com
