kubernetes
This commit is contained in:
parent
76822e7086
commit
d5cf26d6b9
@ -3,5 +3,206 @@ gitea: none
|
|||||||
include_toc: true
|
include_toc: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# Kubernetes
|
# Kubernetes (K8s)
|
||||||
|
|
||||||
|
Gutes Erklär-Video: https://www.youtube.com/watch?v=1SaPfm96lY4
|
||||||
|
|
||||||
|
## Nodes
|
||||||
|
|
||||||
|
Ein Kubernetes Cluster besteht aus verschiedenen Servern, die __Nodes__ genannt werden. Es gibt 2 verschiedene Arten von Nodes:
|
||||||
|
|
||||||
|
- Control Pane Nodes
|
||||||
|
Für Überwachung, Steuerung, Arbeit im Cluster verteilen. Anzahl: Es genügt theoretisch 1, normalerweise aber für Redundanz mindestens 2. Für Entscheidungen braucht es eine Mehrheit, also 3 oder 5 Control Pane Nodes.
|
||||||
|
- Worker Nodes
|
||||||
|
Anzahl ist variabel. Wenige bis tausende Worker Nodes.
|
||||||
|
|
||||||
|
## Kubernetes Cluster aufsetzen
|
||||||
|
|
||||||
|
- Manueller Aufbau
|
||||||
|
- Aufbau tool-gestützt. Z.B. mit KOPS
|
||||||
|
- Managed-Cluster, z.B. von AWS, Azure, Digital Ocean (Preise vergleichen!)
|
||||||
|
|
||||||
|
Für eine Verbindung mit dem Cluster braucht es das Cube Control Tool __kubectl__, das man unter https://kubernetes.io/docs/tasks/tools/ herunterladen kann.
|
||||||
|
|
||||||
|
Bei Managed Cluster kann ein configuration file heruntergeladen werden. Dieses Yaml File sollte standardmässig als `~/.kube/config` abgelegt werden.
|
||||||
|
|
||||||
|
## Anzeigen aller Worker Nodes
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl get nodes
|
||||||
|
|
||||||
|
# Mehr Ausgabe (IPs, OS, Kernel-Version etc.):
|
||||||
|
kubectl get nodes -o wide
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deklarativer Ansatz vs. Imperativer Ansatz
|
||||||
|
|
||||||
|
Namespaces könnten über `kubectl` erstellt werden. Beispiele:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Namespace erstellen:
|
||||||
|
kubectl create namespace roger
|
||||||
|
|
||||||
|
# Namespace entfernen:
|
||||||
|
kubectl delete namespace roger
|
||||||
|
```
|
||||||
|
|
||||||
|
__Dieser imperative Ansatz sollte vermieden werden.__
|
||||||
|
|
||||||
|
Stattdessen folgt Kubernetes einem __deklarativen Ansatz__. Man beschreibt wie das System aussehen soll, und was gemacht werden soll um zu diesem Ziel zu kommen, entscheidet Kubernetes selbst. Diese Beschreibung wird in einem __Manifest__ gemacht. Die Control Pane Nodes gleichen dann den Soll-Zustand aus dem Manifest mit dem Ist-Zustand ab und richten alle nötigen Sachen selber ein, wie zum Beispiel Namespaces einrichten, um zum Soll-Zustand zu gelangen. Die Überwachung erfolgt laufend, während des Betriebs, sodass die Umgebung ständig angepasst wird, wenn sich im Manifest etwas ändert.
|
||||||
|
|
||||||
|
## Manifest
|
||||||
|
|
||||||
|
Ein Manifest wird in einer YAML Datei Beschrieben. Mit `kind` wird der Typ angegeben.
|
||||||
|
|
||||||
|
Manifest anwenden:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl apply -f ein-manifest.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Manifest deaktivieren:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl delete -f ein-manifest.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Der `name` eines Manifests sollte nicht mehr verändert werden. Falls doch, wird der Zustand des Namespaces nicht aktualisiert, sondern es wird ein neuer erstellt, weil es als __neues Manifest__ angesehen wird.
|
||||||
|
|
||||||
|
### Labels und Annotations
|
||||||
|
|
||||||
|
- `labels` für maschinenlesbare Beschreibungen (Buchstaben, Zahlen, -, _)
|
||||||
|
- `annotations` für menschenlesbare Beschreibungen
|
||||||
|
|
||||||
|
Beispiel:
|
||||||
|
|
||||||
|
```
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: roger
|
||||||
|
labels:
|
||||||
|
author: roger-rutishauser
|
||||||
|
annotations:
|
||||||
|
author: Roger Rutishauser <roger.rutishauser@uzh.ch> und sonst ein beliebiger Text
|
||||||
|
```
|
||||||
|
|
||||||
|
## Resource Type Namespace
|
||||||
|
|
||||||
|
Ein Namespace ist ein abgegrenzter Bereich, dem man einem Anwender oder eine Applikation zuweisen kann.
|
||||||
|
|
||||||
|
```
|
||||||
|
# Namespaces anzeigen lassen
|
||||||
|
# Die 3 Namespaces beginnend mit `kube-` sollten nicht verwendet werden. Auch den default Namespace nicht.
|
||||||
|
kubectl get namespaces
|
||||||
|
|
||||||
|
# Namespace erstellen:
|
||||||
|
kubectl create namespace roger
|
||||||
|
|
||||||
|
# Namespace entfernen:
|
||||||
|
kubectl delete namespace roger
|
||||||
|
|
||||||
|
# Einen Namespace im Detail anzeigen
|
||||||
|
kubectl describe namespace roger
|
||||||
|
```
|
||||||
|
|
||||||
|
Aber wie wir ja nun wissen, sollten Namespaces auch über ein Manifest erstellt werden. Ein Manifest für einen Namespace würde so aussehen:
|
||||||
|
|
||||||
|
```
|
||||||
|
# namespace.yaml
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: roger
|
||||||
|
# etc...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Resource Type Deployment und Pod
|
||||||
|
|
||||||
|
In Kubernetes gibt es für die Container ein Wrapper, die Pods. Normalerweise 1 Pod für 1 Container. Sog. Sidecar-Container können auch im gleichen Pod wie der Hauptcontainer liegen. Man kann sich ein Pod wie eine VM vorstellen, ein logischer Server. Hat eine eigene IP Adresse.
|
||||||
|
|
||||||
|
Er ist nicht zuständig für das Lifecycle Management der darin enthaltenen Container zuständig. Wenn ein Container stoppt, stoppt auch der Pod. Für das Lifecycle Managmenet ist das Deployment zuständig. Es überwacht den Pod, kann ihn bei Bedarf neu starten, oder mehrere Instanzen des Pods starten (Skalierung).
|
||||||
|
|
||||||
|
Häufig werden Pods und Deployment zusammen in einem Manifest beschrieben.
|
||||||
|
|
||||||
|
Beispiel für "Hallo Welt" Webserver:
|
||||||
|
|
||||||
|
``` yaml
|
||||||
|
# Manifest: hallo-welt.yaml
|
||||||
|
|
||||||
|
# ----- Deployment-Teil
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: deployment-hallo-welt
|
||||||
|
namespace: roger
|
||||||
|
annotations:
|
||||||
|
author: Roger Rutishauser
|
||||||
|
# ----- Pod-Teil
|
||||||
|
spec:
|
||||||
|
# ----- Anzahl der Pod-Replikate (Default ist 1)
|
||||||
|
replicas: 1
|
||||||
|
# ----- Selector, um die Pods zu finden, die von diesem Deployment gemanagt werden sollen.
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: hallo-welt # entspricht dem label vom Pod.
|
||||||
|
# ----- Template für den Pod. Weil es an dieser Stelle immer ein Pod ist, muss nicht explizit "kind: Pod" angegeben werden.
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: hallo-welt # key "app" ist frei wählbar
|
||||||
|
annotations:
|
||||||
|
author: Roger Rutishauser
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: pod-hallo-welt # muss nicht gleich lauten wie das deployment
|
||||||
|
image: repository.example.com/hello-world:latest
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 3000
|
||||||
|
```
|
||||||
|
|
||||||
|
### Was ist ein Container im K8s-Umfeld?
|
||||||
|
|
||||||
|
In Kubernetes ist ein Container-Image im Format der Open Container Initiative (OCI) spezifiziert – und Docker-Images sind eine konkrete Umsetzung dieser Spezifikation. Wenn Du also `image: repository.example.com/hello-world:latest` angibst, beziehst Du Dich auf ein __OCI-kompatibles Image__, das häufig über die Docker-Registry-API ausgeliefert wird.
|
||||||
|
|
||||||
|
Allerdings läuft dieses Image in Kubernetes typischerweise nicht über den Docker-Daemon, sondern über eine CRI-Runtime wie __containerd__ oder __CRI-O__. Es ist also kein "Docker-Container" im klassischen Sinne (den Du mit `docker run` gestartet hättest), sondern ein OCI-Image, das von Kubernetes' Container-Runtime gemanagt wird.
|
||||||
|
|
||||||
|
Du kannst das Image allerdings lokal mit Docker bauen und in die Registry pushen – beim Ausrollen in Kubernetes wird es dann von der CRI-Runtime geholt und gestartet.
|
||||||
|
|
||||||
|
### Pods und deren Status anzeigen:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl get pods --namespace roger
|
||||||
|
|
||||||
|
# oder
|
||||||
|
kubectl get pods --all-namespaces
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pod Details anzeigen
|
||||||
|
|
||||||
|
So sieht man beispielsweise, wie die IP und der Port des Pods lautet.
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl describe pod pod-hallo-welt-1234dsdpwqo-4shmp --namespace roger
|
||||||
|
```
|
||||||
|
|
||||||
|
## Was ist Helm?
|
||||||
|
|
||||||
|
Helm ist ein Paketmanager für Kubernetes – ähnlich wie apt für Ubuntu oder yum für CentOS, nur eben speziell für Kubernetes-Ressourcen.
|
||||||
|
|
||||||
|
### Was ist ein Helm Chart?
|
||||||
|
|
||||||
|
Ein Helm Chart ist ein Bündel von YAML-Dateien (plus optional Vorlagen/Parameter), das die Definitionen aller Ressourcen enthält, die für eine bestimmte Anwendung oder einen Service auf Kubernetes nötig sind.
|
||||||
|
|
||||||
|
Beispiel: Ein Helm Chart für WordPress enthält alles, was WordPress braucht: Deployment, Service, eventuell Persistent Volume Claims, Konfigurationen usw.
|
||||||
|
|
||||||
|
Man kann sich ein Helm Chart wie ein Installationspaket vorstellen, das man auf einem Kubernetes-Cluster "installiert".
|
||||||
|
|
||||||
|
- Ein Chart ist ein Ordner mit Dateien, der beschreibt, was und wie etwas in Kubernetes deployed wird (z.B. Deployments, Services, Ingress, ConfigMaps, etc.).
|
||||||
|
- Charts sind versioniert und wiederverwendbar – sie können einfach angepasst (z.B. über Werte in einer values.yaml) und auf mehreren Clustern/Umgebungen installiert werden.
|
||||||
|
- Helm sorgt für das Templating: Man kann Variablen in den YAML-Dateien verwenden (Platzhalter), sodass ein Chart flexibel konfigurierbar ist.
|
||||||
|
- Mit helm install installierst du ein Chart als Release auf deinem Cluster.
|
||||||
|
- Mit helm upgrade und helm rollback kannst du Deployments einfach aktualisieren oder zurücksetzen.
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user