Kubernetes-es cikksorozatunk Rinor Maloku Learn Kubernetes in Under 3 Hours: A Detailed Guide to Orchestrating Containers posztjának fordításán alapul, a szerző engedélyével.
A legtöbb Kubernetes-t bemutató cikk azonnal a történet közepébe vág: bemutatja az alapvető fogalmakat és parancsokat feltételezve, hogy az olvasó tökéletesen tisztában van a modern alkalmazásfejlesztéssel, a microservices és a Docker konténerek mibenlétével.
Cikksorozatunkban az alábbi tematikát fogjuk követni:
- először egy mikroservicesre épülő alkalmazást fogunk futtatni lokális környezetben, ezután
- ezt az alkalmazást konténerizáljuk, végül
- bemutatjuk a Kubernetest és a konténerizált alkalmazásunkat egy Kubernetes Cluster-be telepítjük.
Ez a megközelítés véleményünk szerint alkalmas arra, hogy a feladat teljes mélységét átlátva ráébresszük az olvasót, hogy a Kubernetes valójában mennyire egyszerű. Igen, a Kubernetes egyszerű, ha tisztában vagy az azt körülevő technológiákkal és kontextussal.
Vágjunk is bele!
A példa alkalmazás
Annak az egyszerű alkalmazásnak, amelyen keresztül könnyen bemutatható a konténerizáció és a Kubernetes, egyetlen funkcióval bír: egy bevitt mondatról szövegelemzéssel megállapítja annak érzelmi töltetét. Ez a funkció a “sentiment analyser”.

Fig. 1. Sentiment Analysis Web App
Technikai oldalról az alkalmazás 3 részből áll:
- SA-frontend: egy Nginx web szerver szolgálja ki a statikus ReactJS file-okat.
- SA-webapp: egy Java webalkalmazás kezeli a frontendről érkező kéréseket.
- SA-logic: egy Python alkalmazás végzi el a háttérben a szövegelemzést.
Fontos megjegyezni, hogy a mikroszervizek nem izolálódnak teljesen, és ugyan lehetővé teszik az egyes funkciók elkülönülését (“separation of concerns”), de egymással együtt kell működniük.

Fig. 2. Data flow in the Sentiment Analysis WebApp
A komponensek közötti interakciót szemlélteti a fenti ábra:
- A kliens alkalmazás elkéri az index.html-t (amely cserébe az egybecsomagolt ReactJS alkalmazást is elkéri)
- A felhasználó a form kitöltésével meghívja a Spring WebApp-ot
- A Spring WebApp továbbítja a kérést a Python alkalmazásnak
- A Python alkalmazás elvégzi a kalkulációt és visszaküldi a választ
- A Spring WebApp visszaadja a kapott választ a ReactJS-es alkalmazásnak (amely megmutatja azt a felhasználónak)
A fenti példa lokális szükséges kód megtalálható az alábbi kódtárban (a szerző engedélyével): http://github.com/rinormaloku/k8s-mastery
Első lépés: microservice alapú alkalmazás futtatása lokálisan
Mindhárom alkalmazást futtatnunk kell lokálisan, kezdjük hát a legtetszetősebbel, a frontend alkalmazással.
A React-os környezet telepítése
Az SA-frontend életre keltéséhez NodeJS-re és NPM-re van szükségünk. Miután e kettőt feltelepítetted, lépj be az sa-frontend mappába és ott add ki:
npm install
Ezzel letöltjük az összes Javascript függőséget, amely a React alkalmazáshoz szükséges. Ezek a node_modules mappába kerülnek. (A függőségeket a package.json file írja le.) Miután minden függőség lejött, add ki a következő parancsot:
npm start
Ennyi! Ezzel elindítottuk az első React-os alkalmazásunkat, amelyet a localhost-on a 3000-es porton érsz el:
A következő lépés a React alkalmazásunk felkészítése éles környezetre.
A React alkalmazásunk felkészítése éles környezetre
Ehhez az alkalmazásunkat statikus file-okká kell alakítanunk, majd egy web szerveren keresztül kell elérhetővé tenni. Még mindig az sa-frontend mappában adjuk ki a következő parancsot:
npm run build
A fenti parancs egy “build” nevű mappát hoz létre, amely a React alkalmazásunk összes statikus file-ját tartalmazza.
Statikus file-ok kiszolgálása Nginx-szel
A hivatkozott leírást követve tegyünk fel egy Nginx-et, majd mozgassuk az sa-fontend/build mappa teljes tartalmát az Nginx /html mappájába.
Így az alkalmazás legenerált index.html file-ja elérhető lesz a lokális Nginx fő mappája alatt /html/index.html-ként. Ez lesz az a file, amit az Nginx alapértelmezettként kiszolgál.
Az Nginx alapesetben a 80-as porton szolgál ki, vagyis lokálisan a http://localhost:80 címen a ReactJS alkalmazásunknak kell feltűnnie:

