Commit fe7ce7b0 authored by Nane Kratzke's avatar Nane Kratzke
Browse files

IN-memory

parent 78b331ac
Pipeline #21561 passed with stages
in 1 minute and 12 seconds
variables:
KUBECTL: "quay.io/bitnami/kubectl:1.18"
PRIME: "yes"
CACHE: "no" # one of "no", "in-memory", "persistent"
TERMINATE: "yes"
CACHE: "in-memory" # one of "no", "in-memory", "persistent"
TERMINATE: "no"
stages:
- prepare
......
......@@ -43,8 +43,6 @@ Ingress --- Prime Service ---|- Prime Pod -|--- Redis Service --- Redis Pod
- [Vorbereitung](#vorbereitung)
- [Übung 01: Deployment eines Prime Service](#übung-01-deployment-eines-prime-service)
- [Übung 02: Ergänzung eines In-Memory Caches](#übung-02-ergänzung-eines-in-memory-caches)
- [Übung 03: Erweiterung zu einem persistentem Cache](#übung-03-erweiterung-zu-einem-persistentem-cache)
- [Übung 04: Skalierung und Chaos Engineering](#übung-04-skalierung-und-chaos-engineering)
- [Übung 05: Terminieren Sie das Deployment](#übung-05-terminieren-sie-das-deployment)
- [Übung 06: Deployment des Prime Service in GKE](#übung-06-deployment-des-prime-service-in-gke)
- [Links](#links)
......@@ -142,28 +140,70 @@ Gratulation! Sie haben Ihren ersten lastausgleichenden Dienst in Kubernetes depl
## Übung 02: Ergänzung eines In-Memory Caches
Unsere Pods bestimmen aktuell für jede Zahl, ob es sich dabei um eine Primzahl handelt oder nicht. Werden Zahl wiederholt geprüft, wäre es effizienter, sich dieses Ergebnis zu speichern. Pods sollten jedoch grundsätzlich stateless designed werden (d.h. sich nichts speichern), damit diese einfach horizontal skaliert werden können.
Man kann dies machen, in dem man Zustände in statefull Komponenten isoliert (und versucht, diese möglichst nicht zu skalieren, denn stateful Komponenten zu skalieren ist komplex und aufwändig, sie haben eine ganzes Modul, was sich im Kern nur um dieses Problem dreht => Verteilte Datenbanken).
Wir schalten daher nun zu unserem Prime-Service einen In-Memory Redis Cache dazu (siehe Einleitung oben). Dieser Cache ist (erst einmal) ebenso stateless, speichert sich Primzahleigenschaften zu Zahlen also nicht dauerhaft, aber isoliert von den Primzahleigenschaft-prüfenden Pods. Ein Pod fragt also erst den Cache ab (geht schnell). Falls der Cache nicht antwortet, beantwortet der Pod die Anfrage selber, andernfalls liefert er das Cache-Ergebnis zurück.
1. Setzen Sie in `.gitlab-ci.yml` die Umgebungsvariablen wie folgt:
```yaml
PRIME: "yes"
CACHE: "in-memory"
TERMINATE: "no"
```
2. Committen Sie in den Master-Branch. Und warten Sie bis die Pipeline erfolgreich beendet wurde.
3. Rufen Sie nun den Dienst in ihrem Browser auf [https://prime-XYZ.loki.th-luebeck.dev/prime/12345](https://prime-XYZ.loki.th-luebeck.dev/prime/12345) (ersetzen Sie XYZ dabei durch die Ihre User-ID in GitLab, siehe Übung 01).
```text
12345 is not a prime number. It can be divided by 3 (answer from prime-deployment-b667868f6-b2krp; processed)
```
Laden Sie die Seite mehrmals erneut. Sie werden feststellen, dass die Antwort jedesmal von einem anderen Pod beantwortet wird. Die Requests werden Round-Robin über alle Prime-Pods verteilt.
Ab dem zweiten Aufruf sehen Sie aber `via cache`. Die Pods finden bereits berechnete Zahlen also im externen Cache und müssen diese nicht selber errechnen.
## Übung 03: Erweiterung zu einem persistentem Cache
In Übung 02 haben wir gesehen, dass wenn der Cache neu gestartet wird, wir viele Informationen verlieren und die Prime-Pods viele Zahlen neu durchrechnen müssen (und dabei den Cache neu aufbauen).
Besser wäre es, wenn wir den Cache über Pod-Restarts behalten können. Dies kann man in Kubernetes mittels Volumes machen. Volumes ermöglichen es, einen Zustand (auf einer Festplatte) unabhängig von einem flüchtigen Pod zu speichern.
## Übung 04: Skalierung und Chaos Engineering
**Skalieren:**
- Klicken Sie auf `Workloads -> Deployments` und selektieren Sie `prime-deployment -> Edit` und ändern Sie das Feld `spec.replicas` erst von 5 auf 8 und dann von 8 auf 3 (jeweils mit `Save` speichern).
- Sie sehen dann, wie die Pods des Deployments automatisch gestartet bzw. terminiert werden. Auf diese Weise lassen sich also Dienste einfach horizontal skalieren.
- Skalieren Sie Ihre Prime-Pods bis auf 30 Replicas! (Es sollten 30 Pods erzeugt werden).
- Skalieren Sie Ihre Prime-Deployment bis auf 40 Replicas! (es sollten nur max. 32 Pods erzeugt worden sein, da dann Ihr CPU Quota von 8 CPUs pro Namespace aufgebraucht ist!)
- Skalieren Sie Ihre Prime-Deployment bitte wieder auf 5 Replicas (das reicht vollkommen aus!)
**Chaos Engineering:**
Machen Sie sich ein wenig über [Chaos Engineering](https://en.wikipedia.org/wiki/Chaos_engineering) schlau. Es gibt sogar ein [Helm](https://helm.sh) Chart für Kubernetes namens [Kube-Monkey](https://www.padok.fr/en/blog/kube-monkey-kubernetes). Sie können das ja mal in ihren eigenen Projekten versuchen einzusetzen. Chaos Engineering geht aber auch ganz einfach manuell.
1. Setzen Sie in `.gitlab-ci.yml` die Umgebungsvariablen wie folgt:
```yaml
PRIME: "yes"
CACHE: "persistent"
TERMINATE: "no"
```
2. Committen Sie in den Master-Branch. Und warten Sie bis die Pipeline erfolgreich beendet wurde.
3. Starten Sie Lens und öffnen Sie `Workload -> Pods`.
4. Selektieren Sie nun willkürlich ein paar Prime Pods und wenn Sie wollen auch den Redis Pod (dieser ist für die Persistenz verantwortlich). Klicken Sie dann auf Minus (-) und löschen Sie die Pods.
5. Fragen Sie nun den Dienst während dieser "Ausfälle" über den Browser ab. Sie werden sehen, dass Sie weiterhin Antworten erhalten und die Pods von Kubernetes eigenständig wieder gestartet werden bis die definierte Replica-Anzahl wieder erreicht wurde. Ggf. ist währenddessen kurzfristig der Cache nicht erreichbar. Im echten Leben, würde die Performance nun etwas einbrechen. Das war es aber auch schon.
6. Machen Sie nun den absoluten **Stresstest**. Selektieren Sie alle **Pods**. Terminieren Sie anschließend alle **Pods**. Und Fragen Sie erneut mit dem Browser den Dienst ab. Nun kann es kurzfristig passieren, dass Sie ein paar 500er HTTP Status Codes erhalten. Ihr Service fängt sich aber nach ein paar Sekunden wieder.
Dieses Verhalten nennen wir **resilient** (Störungen tolerierend, für Störung unanfällig).
## Übung 05: Terminieren Sie das Deployment
1. Löschen Sie bitte Ihr Deployment in dem Sie in Ihrer `.gitlab-ci.yml` die Variable `TERMINATE` auf `"yes"` setzen.
2. Committen Sie bitte in den Master-Branch.
Prüfen Sie in Lens mittels
2. Committen Sie diese Änderung bitte in den Master-Branch. Prüfen Sie im Lens-Terminal mittels
```bash
kubectl get all
kubectl get ing
```
das alle Ressourcen sauber gelöscht wurden.
das alle Ressourcen sauber gelöscht wurden. Das Terminieren kann ggf. etwas dauern.
## Übung 06: Deployment des Prime Service in GKE
......@@ -172,7 +212,22 @@ In diesem Schritt passen wir das in den Übungen 1 bis 3 entwickelte Deployment
## Links
- [Lens](https://k8slens.io)
- [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)
- [Service](https://kubernetes.io/docs/concepts/services-networking/service/)
- [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
- [Persitent Volume Claim (PVC)](https://kubernetes.io/docs/concepts/storage/persistent-volumes)
- [Flask](https://palletsprojects.com/p/flask/)
- [Redis](https://redis.io)
- [KubeMonkey](https://www.padok.fr/en/blog/kube-monkey-kubernetes)
- [Helm](https://helm.sh)
## Was sollten Sie mitnehmen?
-
\ No newline at end of file
- Deployment Pipelines können durchaus komplex werden.
- Deployment Pipelines lassen sich mittels Umgebungsvariablen steuern (z.B. kann man unterschiedliche Ausbaustufen eines Dienstes definieren und für unterschiedliche Environments ausbringen).
- Deployment Controller sorgen in Kubernetes dafür das Pods kontinuierlich überwacht werden und Pods oberhalb eines Replica-Wertes gelöscht und unterhalb eines Replica-Wertes neu gestartet werden.
- Diese horizontale Skalierbarkeit von Pods ermöglicht so einerseits Lastausgleich und andererseits Fehlerresilienz falls Pods "abstürzen" oder einzelne Pods nicht mehr reagieren.
- Ein typisches Deployment Pattern für einen in Kubernetes gehosteten Dienst sieht wie folgt aus: `Ingress -> Service -> Pod(s) <- Deployment`.
- Dienste sollten stateless designed werden. Ist ein State erforderlich, so sollte dieser Zustand in einem Statefull Service isoliert werden (z.B. mittels Redis). Auf diese Weise kann der Zustand auch einfach über mehrere horizontal skalierende Pods geteilt werden.
- Ist der zu verwaltende Zustand sehr groß (d.h. nicht mehr sinnvoll auf einem Host vorhaltbar), bieten sich ggf. verteilte Datenbanksysteme an (mehr dazu im Modul "Verteilte Datenbank und Informationssysteme").
- Chaos Engineering ist eine Möglichkeit die Failure-Rate sogar in Produktivumgebungen künstlich zu erhöhen und DevOps Teams so von Anfang an zu zwingen, resiliente Systeme zu entwerfen und die Resilienz kontinuierlich auch im Produktivsystem zu überprüfen.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment