Diese Datei ist in Markdown geschrieben und kann z.B. mit IntelliJ IDEA gelesen werden. Näheres zu Markdown gibt es z.B. bei Markdown Guide oder JetBrains
Bevor man mit der Projektarbeit an der 2. Abgabe beginnt, sichert man sich die 1. Abgabe, u.a. weil für die 2. Abgabe auch die Original-Implementierung aus der 1. Abgabe benötigt wird.
Inhalt
- Eigener Namespace in Kubernetes
- Relationale Datenbanksysteme
- Administration des Kubernetes-Clusters
- Übersetzung und lokale Ausführung
- HTTP Client von IntelliJ IDEA
- OpenAPI mit Swagger
- Unit Tests und Integrationstests
- Rechnername in der Datei hosts
- Kubernetes, Helm und Skaffold
- Statische Codeanalyse
- Dokumentation
- Einfache Lasttests mit Fortio
Genauso wie in Datenbanksystemen gibt es in Kubernetes keine untergeordneten
Namespaces. Vor allem ist es in Kubernetes empfehlenswert für die eigene
Software einen neuen Namespace anzulegen und NICHT den Default-Namespace
zu benutzen. Das wurde bei der Installation von Kubernetes durch den eigenen
Namespace acme
bereits erledigt. Außerdem wurde aus Sicherheitsgründen beim
defaultmäßigen Service-Account das Feature Automounting deaktiviert und der
Kubernetes-Cluster wurde intern defaultmäßig so abgesichert, dass
- über das Ingress-Gateway keine Requests von anderen Kubernetes-Services zulässig sind
- über das Egress-Gateway keine Requests an andere Kubernetes-Services zulässig sind.
Wenn man den eigenen Microservice direkt mit Windows - nicht mit Kubernetes - laufen lässt, kann man PostgreSQL und das Administrationswerkzeug pgadmin einfach mit Docker Compose starten und später auch herunterfahren.
❗ Vor dem 1. Start von PostgreSQL muss das Skript
create-db-kunde.sql
aus dem Verzeichnisextras\sql\postgres
nachC:\Zimmermann\volumes\postgres\sql
kopieren und die Anleitung ausführen. Für die Windows-VerzeichnisseC:\Zimmermann\volumes\postgres\data
,C:\Zimmermann\volumes\postgres\tablespace
undC:\Zimmermann\volumes\postgres\tablespace\kunde
muss außerdem Vollzugriff gewährt werden, was über das Kontextmenü mit Eigenschaften und den Karteireiter Sicherheit für die Windows-Gruppe Benutzer eingerichtet werden kann. Übrigens ist das Emoji für das Ausrufezeichen von https://emojipedia.org.
# User "postgres" in docker-compose.yaml vor dem 1. Start auskommentieren
docker compose up postgres pgadmin
# 2. Shell: DB, DB-User und Tablespace anlegen
docker compose exec postgres bash
chown postgres:postgres /var/lib/postgresql/tablespace
chown postgres:postgres /var/lib/postgresql/tablespace/kunde
docker compose down
# in docker-compose.yaml den User "postgres" wieder aktivieren, d.h. Kommentar entfernen
# 1. Shell:
docker compose up postgres
# 2. Shell:
docker compose exec postgres bash
psql --dbname=postgres --username=postgres --file=/sql/create-db-kunde.sql
# 2. Shell: Herunterfahren
docker compose down
Der Name des Docker-Containers lautet postgres
und ebenso lautet der
virtuelle Rechnername postgres
. Der virtuelle Rechnername postgres
wird später auch als Service-Name für PostgreSQL in Kubernetes verwendet.
Der neue Datenbank-User kunde
wurde zum Owner der Datenbank kunde
.
Statt eine PowerShell zu verwenden, kann man Docker Compose auch direkt in IntelliJ aufrufen, indem man im Tool-Window Services unterhalb von Docker und dem Eintrag Docker-compose: kunde den Service postgres durch den grünen Start-Button am linken Rand startet.
Jetzt läuft der PostgreSQL- bzw. DB-Server. Die Datenbank-URL für den eigenen
Microservice als DB-Client lautet: postgresql://localhost/kunde
, dabei ist
localhost
aus Windows-Sicht der Rechnername, der Port defaultmäßig 5432
und der Datenbankname kunde
.
Außerdem kann pgadmin zur Administration verwendet werden. pgadmin läuft
ebenfalls als Docker-Container und ist über ein virtuelles Netzwerk mit dem
Docker-Container des DB-Servers verbunden. Deshalb muss beim Verbinden mit dem
DB-Server auch der virtuelle Rechnername postgres
statt localhost
verwendet
werden. pgadmin kann man mit einem Webbrowser und der URL http://localhost:8888
aufrufen. Die Emailadresse [email protected]
und das Passwort p
sind voreingestellt.
Da pgadmin ist übrigens mit Chromium implementiert ist.
Beim 1. Einloggen konfiguriert man einen Server-Eintrag mit z.B. dem Namen
localhost
und verwendet folgende Werte:
- Host:
postgres
(virtueller Rechnername des DB-Servers im Docker-Netzwerk. BEACHTE:localhost
ist im virtuellen Netzwerk der Name des pgadmin-Containers selbst !!!) - Port:
5432
(Defaultwert) - Username:
postgres
(Superuser beim DB-Server) - Password:
p
Es empfiehlt sich, das Passwort abzuspeichern, damit man es künftig nicht jedes Mal beim Einloggen eingeben muss.
Wenn der eigene Microservice in Kubernetes gestartet werden soll (s.u.), muss
PostgreSQL zuvor in Kubernetes gestartet werden, was mit Skaffold gemacht
werden kann. Wenn die Umgebungsvariable SKAFFOLD_PROFILE
auf den Wert dev
gesetzt ist, dann wird das Profile dev
verwendet, welches bei Helm zusätzlich
die Datei dev.yaml
verwendet. Bis der Endpoint für PostgreSQL aktiviert ist,
muss man ein bisschen warten.
cd extras\postgres
skaffold dev --no-prune=false --cache-artifacts=false
<Strg>C
skaffold delete
Dabei wurde auch das Administrationswerkzeug pgadmin innerhalb von Kubernetes
gestartet und kann wegen Port-Forwarding mit http://localhost:8888
aufgerufen
werden.
Mit <Strg>C
kann die Installation wieder zurückgerollt werden und man ruft
abschließend skaffold delete
auf.
Ohne die beiden Optionen muss man noch manuell die PersistentVolumeClaims
löschen, da bei metadata.finalizers
der Wert auf kubernetes.io/pvc-protection
gesetzt ist und auch durch kubectl patch pvc <PVC_NAME> -p '{"metadata":{"finalizers": []}}' --type=merge
nicht entfernt werden kann. Dazu gibt es das PowerShell-Skript delete-pvc.ps1
im Verzeichnis extras\postgres
.
Statt Skaffold kann man auch helmfile mit manuellem Port-Forwarding verwenden:
cd extras\postgres
helmfile apply
.\port-forward.ps1
# Deinstallieren
helmfile destroy
.\delete-pvc.ps1
Wenn man den eigenen Microservice direkt mit Windows - nicht mit Kubernetes - laufen lässt, kann man MySQL und das Administrationswerkzeug phpMyAdmin einfach mit Docker Compose starten und später auch herunterfahren.
❗ Vor dem 1. Start von MySQL muss man das Skript
create-db-kunde.sql
aus dem Projektverzeichnisextras\sql\mysql
nachC:\Zimmermann\volumes\mysql\sql
kopieren und die Anleitung ausführen. Dabei wird der DB-Userkunde
und dessen Datenbankkunde
angelegt, d.h. der neue Datenbank-Userkunde
wird zum Owner der Datenbankkunde
. Dazu muss man sich mit dem Docker-Container mit Namenmysql
verbinden und im Docker-Container das SQL-Skript ausführen:
docker compose up mysql phpmyadmin
# 2. Shell: DB-User "kunde" und dessen Datenbank "kunde" anlegen
docker compose exec mysql sh
mysql --user=root --password=p < /sql/create-db-kunde.sql
# 2. Shell: Herunterfahren
docker compose down
Statt eine PowerShell zu verwenden, kann man Docker Compose auch direkt in IntelliJ aufrufen, indem man im Tool-Window Services unterhalb von Docker und dem Eintrag Docker-compose: kunde den Service mysql durch den grünen Start-Button am linken Rand startet.
Jetzt läuft der DB-Server. Die Datenbank-URL für den eigenen Microservice als
DB-Client lautet: mysql://localhost/kunde
. Dabei ist localhost
aus
Windows-Sicht der Rechnername, der Port defaultmäßig 3306
und der
Datenbankname kunde
.
Außerdem kann phpMyAdmin oder dbeaver zur Administration verwendet werden.
phpMyAdmin läuft ebenfalls als Docker-Container und ist über ein virtuelles
Netzwerk mit dem Docker-Container des DB-Servers verbunden. Deshalb muss beim
Verbinden mit dem DB-Server auch der virtuelle Rechnername mysql
verwendet werden.
phpMyAdmin ruft man mit einem Webbrowser und der URL http://localhost:8889
auf. Zum Einloggen verwendet man folgende Werte:
- Server:
mysql
(virtueller Rechnername des DB-Servers im Docker-Netzwerk. BEACHTE:localhost
ist im virtuellen Netzwerk der Name des phpMyAdmin-Containers selbst !!!) - Benutzername:
root
(Superuser beim DB-Server) - Password:
p
Wenn der eigene Microservice in Kubernetes gestartet werden soll (s.u.), muss
MySQL zuvor in Kubernetes gestartet werden, was mit Skaffold gemacht werden
kann. Wenn die Umgebungsvariable SKAFFOLD_PROFILE
auf den Wert dev
gesetzt ist, dann wird das Profile dev
verwendet, welches bei Helm zusätzlich
die Datei dev.yaml
verwendet. Bis der Endpoint für MySQL aktiviert ist,
muss man ein bisschen warten.
cd extras\mysql
skaffold dev --no-prune=false --cache-artifacts=false
<Strg>C
skaffold delete
Dabei wurde auch das Administrationswerkzeug phpMyAdmin innerhalb von Kubernetes
gestartet und kann wegen Port-Forwarding mit http://localhost:8889
aufgerufen
werden.
Mit <Strg>C
kann die Installation wieder zurückgerollt werden.
Ohne die beiden Optionen muss man noch manuell die PersistentVolumeClaims
löschen, da bei metadata.finalizers
der Wert auf kubernetes.io/pvc-protection
gesetzt ist und auch durch kubectl patch pvc <PVC_NAME> -p '{"metadata":{"finalizers": []}}' --type=merge
nicht entfernt werden kann. Dazu gibt es das PowerShell-Skript delete-pvc.ps1
im Verzeichnis extras\mysql
.
Statt Skaffold kann man auch helmfile mit manuellem Port-Forwarding verwenden:
cd extras\mysql
helmfile apply
.\port-forward.ps1
# Deinstallieren
helmfile destroy
.\delete-pvc.ps1
Wenn man den eigenen Microservice direkt mit Windows - nicht mit Kubernetes - laufen lässt, kann man Oracle einfach mit Docker Compose starten und später auch herunterfahren.
❗ Das erstmalige Hochfahren von Oracle XE kann einige Minuten dauern. Dabei werden auch die beiden üblichen Oracle-User
SYS
undSYSTEM
jeweils mit dem Passwortp
angelegt.
docker compose up
# Herunterfahren in einer 2. Shell:
docker compose down
Der Name des Docker-Containers und des virtuellen Rechners lautet oracle
.
Der virtuelle Rechnername wird später auch als Service-Name für
Oracle in Kubernetes verwendet.
❗ Nach dem 1. Start des DB-Servers muss man einmalig den Datenbank-User
kunde
, den Tablespacekundespace
und das Schemakunde
für den gleichnamigen User anlegen. Dazu muss man ggf. SQLcl von https://www.oracle.com/de/tools/downloads/sqlcl-downloads.html herunterladen und die ZIP-Datei inC:\Zimmermann
auspacken, so dass es die DateiC:\Zimmermann\sqlcl\bin\sql.exe
gibt. Außerdem muss man die UmgebungsvariablePATH
umC:\Zimmermann\sqlcl\bin
ergänzen. Danach kann man folgendes PowerShell-Skript ausführen:
cd extras\oracle
.\create-kunde.ps1
Statt eine PowerShell zu verwenden, kann man Docker Compose auch direkt in IntelliJ aufrufen, indem man im Tool-Window Services unterhalb von Docker und dem Eintrag Docker-compose: kunde den Service oracle durch den grünen Start-Button am linken Rand startet.
Die Datenbank-URL für den eigenen Microservice und auch für SQL Developer
als grafischen DB-Client lautet: oracle:thin:kunde/p@localhost/XEPDB1
.
Dabei ist
kunde
der Benutzername,p
das Passwortlocalhost
aus Windows-Sicht der Rechnername- der Port defaultmäßig
1521
und XEPDB1
(XE Portable Database) der Name der Default-Datenbank nach dem 1. Start.
Zur Administration des Kubernetes-Clusters ist für Entwickler*innen m.E. Lens oder Octant von VMware Tanzu oder Kui von IBM gut geeignet.
In der Menüleiste am rechten Rand ist ein Auswahlmenü, in dem i.a. Application
zu sehen ist. In diesem Auswahlmenü wählt man den ersten Menüpunkt
Edit Configurations ...
aus.
Falls das Label Program Arguments nicht sichtbar ist, kann man es aktivieren, indem man auf Modify options klickt und im Abschnitt Java Program Arguments auswählt. Dann trägt man Folgendes ein:
--spring.output.ansi.enabled=ALWAYS --spring.config.location=classpath:/application.yml --spring.profiles.default=dev --spring.profiles.active=dev
Falls das Label Environment variables nicht sichtbar ist, kann man es aktivieren, indem man auf Modify options klickt und im Abschnitt Operating System auswählt. Dann trägt man folgenden String ein:
LOG_PATH=./build/log;APPLICATION_LOGLEVEL=trace;HIBERNATE_LOGLEVEL=debug
Wenn man für z.B. die Interaktion mit dem 2. Microservice "bestellung" TLS deaktivieren möchte, dann gibt man im Eingabefeld Program Arguments noch zusätzlich folgenden String ein:
--server.http2.enabled=false --server.ssl.enabled=false
Falls man den Port z.B. von 8080
auf 8081
beim Microservice "bestellung"
ändern möchte, dann ergänzt man außerdem noch --server.port=8081
.
In der Menüleiste am rechten Rand ist ein Auswahlmenü, in dem i.a. Application
zu sehen ist. In diesem Auswahlmenü wählt man den ersten Menüpunkt
Edit Configurations ...
aus.
Falls das Label Program Arguments nicht sichtbar ist, kann man es
aktivieren, indem man auf Modify options klickt und im Abschnitt Java
auswählt. Dann trägt man Folgendes ein:
--spring.output.ansi.enabled=ALWAYS --spring.config.location=classpath:/application.yml --spring.profiles.default=dev --spring.profiles.active=dev
Falls das Label Environment variables nicht sichtbar ist, kann man es
aktivieren, indem man auf Modify options klickt und im Abschnitt Operating System
auswählt. Dann trägt man die Variablen mit ihren Werten ein:
`LOG_PATH=./build/log;APPLICATION_LOGLEVEL=trace;HIBERNATE_LOGLEVEL=debug`
Nachdem das Port-Forwarding für den DB-Server aufgerufen wurde, kann man in einer
Powershell den Server mit dem Profil dev
starten:
.\gradlew bootRun
# MySQL statt PostgreSQL
.\gradlew bootRun -Ddb=mysql
# H2 statt PostgreSQL
.\gradlew bootRun -Ddb=h2
Mit <Strg>C
kann man den Server herunterfahren, weil in der Datei
application.yml
im Verzeichnis src\main\resources
graceful shutdown
konfiguriert ist.
Mit dem Kommando .\gradlew bootRun -Dport=8081
kann man den Server auf Port
8081
statt auf Port 8080
laufen lassen.
Mit dem Kommando .\gradlew bootRun -DnoTls=true
kann man den Server ohne TLS
laufen lassen. Das ist insbesondere dann notwendig, wenn ein 2. Server getestet
werden soll und dieser ohne TLS läuft.
Bei Verwendung der Buildpacks werden ggf. einige Archive von Github heruntergeladen,
wofür es leider kein Caching gibt. Ein solches Image kann mit dem Linux-User cnb
gestartet werden. Mit der Task bootBuildImage kann man im Verzeichnis für das
Projekt "bestellung" ebenfalls ein Docker-Image erstellen.
.\gradlew bootBuildImage -Dtag='2.0.0'
Mit dive kann man dann ein Docker-Image und die einzelnen Layer inspizieren:
cd \Zimmermann\dive
.\dive juergenzimmermann\kunde:2.0.0
Statt dive kann man auch das Tool Window Services von IntelliJ IDEA verwenden.
Wenn ein Docker-Image mit Buildpacks gebaut wurde, kann man mit folgendem Kommando inspizieren, mit welchen Software-Paketen es gebaut wurde:
pack inspect juergenzimmermann/kunde:2.0.0
Mit der PowerShell kann man Docker-Images folgendermaßen auflisten und löschen,
wobei das Unterkommando rmi
die Kurzform für image rm
ist:
docker images | sort
docker rmi myImage:myTag
Im Laufe der Zeit kann es immer wieder Images geben, bei denen der Name
und/oder das Tag <none>
ist, sodass das Image nicht mehr verwendbar und
deshalb nutzlos ist. Solche Images kann man mit dem nachfolgenden Kommando
herausfiltern und dann unter Verwendung ihrer Image-ID, z.B. 9dd7541706f0
löschen:
docker rmi 9dd7541706f0
Wenn das Image gebaut ist, kann man durch Docker Compose die Services für den DB-Server, den DB-Browser und den eigenen Microservice auf einmal starten. Dabei ist der Service kunde so konfiguriert, dass er erst dann gestartet wird, wenn der "healthcheck" des DB-Servers "ready" meldet.
docker compose up postgres pgadmin kunde
# oder MySQL statt PostgreSQL
docker compose up mysql phpmyadmin kunde
Wenn MySQL statt PostgreSQL verwendet wird, muss man zuvor in docker-compose.env
den Eintrag für die Umgebungsvariable SPRING_DATASOURCE_URL
für MySQL umstellen.
Außerdem muss man den Eintrag für die Umgebungsvariable SPRING_FLYWAY_TABLESPACE
auskommentieren.
Wenn H2 als Main Memory-Datenbank verwendet werden soll, so müssen in docker-compose.env
die Einträge für SPRING_DATASOURCE_...
und SPRING_FLYWAY_TABLESPACE
auskommentiert
und die initial auskommentieren Einträge für H2 aktiviert werden.
Wenn man auch noch FakeSMTP als Mailserver für die Entwicklung nutzen möchte, so muss auch noch der Service fakesmtp gestartet werden, z.B.
docker compose up postgres pgadmin fakestmp kunde
Im Verzeichnis extras\http-client
gibt es Dateien mit der Endung .http
, in
denen HTTP-Requests vordefiniert sind. Diese kann man mit verschiedenen
Umgebungen ("environment") ausführen, z.B. für https oder für http.
Zertifikate für TLS bzw. HTTPS werden in IntelliJ IDEA gespeichert und können über "File > Settings > Tools > Server Certificates" inspiziert werden. Siehe auch https://intellij-support.jetbrains.com/hc/en-us/articles/206544519-Directories-used-by-the-IDE-to-store-settings-caches-plugins-and-logs
Mit der URL https://localhost:8080/swagger-ui.html
kann man in einem
Webbrowser den RESTful Web Service über eine Weboberfläche nutzen, die
von Swagger auf der Basis von der Spezifikation OpenAPI generiert wurde.
Die Swagger JSON Datei kann man mit https://localhost:8080/v3/api-docs
abrufen.
Wenn der PostgreSQL-Server erfolgreich gestartet ist und das Port-Forwarding aktiv ist, können auch die Unit- und Integrationstests gestartet werden.
.\gradlew test
Falls der Server mit MySQL getestet werden soll, muss man -Ddb=mysql
ergänzen.
WICHTIGER Hinweis zu den Tests für den zweiten Microservice, der den ersten Microservice aufruft:
- Da die Tests direkt mit Windows laufen, muss Port-Forwarding für den aufzurufenden, ersten Microservice gestartet sein.
- Außerdem muss in
build.gradle.kts
innerhalb vontasks.test
der Name der UmgebungsvariableKUNDE_SERVICE_HOST
auf den Namen des eigenen ersten Microservice angepasst werden, z.B.SPORTVEREIN_SERVICE_HOST
.
Um das Testergebnis mit Allure zu inspizieren, ruft man einmalig
.\gradlew downloadAllure
auf. Fortan kann man den generierten Webauftritt mit
den Testergebnissen folgendermaßen aufrufen:
.\gradlew allureServe
Wenn man mit Kubernetes arbeitet, bedeutet das auch, dass man i.a. über TCP
kommuniziert. Deshalb sollte man überprüfen, ob in der Datei
C:\Windows\System32\drivers\etc\hosts
der eigene Rechnername mit seiner
IP-Adresse eingetragen ist. Zum Editieren dieser Datei sind Administrator-Rechte
notwendig.
Wenn die Anwendung in Kubernetes läuft, ist die Log-Datei application.log
im
Verzeichnis C:\Zimmermann\volumes\kunde-v2
. Das bedeutet auch zwangsläufig,
dass diese Datei durch den Linux-User vom (Kubernetes-) Pod angelegt und
geschrieben wird, wozu die erforderlichen Berechtigungen in Windows gegeben
sein müssen.
Wenn man z.B. die Anwendung zuerst mittels Cloud Native Buildpacks laufen
lässt, dann wird application.log
vom Linux-User cnb
erstellt.
Helm ist ein Package Manager für Kubernetes mit einem Template-Mechanismus auf der Basis von Go.
Zunächst muss man z.B. mit dem Gradle-Plugin von Spring Boot ein Docker-Image erstellen (s.o.).
Die Konfiguration für Helm ist im Unterverzeichnis extras\kunde
. Die
Metadaten für das Helm-Chart sind in der Default-Datei Chart.yaml
und die
einzelnen Manifest-Dateien für das Helm-Chart sind im Unterverzeichis
templates
im Format YAML. In diesen Dateien gibt es Platzhalter ("templates")
mit der Syntax der Programmiersprache Go. Die Defaultwerte für diese Platzhalter
sind in der Default-Datei values.yaml
und können beim Installieren durch weitere
YAML-Dateien überschrieben werden. Im unten stehenden Beispiel wird so ein
Helm-Service dem Release-Namen kunde mit dem Helm-Chart Chart.yaml
aus
dem aktuellen Verzeicnis in Kubernetes installiert. Dabei muss die Umgebungsvariable
HELM_NAMESPACE
auf den Wert acme
gesetzt sein.
# Ueberpruefen, ob die Umgebungsvariable HELM_NAMESPACE gesetzt ist:
Write-Output $env:HELM_NAMESPACE
cd extras\kunde
helm lint --strict .
helm-docs
# einfacher: helmfile oder Skaffold
helm install kunde . -f values.yaml -f dev.yaml
helm list
helm status kunde
# MySQL statt PostgreSQL:
helm install kunde . -f values.yaml -f dev.yaml -f dev-mysql.yaml
# H2 statt PostgreSQL:
helm install kunde . -f values.yaml -f dev.yaml -f dev-h2.yaml
Später kann das Helm-Chart mit dem Release-Namen kunde auch deinstalliert werden:
cd extras\kunde
helm uninstall kunde
helmfile apply
helm list
helm status kunde
kubectl describe svc/kunde -n acme
# in Lens: Network > Endpoints
kubectl get ep -n acme
.\port-forward.ps1
# Deinstallieren
helmfile destroy
Wenn MySQL statt PostgreSQL verwendet werden soll, muss man in der Datei
helmfile
in der Zeile mit dev-mysql.yaml
den Kommentar entfernen und die
andere Zeile mit values:
auskommentieren. Analog für H2 statt PostgreSQL.
Gegenüber Skaffold (s.u.) hat helmfile allerdings folgende Defizite:
- helmfile funktioniert nur mit Helm, aber nicht mit Kustomize, kubectl, kpt
- Continuous Deployment wird nicht unterstützt
- Die Konsole des Kubernetes-Pods sieht man nicht in der aufrufenden PowerShell.
- Port-Forwarding muss man selbst einrichten bzw. aufrufen
Um beim Entwickeln von localhost (und damit von außen) auf einen
Kubernetes-Service zuzugreifen, ist Port-Forwarding die einfachste
Möglichkeit, indem das nachfolgende Kommando für den installierten Service mit
Name kunde aufgerufen wird. Alternativ kann auch das Skript port-forward.ps1
aufgerufen werden.
kubectl port-forward service/kunde 8080 --namespace acme
Nach dem Port-Forwarding kann man auf den in Kubernetes laufenden Service zugreifen:
- HTTP Client von IntelliJ
- Cmdlet
Invoke-WebRequest
von PowerShell - cURL
Ein Ingress Controller ist zuständig für das Traffic Management bzw. Routing
der eingehenden Requests zu den Kubernetes Services. Ein solcher Ingress Controller
wurde durch extras\kunde\templates\ingress.yaml
installiert und kann von
außen z.B. folgendermaßen aufgerufen werden, falls der eigentliche Kommunikationsendpunkt
in Kubernetes verfügbar ist.
# ca. 2. Min. warten, bis der Endpoint bei kunde verfuegbar ist (in Lens: Network > Endpoints)
kubectl get ep -n acme
$secpasswd = ConvertTo-SecureString p -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential('admin', $secpasswd)
# GET-Request fuer REST-Schnittstelle mit Invoke-WebRequest:
$response = Invoke-WebRequest https://kubernetes.docker.internal/kunden/00000000-0000-0000-0000-000000000001 `
-Headers @{Accept = 'application/hal+json'} `
-SslProtocol Tls13 -HttpVersion 2 -SkipCertificateCheck `
-Authentication Basic -Credential $credential
Write-Output $response.RawContent
# GraphQL mit Invoke-WebRequest:
$response = Invoke-WebRequest https://kubernetes.docker.internal/kunden/graphql `
-Method Post -Body '{"query": "query { kunde(id: \"00000000-0000-0000-0000-000000000001\") { nachname } }"}' `
-ContentType 'application/json' `
-SslProtocol Tls13 -HttpVersion 2 -SkipCertificateCheck `
-Authentication Basic -Credential $credential
Write-Output $response.RawContent
# GET-Request fuer REST-Schnittstelle mit cURL:
curl --verbose --user admin:p --tlsv1.3 --http2 --insecure https://kubernetes.docker.internal/kunden/00000000-0000-0000-0000-000000000001
# GraphQL mit cURL:
curl --verbose --data '{"query": "query { kunde(id: \"00000000-0000-0000-0000-000000000001\") { nachname } }"}' `
--header 'Content-Type: application/json' `
--tlsv1.3 --insecure `
--user admin:p `
https://kubernetes.docker.internal/kunden/graphql
Skaffold ist ein Werkzeug, das den eigenen Quellcode beobachtet. Wenn Skaffold Änderungen festestellt, wird das Image automatisch neu gebaut und ein Redeployment in Kubernetes durchgeführt.
Um das Image mit dem Tag 2.0.0
zu bauen, muss die Umgebungsvariable TAG
auf
den Wert 2.0.0
gesetzt werden. Dabei ist auf die Großschreibung bei der
Umgebungsvariablen zu achten.
In skaffold.yaml
ist konfiguriert, dass das Image mit Cloud Native
Buildpacks gebaut wird.
Weiterhin gibt es in Skaffold die Möglichkeit, Profile zu definieren, um z.B.
verschiedene Werte bei der Installation mit Helm zu verwenden. Dazu ist in
skaffold.yaml beispielsweise konfiguriert, dass die Umgebungsvariable
SKAFFOLD_PROFILE
auf dev
gesetzt sein muss, um bei Helm zusätzlich die Datei
dev.yaml
zu verwenden.
Das Deployment wird mit Skaffold nun folgendermaßen durchgeführt und kann mit
<Strg>C
abgebrochen bzw. zurückgerollt werden:
$env:TAG = '2.0.0'
skaffold dev
helm list
helm status kunde
kubectl describe svc/kunde -n acme
# in Lens: Network > Endpoints
kubectl get ep -n acme
<Strg>C
skaffold delete
Bis das Port-Forwarding, das in skaffold.yaml
konfiguriert ist und nicht
manuell eingerichtet werden muss, auch ausgeführt wird, muss man ggf. ein
bisschen warten. Aufgrund der Einstellungen für Liveness und Readiness
kann es einige Minuten dauern, bis in der PowerShell angezeigt wird, dass die
Installation erfolgreich war. Mit Lens oder Octant kann man
jedoch die Log-Einträge inspizieren und so vorher sehen, ob die Installation
erfolgreich war. Sobald Port-Forwarding aktiv ist, sieht man in der PowerShell
auch die Konsole des gestarteten (Kubernetes-) Pods.
Außerdem generiert Skaffold noch ein SHA-Tag zusätzlich zu 2023.1.0
.
Das kann man mit docker images | sort
sehen. Von Zeit zu Zeit sollte man
mittels docker rmi <image:tag>
aufräumen.
Wenn man nun in IntelliJ IDEA den Quellcode des Microservice editiert und dieser durch IJ unmittelbar übersetzt wird, dann überwacht dabei Skaffold die Quellcode-Dateien, baut ein neues Image und führt einen neuen Deployment-Vorgang aus. Deshalb spricht man von Continuous Deployment.
Mit kubectl top pods -n acme
kann man sich die CPU- und RAM-Belegung der Pods
anzeigen lassen. Ausgehend von diesen Werten kann man resources.requests
und
resources.limits
in dev.yaml
ggf. anpassen. Voraussetzung für kubectl top
ist, dass der metrics-server
für Kubernetes im Namespace kube-system
installiert wurde.
Ob Best Practices bei der Installation eingehalten wurden, kann man mit
Polaris überprüfen. Um den Aufruf zu vereinfachen, gibt es im Unterverzeichnis
extras\kubernetes
das Skript polaris.ps1
:
cd extras\kubernetes
.\polaris.ps1
Nun kann Polaris in einem Webbrowser mit der URL http://localhost:8008
aufgerufen werden.
Eine statische Codeanalyse ist durch die beiden Werkzeuge ktlint und Detekt möglich, indem man die folgenden Gradle-Tasks aufruft:
.\gradlew ktlint detektMain detektTest
Für eine statische Codeanalyse durch SonarQube muss zunächst der SonarQube-Server mit Docker Compose als Docker-Container gestartet werden:
cd extras\sonarqube
docker compose up
Wenn der Server zum ersten Mal gestartet wird, ruft man in einem Webbrowser die
URL http://localhost:9000
auf. In der Startseite muss man sich einloggen und
verwendet dazu als Loginname admin
und ebenso als Password admin
. Danach
wird man weitergeleitet, um das initiale Passwort zu ändern. Das neue Passwort
trägt man dann in das Skript sonar-scanner.ps1
im Wurzelverzeichnis ein.
Zur Konfiguration für künftige Aufrufe des SonarQube-Scanners trägt man jetzt
noch in der Konfigurationsdatei sonar-project.properties
den Projektnamen beim
der Property sonar.projectKey
ein.
Nachdem der Server gestartet ist, wird der SonarQube-Scanner in einer zweiten
PowerShell mit dem Skript sonar-scanner.ps1
gestartet. Das Resultat kann dann
in der Webseite des zuvor gestarteten Servers über die URL http://localhost:9000
inspiziert werden.
Abschließend wird der oben gestartete Server heruntergefahren.
cd extras\sonarqube
docker compose down
Eine HTML- und PDF-Dokumentation aus AsciiDoctor-Dateien, die ggf. UML-Diagramme mit PlantUML enthalten, wird durch folgende Gradle-Tasks erstellt:
.\gradlew asciidoctor asciidoctorPdf
Eine API-Dokumentation in Form von HTML-Seiten kann man durch das Gradle-Plugin javadoc erstellen:
.\gradlew javadoc
Fortio als Werkzeug für Lasttests ist als eigenständiges Projekt aus Istio hervorgegangen.
In docker-compose.env
kommentiert man die folgenden Einträge aus, um keine unnötig teuren
Protokollausgaben in der Konsole zu erhalten, die sowieso nur für einen Entwicklungsrechner gedacht sind.
- REQUEST_RESPONSE_LOGLEVEL
- HIBERNATE_LOGLEVEL
- FLYWAY_LOGLEVEL
- APPLICATION_LOGLEVEL
Nun kann man den Fortio-Server in einer weiteren PowerShell starten:
cd extras
.\fortio.ps1
Jetzt ruft man in einem Webbrowser die URL http://localhost:8088/fortio
auf. Dort kann man
einen einfachen Lasttest konfigurieren, indem man die Beispielwerte eingibt, die beim Skript
fortio.ps1
ausgegeben wurden. Bevor man auf den Button Start
klickt, um den einfachen
Lasttest zu starten, empfiehlt es sich, vorab zumindest einen HTTP-Request abzuschicken,
weil man sonst den Lasttest nach einem "Kaltstart" durchführt.
Alternative und populäre Werkzeuge für Lasttests sind:
- Locust von https://github.com/locustio/locust: Skripte werden in Python implementiert
- k6 aus dem Projekt Grafana https://github.com/grafana/k6: Skripte werden in JavaScript implementiert
- ab aus dem Apache-Projekt httpd: https://httpd.apache.org/docs/current/programs/ab.html
- Apache JMeter https://jmeter.apache.org
- hey: Go-Umgebung erforderlich
- The Grinder von https://grinder.sourceforge.net: Skripte werden in Jython implementiert
- wrk von https://github.com/wg/wrk: Skripte werden in Lua implementiert