Fig. 3. React app served from Nginx
Ha ebben a stádiumban beírunk egy mondatot és rákattintunk a SEND gombra, akkor még egy 404-es hibát kell, hogy kapjunk. Miért is van ez?
Vizsgáljuk meg a kódot
Az App.js file-ban keressük meg azt a részt, ami akkor hívódik meg, amikor a SEND gombot megnyomjuk. A SEND gomb az “analyzeSentence” metódust hívja meg.
analyzeSentence() { fetch('http://localhost:8080/sentiment', { // #1 method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sentence: this.textField.getValue()})// #2 }) .then(response => response.json()) .then(data => this.setState(data)); // #3 }
A #1 számozás azt az URL-t jelöli, amelyikre a POST hívás érkezik. (Egy alkalmazásnak ezen az URL-en kell figyelnie).
A #2 számozásnál a kérés törzsét küldjük be, ami esetünkben:
{ sentence: “I like yogobella!” }
A #3 számozásnál frissül a komponens állapota. Ezzel a komponens újra leképeződik. Ha adatot kapunk a háttérből, akkor az is megjelenik.
Minden helyesnek tűnik. Viszont semmi sem figyel a 8080-as porton. Ez az, ami hiányzik. A Spring-es web alkalmazásunkat is el kell indítanunk.

Fig. 4. Microservice Spring WebApp missing
A Spring-es web alkalmazás beállítása
A Java-s alkalmazás futtatásához szükséged lesz JDK8-ra és Maven-re. Miután ezeket feltetted, folytassuk a következőkkel.
Az alkalmazás JAR-ba csomagolása
Lépjünk be az sa-webapp mappába és ott adjuk ki a következő parancsot:
mvn install
Ezzel létrejön egy “target” mappa az sa-webapp-on belül. A “target” mappában az alábbi file keletkezett: “sentiment-analysis-web-0.0.1-SNAPSHOT.jar”
A Java alkalmazásunk indítása
A “target” mappában add ki a következő parancsot:
java -jar sentiment-analysis-web-0.0.1-SNAPSHOT.jar
Paffff. Az alkalmazás elhasal a következő hibával:
Error creating bean with name 'sentimentController': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'sa.logic.api.url' in value "${sa.logic.api.url}"
A nyomravezető tipp a kiemelt részben látható.
Vizsgáljuk meg a Java kódot
A SentimentController-ben az alábbi rész az érdekes:
@CrossOrigin(origins = "*") @RestController public class SentimentController { @Value("${sa.logic.api.url}") // #1 private String saLogicApiUrl; @PostMapping("/sentiment") public SentimentDto sentimentAnalysis( @RequestBody SentenceDto sentenceDto) { RestTemplate restTemplate = new RestTemplate(); return restTemplate.postForEntity( saLogicApiUrl + "/analyse/sentiment", // #2 sentenceDto, SentimentDto.class) .getBody(); } }
Az 1# számozású sorban a “sa.logic.api.url” értékével töltjük fel a “saLogicApiUrl”-t.
A #2 számozásnál a “saLogicApiUrl”-hez még hozzáadjuk a “/analyse/sentiment” részt, és ezzel teljes lesz az az URL, amit a Java alkalmazásunknak meg kell hívnia.
Állítsuk be ezt a Java property-t az alábbi módon, most kivételesen nem egy application.properties file-ból, hanem egyszerűen egy parancsból:
java -jar sentiment-analysis-web-0.0.1-SNAPSHOT.jar --sa.logic.api.url=WHAT.IS.THE.SA.LOGIC.API.URL
Vagyis esetünkben ez legyen “localhost:5000”, tehát:
java -jar sentiment-analysis-web-0.0.1-SNAPSHOT.jar --sa.logic.api.url=http://localhost:5000
Így nem lesz már eltörve az út a backend alkalmazásig. Ez a háttér alkalmazás viszont még nem fut. A következő lépésben ezt kell elindítanunk.
A Python alkalmazás beállítása
A Python alkalmazás lokális futtatásához szükségünk lesz egy Python3-ra és Pip-re.
Telepítsük fel a függőségeket.
Navigáljunk az sa-logic/sa mappába, ahol adjuk ki az alábbi parancsokat:
python -m pip install -r requirements.txt python -m textblob.download_corpora
Majd indítsuk el a Python alkalmazást:
python sentiment_analysis.py * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Ezzel a háttér alkalmazásunk az 5000-es porton figyel és várja a kéréseket.
Így teljes a kép, az alábbiak alapján lokálisan működik minden komponens:
Nyissuk ki tehát újra a böngészőnket és hívjuk be a frontend alkalmazást. Most már nem szabad, hogy 404-et kapjunk, mindennek működnie kell.
Minden szép és jó, viszont ezek a komponensek még nem készek a Kubernetes-re. Ezeket először egyenként konténerizálni kell.
Erre térünk ki a cikksorozat következő részében.
Dockerre fel!