add synced notes on IT know how

This commit is contained in:
Mathias Schneider
2026-03-17 19:01:50 +01:00
parent b8797d5ca8
commit fc3aef4da8
31 changed files with 13162 additions and 1 deletions
@@ -0,0 +1,358 @@
Hier ist eine umfassende Einführung in Argo CD verständlich, aber fachlich fundiert.
---
## 1. Was ist Argo CD?
Argo CD ist ein **GitOps-Tool** für **Kubernetes**. Es sorgt dafür, dass der Zustand eines Kubernetes-Clusters immer mit dem übereinstimmt, was in einem **Git-Repository** als „Wahrheit“ definiert ist.
Kerneigenschaften:
- **Git-zentriert**: Git als Single Source of Truth (Manifest-Dateien, Helm-Charts, Kustomize, etc.)
- **Deklarativ**: Der gewünschte Zustand (desired state) ist beschrieben, nicht programmiert
- **Kontinuierliche Synchronisierung**: Änderungen in Git werden automatisch oder manuell im Cluster ausgerollt
- **Visuell**: Web UI mit Übersicht über Applikationen, Health-Status, Diffs, History
- **Mehrcluster-fähig**: Kann mehrere Kubernetes-Cluster verwalten
---
## 2. GitOps der Kontext von Argo CD
Argo CD implementiert das GitOps-Konzept:
- **Infrastruktur & Deployments im Git** (Manifest-Dateien, Helm Values, Kustomize Overlays, etc.)
- **Pull-basiert**: Argo CD „zieht“ den Zustand regelmäßig aus Git und gleicht ihn mit dem Cluster ab.
- **Versioniert & auditiert**: Jede Änderung ist ein Git-Commit, inkl. History, Review, Rollback-Möglichkeit
- **Automatisierte Drift-Erkennung**: Unterschiede zwischen Git und Cluster werden erkannt und gemeldet
Vorteile von GitOps mit Argo CD:
- Reproduzierbare Deployments
- Besseres Change-Management (Git-Workflows, PRs)
- Weniger manuelle „[[kubectl]] apply“-Befehle
- Klare Trennung von Build (CI) und Deployment (CD)
---
## 3. Architektur von Argo CD
### 3.1 Hauptkomponenten
- **argocd-server**
- Stellt die Web UI und das gRPC/REST-API bereit
- Authentifizierung (lokale User, SSO via OIDC, etc.)
- Kommunikation mit CLI (`argocd` CLI) und UI
- **argocd-repo-server**
- Greift auf Git-Repositories zu
- Rendert Manifeste (z.B. Helm, Kustomize, Jsonnet)
- Führt Template-Engines und „Config Management Plugins“ aus
- **argocd-application-controller**
- Herzstück des Sync-Mechanismus
- Vergleicht desired state (Git) mit live state (Cluster)
- Führt Syncs, Health-Checks und Rollbacks aus
- **argocd-redis** (optional, in vielen Installationen vorhanden)
- Cache für Repositories und Application-Informationen
Diese Komponenten laufen typischerweise im Namespace `argocd` im Cluster.
### 3.2 Target Cluster
Argo CD kann:
- Den **Cluster, in dem es selbst läuft**, verwalten
- **Externe Cluster** (z.B. Staging, Prod) als zusätzliche „Cluster Secrets“ anbinden
---
## 4. Zentrale Konzepte
### 4.1 Application
Die zentrale Ressource in Argo CD ist eine CRD namens **Application** (`kind: Application`).
Eine Application beschreibt:
- **Quelle (source)**: Woher kommen die Manifeste?
- Git-Repository / Helm-Repo / Kustomize-Ordner
- Pfad im Repo
- ggf. Helm-Chart und Values
- **Ziel (destination)**:
- Zu verwaltender Kubernetes-Cluster
- Ziel-Namespace
- **Sync-Strategie & -Optionen**:
- Automatische Synchronisierung (auto sync) oder manuell
- Verhalten bei Fehlern, Prune, Self-Heal etc.
Ein minimaler `Application`-Beispiel (vereinfachtes YAML):
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/mein-org/mein-repo.git
targetRevision: main
path: kubernetes/my-app
destination:
server: https://kubernetes.default.svc
namespace: my-app
syncPolicy:
automated:
prune: true
selfHeal: true
```
### 4.2 Sync-Status & Health-Status
Für jede Application zeigt Argo CD zwei wesentliche Zustände:
- **Sync-Status**:
- `Synced`: Cluster-Zustand entspricht Git-Zustand
- `OutOfSync`: Unterschiede zwischen Git und Cluster
- **Health-Status**:
- `Healthy`: Anwendung läuft wie erwartet (z.B. alle Pods bereit)
- `Degraded`: Fehlerzustände (CrashLoop, fehlende Ressourcen etc.)
- `Progressing`: Deployment läuft noch, noch nicht stabil
Health-Checks sind ressourcentyp-spezifisch (Deployments, StatefulSets, CRDs etc.).
### 4.3 Drift-Erkennung
Argo CD vergleicht:
- **Desired state**: Manifeste, die aus Git gerendert wurden
- **Live state**: Tatsächliche Ressourcen im Cluster
Wenn jemand manuell `kubectl apply` oder `kubectl edit` verwendet, entsteht „Drift“. Argo CD:
- Markiert den Status als `OutOfSync`
- Kann bei `selfHeal: true` diese Änderungen automatisch wieder rückgängig machen (zurück auf Git-Zustand)
---
## 5. Unterstützte Werkzeuge & Formate
Argo CD unterstützt u.a.:
- **Plain YAML-Manifeste**
- **Helm** (Charts, Values)
- **Kustomize**
- **Jsonnet**
- **Ksonnet (legacy)**
Außerdem:
- **Config Management Plugins (CMP)**: Eigene Tools/Pipelines zum Manifest-Rendering integrierbar
- **Multiple Sources**: Neuere Versionen unterstützen mehrere Quellen pro Application (z.B. App-Manifeste + separate Helm-Values)
---
## 6. Installation & erste Schritte
### 6.1 Installation
Typische Wege:
- **kubectl apply** eines offiziellen Install-Manifests:
- z.B. `https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml`
- **Helm-Chart** (empfohlen für produktivere Setups)
- **Operator-Lösungen** in manchen Distributionen
Nach der Installation:
- Argo CD läuft im Namespace `argocd`
- UI via `argocd-server` (LoadBalancer, Ingress oder Port-Forward)
- Erstlogin meist über das Passwort aus dem `argocd-initial-admin-secret`
### 6.2 CLI
Das CLI-Tool `argocd` erlaubt:
- Login: `argocd login <server>`
- Erstellung von Applications: `argocd app create ...`
- Manuelles Syncen: `argocd app sync my-app`
- Status anzeigen, Diffs, Rollbacks etc.
---
## 7. Deployment-Strategien & Sync-Policies
### 7.1 Manuelles vs. automatisches Syncen
- **Manuell**:
- Änderungen in Git werden erkannt, aber nur als `OutOfSync` markiert
- Deploy erfolgt erst nach `argocd app sync` (CLI/UI)
- **Automatisch (auto sync)**:
- Argo CD führt bei Änderungen in Git automatisch ein Sync aus
- Option `prune` entfernt Ressourcen, die in Git gelöscht wurden
- Option `selfHeal` korrigiert Drift im Cluster
### 7.2 Sync-Optionen
- **Sync-Wellen (Sync Waves)**:
- Steuerung der Reihenfolge via `argocd.argoproj.io/sync-wave` Annotation
- **Sync-Hooks**:
- Vor-/Nachschaltbare Hooks (`PreSync`, `PostSync`, `SyncFail` etc.)
- Realisiert mit bestimmten Kubernetes-Resourcen und Annotationen
---
## 8. Projekte (AppProjects) & Multi-Tenancy
Die CRD **AppProject** erlaubt die logische Gruppierung und Begrenzung von Applications.
Funktionen von AppProjects:
- Einschränkung von:
- Erlaubten Git-Repositories
- Erlaubten Ziel-Cluster / Namespaces
- Erlaubten Ressourcentypen
- Gemeinsame Policies & RBAC für eine Gruppe von Apps
- Sinnvoll für **Multi-Tenancy**:
- z.B. ein Project pro Team, Produkt oder Mandant
---
## 9. Sicherheit & RBAC
### 9.1 Authentifizierung
- Lokale Benutzer in Argo CD (Admin, weitere User)
- Single Sign-On via:
- OIDC (z.B. Keycloak, Dex, Azure AD, Okta)
- SAML (über OIDC-Integrationen)
- Tokens für Automatisierung (CI-Systeme, Bots)
### 9.2 Autorisierung (RBAC)
Argo CD hat ein eigenes RBAC-System:
- Rollen (z.B. `role:readonly`, `role:admin`, benutzerdefinierte Rollen)
- Zuordnung von Rollen zu Subjekten (User, Gruppen)
- Rechte auf:
- Anwendungen (lesen, syncen, löschen)
- Projekte
- Cluster, Repos
- Granulare Steuerung:
- z.B. „Team A darf nur Apps in Project X syncen“
---
## 10. Typische Patterns: App-of-Apps & Monorepo/Multirepo
### 10.1 App-of-Apps Pattern
Ein häufiges Muster ist die **„Application of Applications“**:
- Eine „Root-Application“, deren Manifeste nur aus anderen `Application`-Ressourcen bestehen
- Diese Root-App definiert alle anderen Applikationen/Umgebungen
- Vorteile:
- Zentrales Entry-Point
- Environments (dev/stage/prod) als Under-Apps
- Bessere Struktur bei vielen Services
### 10.2 Repository-Strukturen
- **Monorepo**:
- Alle Manifeste aller Services und Environments in einem Git-Repo
- **Multirepo**:
- Pro Service oder Team ein eigenes Repo
- Infrastruktur/Plattform in separaten Repos
- Argo CD unterstützt beide Modelle Entscheidung ist organisatorisch/architektonisch.
---
## 11. Integration in CI/CD-Pipelines
Argo CD übernimmt in einem klassischen Setup die **CD-Rolle**:
- CI-Pipeline (z.B. GitLab CI, GitHub Actions, Jenkins):
- Buildet Container-Images
- Pusht Images in ein Registry
- Aktualisiert Versionsnummern/Tags in den Git-Manifesten (Deployment-Repo)
- Argo CD:
- Erkennt Änderungen im Git-Repo
- Deployt diese in den Cluster
Dadurch entsteht eine klare Trennung:
- CI = Builds, Tests, Image-Erzeugung
- CD = Versionswechsel im Git + Argo CD Sync
---
## 12. Monitoring & Observability
- Argo CD bietet:
- Events & Logs (Application-Controller, Repo-Server etc.)
- Metriken (Prometheus-Exporter) für:
- Anzahl Apps, Sync-Status, Health
- Dauer von Syncs
- Fehler, Retries
- Integration mit:
- **Prometheus/Grafana** (Dashboards für Argo CD)
- Alerting auf Drift, Degradation, Sync-Fehler
---
## 13. Best Practices
Einige bewährte Vorgehensweisen:
1. **Git als einzige Wahrheit**
- Keine manuellen Änderungen via `kubectl` in produktiven Namespaces
2. **Automatisches Syncen mit Self-Heal** (mindestens in lower Environments)
3. **Trennung von Image-Build-Repo und Deployment-Repo**
4. **AppProjects pro Team/Domain** zur Strukturierung und Begrenzung
5. **RBAC sauber definieren**:
- Admin-Rechte nur für wenige
- Team-spezifische Rollen
6. **Health-Konfigurationen pflegen**:
- Custom Health Checks für eigene CRDs, falls nötig
7. **Klare Namenskonventionen** für Applications, Projekte und Repos
8. **App-of-Apps** für große Landschaften:
- z.B. `cluster-bootstrap` Application, die alle anderen Apps initialisiert
---
## 14. Typische Fallstricke
- **Drift durch manuelle Änderungen**:
- Ursache für OutOfSync und schwer zu reproduzierende Zustände
- **Fehlerhafte oder komplexe Helm-/Kustomize-Setups**:
- Render-Probleme im Repo-Server bei sehr komplexen Konfigurationen
- **Unzureichende Rechte im Ziel-Cluster**:
- Argo CD-Service-Account braucht passende RBAC-Rechte
- **Netzwerk-/Firewall-Probleme**:
- Argo CD muss das Git-Repo erreichen können (Proxy, SSL, SSH-Keys)
- **Stateful-Migrationen**:
- Vorsicht bei Datenbank-Migrationen im Sync-Prozess (Hook-Jobs, Migrationsphasen)
---
## 15. Argo CD vs. andere GitOps-Tools (z.B. Flux)
Kurzvergleich zu **Flux** (ein anderes populäres GitOps-Tool):
- **Argo CD**:
- Sehr starke, moderne **UI**
- Klare Application-Entität
- Häufig intuitiv für Teams, die visuelle Steuerung wünschen
- **Flux**:
- Sehr „Kubernetes-native“, keine eigene zentrale UI (oft mit zusätzlicher UIs wie Weave GitOps)
- Stärker über CRDs und CLI gesteuert, weniger „zentrales“ Dashboard
Beide implementieren GitOps; die Wahl hängt oft von:
- UI-Bedarf
- Präferenzen des Teams
- Vorhandenen Ökosystem-Komponenten
@@ -0,0 +1,255 @@
Im IT-Kontext bedeutet **Ingress** allgemein:
> „Eingehender Datenverkehr in ein System, Netzwerk oder einen Dienst.“
Je nach Kontext wird der Begriff etwas unterschiedlich verwendet:
# Allgemein
### 1. Netzwerk / Security
In klassischen Netzwerken und Firewalls unterscheidet man:
- **Ingress-Traffic**: Datenverkehr, der **von außen nach innen** in ein Netzwerk oder System hineinkommt
(z.B. HTTP-Anfragen aus dem Internet an Ihren Webserver).
- **Egress-Traffic**: Datenverkehr, der **von innen nach außen** geht
(z.B. Ihr Server ruft eine externe API im Internet auf).
Typische Themen rund um Ingress in diesem Kontext:
- **Ingress-Filterung**: Regeln, die festlegen, welcher eingehende Traffic erlaubt ist (z.B. Firewall-Regeln).
- **Ingress-Schutz**: Maßnahmen gegen Angriffe von außen (DDoS-Schutz, WAF, Rate Limiting).
### 2. Kubernetes (Spezialfall „Ingress“ Resource)
In Kubernetes ist **Ingress** ein eigener Begriff und bezeichnet eine **API-Ressource**, die regelt, wie externe Requests in den Cluster hinein zu den internen Services geleitet werden.
Kurz gesagt:
- Ein **Ingress** ist eine Art **Reverse Proxy / Routing-Regel** auf Layer 7 (HTTP/HTTPS).
- Er definiert z.B.:
- Welche Domain (`host`) auf welchen Service zeigt
- Welche Pfade (`/api`, `/app`) zu welchen Services geroutet werden
- SSL/TLS-Termination (HTTPS)
Beispielhafte Ingress-Definition in Kubernetes:
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: my-api-service
port:
number: 80
```
Hier sorgt der Ingress dafür, dass Anfragen an `https://myapp.example.com/api` in den Cluster gehen und beim Service `my-api-service` landen.
---
Im Kubernetes-Kontext ist „Ingress“ etwas spezieller als nur „eingehender Traffic“. Es gibt drei eng zusammenhängende Dinge:
1. **Ingress-Ressource** (YAML-Objekt, das Routing-Regeln beschreibt)
2. **Ingress-Controller** (Software/Pod, der diese Regeln umsetzt)
3. **(Optional) IngressClass** (welcher Controller für welches Ingress zuständig ist)
Ich gehe der Reihe nach durch.
---
# Kubernetes
## 1. Warum braucht man Ingress überhaupt?
Ohne Ingress hast du im Wesentlichen drei Möglichkeiten, Dienste nach außen verfügbar zu machen:
- `ClusterIP` (Standard): nur intern im Cluster erreichbar
- `NodePort`: öffnet einen Port auf jedem Node; eher low-level / unkomfortabel
- `LoadBalancer`: Cloud-Loadbalancer vor einem Service (oft pro Service ein eigener LB)
Nachteile:
- Viele externe IPs / Loadbalancer, wenn du viele Services hast
- Keine zentrale Layer7-Logik (z.B. Routing per Hostname/URL-Pfad, TLS-Termination)
**Ingress** löst genau das:
> Ein (oder wenige) externe Einstiegspunkte, die per Hostname und Pfad auf viele interne Services routen können, inkl. HTTPS/TLS, Auth, Rate-Limiting (je nach Controller).
---
## 2. Ingress-Ressource (das YAML-Objekt)
Die Ingress-Ressource beschreibt **Deklarativ**, wie Anfragen von außen zu Services im Cluster geroutet werden sollen:
- Auf Basis von **Hostname** (`host`, z.B. `api.example.com`)
- Auf Basis von **Pfad** (`path`, z.B. `/api`, `/app`)
- Verknüpft mit einem **Backend-Service** (`Service` + Port)
- Optional: **TLS**-Konfiguration (Zertifikate)
Beispiel:
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
tls:
- hosts:
- myapp.example.com
secretName: myapp-tls-secret
rules:
- host: myapp.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: my-api-service
port:
number: 80
- path: /app
pathType: Prefix
backend:
service:
name: my-frontend-service
port:
number: 80
```
Was hier passiert:
- Alle Anfragen an `https://myapp.example.com/api...` → Service `my-api-service`
- Alle Anfragen an `https://myapp.example.com/app...` → Service `my-frontend-service`
- TLS-Zertifikat liegt in `Secret myapp-tls-secret`
- `ingressClassName: nginx` sagt: „Dieser Ingress ist für den Ingress-Controller mit Klasse `nginx` gedacht“
Wichtige Felder:
- `rules[].host`: auf welchen Host gilt die Regel?
- `rules[].http.paths[].path`: URL-Pfad
- `pathType`:
- `Prefix` → „beginnt mit diesem Pfad“
- `Exact` → „genau dieser Pfad“
- (früher gab es noch `ImplementationSpecific`)
- `backend.service.name` / `port`: zu welchem Service leiten?
---
## 3. Ingress-Controller (die „Engine“ dahinter)
Die YAML-Ressource alleine macht noch nichts. Es braucht einen **Ingress-Controller**:
- Läuft als Pod/Deployment im Cluster
- Beobachtet (watch) Ingress-Ressourcen im API-Server
- Übersetzt die Regeln in eine konkrete Konfiguration (z.B. [[NGINX]], Envoy, Traefik …)
- Lauscht auf einem (oder mehreren) Node-Ports/LoadBalancer-IPs und routet Traffic in die passende Services
Typische Implementierungen:
- **[[NGINX]] Ingress Controller**
- **Traefik**
- **HAProxy Ingress**
- **Envoy-basierte** Controller
- Cloud-spezifische:
- GCE/GLBC (GKE HTTP(S) Load Balancing)
- AWS ALB Ingress Controller
- Azure Application Gateway Ingress
Wichtig:
Du kannst mehrere Ingress-Controller im Cluster haben, z.B. einen für öffentliche, einen für interne Services.
---
## 4. IngressClass (Zuordnung Controller ↔ Ingress)
Mit `IngressClass` kann man genau definieren, **welcher** Ingress-Controller für welche Ingress-Ressourcen zuständig ist.
Beispiel IngressClass:
```yaml
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: nginx
spec:
controller: k8s.io/ingress-nginx
```
Im Ingress verknüpfst du das mit:
```yaml
spec:
ingressClassName: nginx
# ...
```
Somit:
- Nur der Ingress-Controller, der sich als `k8s.io/ingress-nginx` registriert, reagiert auf diesen Ingress.
- Andere Controller ignorieren ihn.
Früher wurde das oft über **Annotations** geregelt (`kubernetes.io/ingress.class`), `ingressClassName` ist der neuere, bevorzugte Weg.
---
## 5. Request-Flow: Wie läuft eine Anfrage technisch?
Typischer Ablauf (z.B. mit [[NGINX]] Ingress Controller in einer Cloud):
1. Benutzer ruft im Browser `https://myapp.example.com/api/users` auf.
2. DNS zeigt `myapp.example.com` auf die externe IP eines Cloud-Loadbalancers.
3. Der Cloud-Loadbalancer leitet die Anfrage an einen Node/Port, auf dem der Ingress-Controller erreichbar ist.
4. Der Ingress-Controller (Pod) erhält die HTTP(S)-Anfrage.
5. Er vergleicht Host (`myapp.example.com`) und Pfad (`/api/users`) mit seinen Ingress-Regeln:
- Host passt zu `myapp.example.com`
- Pfad passt zum Prefix `/api`
6. Er leitet die Anfrage intern an den Kubernetes-Service `my-api-service:80` weiter.
7. Kubernetes-Service verteilt die Anfrage per kube-proxy/IPVS/iptables auf einen Pod (`my-api`-Pod).
8. Antwort geht den Weg zurück und landet beim Benutzer.
---
## 6. Typische Features (Controller-abhängig)
Je nach Ingress-Controller gibt es zusätzliche Möglichkeiten, meist über **Annotations** oder spezifische CRDs:
- **TLS-Termination** und optional TLS-Passthrough
- **HTTP → HTTPS Redirect**
- **Path-Rewrites**, z.B. `/api` außen → `/` im Backend
- **Authentifizierung** (z.B. OAuth2, Basic Auth)
- **Rate Limiting**, IP-Whitelist/Blacklist
- **Canary-Deployments / Traffic-Splitting**
- **gRPC-Support**, WebSockets, etc.
Beispiel (nginx Spezifische Annotation für Redirect):
```yaml
metadata:
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
```
---
## 7. Grenzen von Ingress & Gateway API
Die klassische Ingress-API ist bewusst relativ simpel (Host, Pfad, Backend, TLS).
Für komplexere Szenarien (multi-tenant, umfangreiche Routing-Logik, mehrere Gateways) gibt es inzwischen die **Gateway API** (Ressourcen wie `Gateway`, `HTTPRoute` etc.), die Ingress langfristig ergänzen/teilweise ablösen soll.
Dennoch ist Ingress aktuell (2024) in vielen Clustern der Standardweg, HTTP/HTTPS-Traffic von außen hereinzubringen.
---
Wenn du möchtest, kann ich als Nächstes:
- ein konkretes Setup „von Null an“ durchgehen (z.B. Minikube + [[NGINX]] Ingress + Beispiel-App), oder
- spezifisch auf Annotations/Features eines bestimmten Ingress-Controllers eingehen (etwa nginx oder Traefik).
@@ -0,0 +1,427 @@
Ein JSON Web Token (JWT) wirkt am Anfang oft etwas „magisch“. Wenn man es einmal verstanden hat, ist es aber ein relativ simples Baustein-konzept für Authentifizierung und Autorisierung in modernen Web und APISystemen.
Ich gehe Schritt für Schritt durch:
1. Grundidee: Was ist ein JWT?
2. Aufbau eines JWT
3. Abgrenzung zu verwandten Konzepten
4. Welche Probleme werden mit JWT gelöst?
5. Typische Anwendungsfälle (praxisnah erklärt)
6. Herausforderungen und Fallstricke
7. Kurz-Fazit
---
## 1. Grundidee: Was ist ein JWT?
**Definition (vereinfacht):**
Ein **JWT (JSON Web Token)** ist ein **kompakter, URL-tauglicher, digital signierter Datenblock**, der Informationen über einen Benutzer oder eine Aktion enthält (z.B. „Benutzer X ist eingeloggt und hat Rolle admin“).
Diese Informationen sind im JSON-Format strukturiert und werden mit einem kryptografischen Verfahren signiert (und optional verschlüsselt).
Damit kann ein Server (oder mehrere Server) **prüfen**, ob das Token:
- von einem vertrauenswürdigen Aussteller stammt,
- nicht manipuliert wurde,
- noch gültig ist (nicht abgelaufen).
Man kann sich einen JWT grob als „fälschungssichereren Ausweis“ für Benutzer (oder Clients) vorstellen, der vom Server ausgestellt wird und den der Client bei weiteren Anfragen vorzeigt.
---
## 2. Aufbau eines JWT
Ein JWT besteht aus **drei Teilen**, jeweils Base64URL-kodiert, durch Punkte getrennt:
```text
HEADER.PAYLOAD.SIGNATURE
```
Ein Beispiel (gekürzt, sieht in der Praxis ähnlich aus):
```text
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJzdWIiOiIxMjM0NTYiLCJlbWFpbCI6Im1heC5tdXN0ZXJAbWFpbC5jb20iLCJyb2xlIjoiYWRtaW4iLCJleHAiOjE3MzAxNjkzNDN9
.
dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
```
### 2.1 Header
Der Header beschreibt u.a.:
- welches Signaturverfahren genutzt wird,
- dass es sich um ein JWT handelt.
Beispiel:
```json
{
"alg": "HS256", // Algorithmus: HMAC-SHA256
"typ": "JWT"
}
```
### 2.2 Payload (Claims)
Die Payload enthält die eigentlichen Informationen („Claims“).
Beispiele:
```json
{
"sub": "123456", // subject: Benutzer-ID
"email": "max.mustermann@example.com",
"role": "admin",
"iat": 1730169334, // issued at (Unix-Timestamp)
"exp": 1730172934, // expiry: Ablaufzeitpunkt
"iss": "https://auth.meine-app.de", // issuer
"aud": "https://api.meine-app.de" // audience
}
```
Wichtige Standard-Claims (nicht verpflichtend, aber üblich):
- `iss` Issuer (Wer hat das Token ausgestellt?)
- `sub` Subject (Auf wen bezieht sich das Token? z.B. Benutzer-ID)
- `aud` Audience (Für welche Anwendung/Services ist das Token bestimmt?)
- `exp` Expiration Time (Wann läuft das Token ab?)
- `iat` Issued At (Wann wurde es ausgestellt?)
- `nbf` Not Before (Ab wann ist es gültig?)
Dazu kommen **anwendungsspezifische Claims**, z.B.:
- `email`, `username`
- `roles`: `["admin", "user"]`
- `scope`: `"read:orders write:orders"`
### 2.3 Signature
Die Signatur wird aus dem Header + Payload + einem Geheimnis (oder Schlüssel) gebildet.
Formel grob:
```text
signature = Sign( base64Url(header) + "." + base64Url(payload), secret_or_private_key )
```
Beim Prüfen:
- rekonstruiert der Server diese Signatur aus Header+Payload,
- vergleicht sie mit der Signatur im Token,
- wenn sie übereinstimmen → Token wurde nicht manipuliert.
---
## 3. Abgrenzung zu verwandten Begriffen
### 3.1 JWT vs klassische Session-Cookies
**Klassische Session:**
- Nach Login erzeugt der Server eine **Session-ID** und speichert alle Infos (Benutzer, Rollen usw.) **im Server-Speicher** (in Memory, Redis, DB).
- Die Session-ID wird im Browser z.B. als Cookie gespeichert.
- Bei jeder Anfrage sendet der Browser die Session-ID; Server schaut im eigenen Speicher nach, welche Daten dazu gehören.
**JWT:**
- Nach Login erzeugt der Server ein **Token**, das die Infos (Benutzer, Rollen, Ablaufzeit) **direkt im Token** enthält.
- Das Token wird typischerweise im Browser (Cookie oder Speicher der App) gehalten.
- Bei jeder Anfrage schickt der Client das Token mit (z.B. via HTTP-Header `Authorization: Bearer <token>`).
- Der Server liest und prüft das Token, braucht aber keinen Session-Speicher.
Kurz:
- Session: **zustandsbehaftet (stateful)** auf Server-Seite.
- JWT: **zustandslos (stateless)** auf Server-Seite.
### 3.2 JWT vs OAuth2 / OpenID Connect
- **OAuth2** ist ein **Protokoll für Autorisierung** (wer darf was). Es definiert Flows, Rollen (Client, Resource Owner, Authorization Server, Resource Server) etc.
- **OpenID Connect (OIDC)** baut auf OAuth2 auf und regelt **Authentifizierung** (wer bist du) inklusive ID-Token.
JWT ist hier eher ein **Datenformat**:
- In OAuth2/OIDC werden oft **Access Tokens** und **ID Tokens** als JWT umgesetzt.
- Aber OAuth2/OIDC kann theoretisch auch andere Tokenformate verwenden.
**Merksatz:**
OAuth2 / OIDC = das Protokoll;
JWT = ein mögliches Format für die Tokens.
### 3.3 JWT vs JWS / JWE
- **JWS (JSON Web Signature)**: Standard für signierte JSON-Daten.
- **JWE (JSON Web Encryption)**: Standard für verschlüsselte JSON-Daten.
Ein **typisches JWT ist ein JWS**: signiert, aber nicht verschlüsselt.
Es gibt aber auch **JWTs als JWE**: zusätzlich verschlüsselt (seltener in der Praxis).
Wichtig:
**Signiert heißt: Integrität und Echtheit** (nicht manipuliert, vom richtigen Aussteller),
**nicht automatisch: Geheimhaltung**.
Payload ist bei normalen JWTs **lesbar**, auch wenn sie signiert sind.
### 3.4 JWT vs API-Schlüssel (API Key)
- Ein **API-Key** ist meist ein zufälliger String, der einen Client identifiziert.
Logik: „Wer den Key kennt, darf die API nutzen.“
- Ein **JWT** enthält strukturierte Informationen (Claims) und ist signiert, so dass man viele Details im Token selbst hat (Benutzer, Rollen, Ablauf).
JWT ist in der Regel **ausdrucksstärker** und besser integrierbar in komplexe Auth-Zusammenhänge; ein API-Key ist eher „simple Zugriffskarte“.
### 3.5 JWT vs SAML
- **SAML** ist ein älterer Standard für Single Sign-On (SSO), benutzt XML statt JSON.
- JWT (bzw. OIDC mit JWT) ist moderner, leichtergewichtig, JSON-basiert.
Viele moderne Anwendungen bevorzugen OIDC + JWT statt SAML, vor allem im Web-/API-Bereich.
---
## 4. Welche Probleme werden mit JWT gelöst?
### 4.1 Skalierbare Authentifizierung in verteilten Systemen
Problem:
- Klassische Sessions erfordern zentralen Server-Speicher (Session Store).
- In modernen Microservice-Architekturen und skalierenden Web-Apps (viele Instanzen) ist das unpraktisch.
JWT-Lösung:
- **Zustandslose Tokens**: Jeder Service kann das Token **selbst verifizieren**, ohne zentralen Session Store.
- Mehrere Instanzen, mehrere Services, sogar andere Systeme (Partner-APIs) können mit dem gleichen Token arbeiten, solange sie den Signaturschlüssel kennen (oder das zugehörige Public Key).
### 4.2 Einfache Weitergabe von Benutzerinformationen
Problem:
- Mehrere Services müssen wissen, wer der Benutzer ist und welche Rechte er hat.
- Man möchte nicht jedes Mal eine zusätzliche Datenbankabfrage machen.
JWT-Lösung:
- Claims im Token: `sub`, `email`, `roles`, `scope`, …
- Jeder Service liest diese Claims aus dem Token und kann basierend darauf entscheiden.
### 4.3 Mobile / Single-Page-Applications (SPAs)
Problem:
- SPAs (z.B. React, Angular, Vue) und Mobile-Apps sprechen meist direkt mit APIs.
- Klassische serverseitige Sessions sind dafür unhandlich, weil es keinen klassischen Browser-Request/Response-Cookie-Workflow gibt oder dieser komplexer ist.
JWT-Lösung:
- Client erhält nach Login ein **Access Token (JWT)**.
- Bei jedem API-Request wird das JWT im `Authorization`-Header mitgeschickt.
- APIs können unabhängig vom Frontend arbeiten (auch mehrere Frontends nutzen die gleiche API).
---
## 5. Praxisnahe Anwendungsbeispiele
### 5.1 Web-App / API-Login mit JWT
Ablauf:
1. Benutzer gibt E-Mail + Passwort ein und klickt auf „Login“.
2. Frontend schickt diese Daten an `/auth/login` (Backend).
3. Backend prüft:
- Benutzer existiert?,
- Passwort korrekt?
4. Wenn ok:
- Backend erstellt ein JWT:
- `sub = Benutzer-ID`
- `email = Benutzer-Email`
- `role = "user"`
- `exp = in 15 Minuten`
- signiert das Token mit einem geheimen Schlüssel (z.B. HS256).
5. Backend schickt das Token an das Frontend zurück.
6. Frontend speichert das Token:
- z.B. in einem **httpOnly Cookie** (empfohlen),
- oder in einem sicheren Storage (abhängig vom Setup).
7. Bei jeder API-Anfrage:
- schickt das Frontend das Token mit, z.B.:
```http
GET /api/orders
Authorization: Bearer <JWT_HIER>
```
8. Die API:
- prüft die Signatur,
- prüft `exp` (nicht abgelaufen?),
- liest `sub`, `role`, `scope` aus,
- entscheidet, ob Zugriff erlaubt ist.
### 5.2 Microservices hinter einem API Gateway
Stell dir eine Plattform mit mehreren Microservices vor:
- `User-Service`
- `Order-Service`
- `Billing-Service`
Es gibt einen **Auth-Service**, der JWTs ausstellt.
Alle Services kennen den Public Key (bei asymmetrischer Signatur) oder den Secret Key (bei symmetrischer Signatur).
Ablauf:
- Benutzer loggt sich über Auth-Service ein → bekommt JWT.
- Frontend ruft `Order-Service` auf mit `Authorization: Bearer <JWT>`.
- `Order-Service` prüft JWT:
- gültig?
- `scope` beinhaltet `read:orders`?
- Wenn ja → Bestellung anzeigen.
Vorteil:
Jeder Service muss keinen eigenen Session-Store haben, sondern nur das JWT validieren.
### 5.3 E-Mail-Bestätigung / Passwort-Reset
JWTs eignen sich auch für **zeitlich begrenzte Links**:
Beispiel: Passwort-Reset:
1. Benutzer klickt „Passwort vergessen“.
2. Backend erzeugt ein JWT mit Claims:
- `sub = Benutzer-ID`
- `exp = in 30 Minuten`
- `purpose = "password_reset"`
3. Backend verschickt E-Mail mit Link:
```text
https://meine-app.de/reset-password?token=<JWT_HIER>
```
4. Benutzer klickt den Link.
5. Frontend schickt den Token an das Backend, z.B. POST `/auth/reset-password`.
6. Backend prüft:
- Signatur,
- `exp` (noch gültig?),
- `purpose == "password_reset"`.
7. Wenn alles passt → Passwort darf geändert werden.
---
## 6. Herausforderungen und Fallstricke
JWTs lösen einige Probleme, bringen aber eigene Herausforderungen mit sich.
### 6.1 Sicherheit bei Signatur und Schlüssel
Wichtige Punkte:
- **Algorithmuswahl:**
Typisch:
- Symmetrisch: `HS256` (ein gemeinsames Secret für Signatur & Prüfung)
- Asymmetrisch: `RS256` (privater Schlüssel signiert, öffentlicher Schlüssel prüft)
- **Keys sicher verwalten:**
- nicht im Code hardcoden,
- in sicheren Secret-Stores halten,
- Schlüssel regelmäßig rotieren.
Gefährliche Anti-Pattern:
- `alg: none` akzeptieren (nie tun),
- Server so konfigurieren, dass er das `alg` aus dem Token blind vertraut (statt fest vorzugeben, was erlaubt ist).
### 6.2 Token-Ablauf und „Logout“
JWT ist stateless das macht „Logout“ tricky:
- Klassische Session:
- Session im Server-Speicher löschen → Benutzer abgemeldet.
- JWT:
- Token ist selbstständig gültig, bis `exp` erreicht ist.
- Serverseitig gibt es **keine zentrale Liste** aller aktiven JWTs.
Mögliche Lösungen:
- Tokens **kurzlebig** machen, z.B. 515 Minuten.
- Für längere Sessions:
- **Access Token** kurzlebig,
- **Refresh Token** längerlebig und serverseitig verwaltbar (z.B. in DB),
- bei Logout → Refresh Token invalidieren, Access Token läuft automatisch bald ab.
- Optional: Blacklists/Blocklists oder Token-Revocation-Mechanismen.
### 6.3 Wo speichert man JWT im Browser?
Varianten:
- **httpOnly Cookie**:
- Vorteil: nicht via JavaScript auslesbar → Schutz gegen XSS.
- Nachteil: CSRF muss beachtet werden (CSRF-Protection implementieren).
- **localStorage / sessionStorage**:
- Vorteil: einfache Handhabung im JS-Code.
- Nachteil: bei XSS kann ein Angreifer das Token auslesen → sehr riskant.
In der Praxis:
- Oft Kombination aus httpOnly Cookies + CSRF-Schutz,
- oder Speziallösungen mit sog. „Double Submit Cookies“, „SameSite“-Cookies etc.
### 6.4 Token sind nicht geheim (wenn nur signiert)
Wichtiger Punkt:
- Ein **normaler signierter JWT ist nicht verschlüsselt**.
- Jeder, der das Token sieht, kann die Payload (Claims) lesen, da sie Base64URL-kodiert ist (was keine Verschlüsselung ist).
Daraus folgt:
- Keine hochsensiblen Daten in die Payload packen (z.B. Passwörter, Zahlungsdaten, interne Geheimnisse).
- JWT nur über **HTTPS** übertragen, damit niemand auf dem Weg „mithören“ kann.
- Wenn wirklich Geheimhaltung nötig ist → **JWE (verschlüsseltes JWT)** oder andere Verschlüsselungsmechanismen.
### 6.5 Token-Größe
Wenn man sehr viele Claims ins Token packt:
- wird es groß,
- verursacht mehr Traffic,
- passt evtl. schlechter in Cookies oder Header.
Praktisch:
Nur wirklich relevante Informationen ins JWT aufnehmen:
- Benutzer-ID
- Rollen, Rechte oder Scope
- wenige zusätzliche Angaben
Den Rest kann man bei Bedarf aus der Datenbank abfragen.
### 6.6 Fehler bei der Prüfung des Tokens
Beim Validieren darf man nicht nur die Signatur prüfen, sondern auch:
- Ist das Token abgelaufen? (`exp`)
- Ist das Token noch nicht gültig? (`nbf`, `iat`)
- Stimmt `iss` (Issuer) mit dem erwarteten Aussteller überein?
- Stimmt `aud` (Audience) mit der eigenen Anwendung/API überein?
Beispiel (Node.js mit `jsonwebtoken`):
```js
const jwt = require('jsonwebtoken');
const token = '...'; // vom Client erhalten
const publicKey = '...'; // Public Key (bei RS256) oder Secret (bei HS256)
try {
const payload = jwt.verify(token, publicKey, {
algorithms: ['RS256'],
issuer: 'https://auth.meine-app.de',
audience: 'https://api.meine-app.de',
});
console.log('Token gültig, Benutzer-ID:', payload.sub);
} catch (err) {
console.error('Ungültiges Token:', err.message);
}
```
---
## 7. Kurz-Fazit
- Ein **JWT** ist ein **signierter, kompakter Datenträger im JSON-Format**, der Claims über Benutzer/Clients enthält.
- Er wird verwendet für:
- Authentifizierung (z.B. „Benutzer X ist eingeloggt“),
- Autorisierung (z.B. „Benutzer X hat die Rolle admin“),
- zeitlich begrenzte Aktionen (Passwort-Reset, E-Mail-Bestätigung),
- verteilte Systeme (Microservices), die ohne zentralen Session-Speicher auskommen sollen.
- JWTs sind besonders sinnvoll in:
- Web-APIs,
- SPAs,
- mobilen Apps,
- Microservice- und Cloud-Architekturen.
- Abgrenzung:
- JWT ≠ OAuth2/OIDC (Protokoll vs. Tokenformat),
- JWT ≠ Session-Cookie (zustandslos vs. zustandsbehaftet),
- JWTs sind meist JWS (signiert, aber nicht verschlüsselt).
- Herausforderungen:
- Sichere Schlüsselverwaltung, korrekte Token-Prüfung,
- Umgang mit Logout/Token-Invalidierung,
- sicherer Speicherort im Client (XSS/CSRF),
- kein Hineinpacken hochsensibler Daten.
@@ -0,0 +1,512 @@
## Inhaltsverzeichnis
- [Grundkonzepte](#grundkonzepte)
- [Schritt 1: Welche Endpoints gibt es?](#schritt-1-welche-endpoints-gibt-es)
- [Schritt 2: Endpoint-Konfiguration prüfen](#schritt-2-endpoint-konfiguration-prüfen)
- [Schritt 3: Endpoint erreichbar machen](#schritt-3-endpoint-erreichbar-machen)
- [Troubleshooting](#troubleshooting)
---
## Grundkonzepte
### Was ist ein Endpoint?
Ein **Endpoint** ist eine URL, über die Sie auf eine Anwendung in Kubernetes zugreifen können (z.B. `https://jupyterhub.example.com` oder `http://localhost:8080`).
### Wichtige Kubernetes-Komponenten
#### 1. Pod
- Ein **Pod** ist die kleinste Einheit in Kubernetes
- Enthält einen oder mehrere Container (z.B. Ihre Anwendung)
- Hat eine interne IP-Adresse im Cluster
- Befehl: `kubectl get pods -n <namespace>`
#### 2. Service
- Ein **Service** ist eine stabile Zugangsadresse zu einem oder mehreren Pods
- Macht Pods innerhalb des Clusters erreichbar
- Typen:
- `ClusterIP`: Nur innerhalb des Clusters erreichbar
- `NodePort`: Von außen über Port am Node erreichbar
- `LoadBalancer`: Erstellt einen externen Load Balancer (z.B. bei AWS)
- Befehl: `kubectl get svc -n <namespace>`
#### 3. Ingress
- Ein **Ingress** ist die "Haustür" zu Ihren Services von außerhalb des Clusters
- Ermöglicht HTTP/HTTPS-Zugriff über Domainnamen (z.B. `app.example.com`)
- Benötigt einen Ingress Controller (z.B. [[nginx]])
- Befehl: `kubectl get ingress -n <namespace>`
#### 4. Namespace
- Ein **Namespace** ist wie ein Ordner in Kubernetes
- Trennt verschiedene Anwendungen oder Teams
- Beispiele: `openmetadata`, `jupyterhub`, `default`
---
## Schritt 1: Welche Endpoints gibt es?
### 1.1 Alle Namespaces auflisten
```bash
kubectl get namespaces
```
**Erklärung:** Zeigt alle Namespaces in Ihrem Cluster. Hier finden Sie, wo Ihre Anwendungen laufen.
**Beispiel-Output:**
```
NAME STATUS AGE
default Active 30d
jupyterhub Active 20d
openmetadata Active 5d
argocd Active 25d
```
### 1.2 Anwendungen in einem Namespace finden
```bash
# Pods (laufende Anwendungen)
kubectl get pods -n openmetadata
# Services (Zugriffspunkte)
kubectl get svc -n openmetadata
# Ingress (externe Zugänge)
kubectl get ingress -n openmetadata
```
**Wichtig:** Ersetzen Sie `openmetadata` mit Ihrem Namespace!
**Beispiel-Output:**
```bash
# Pods
NAME READY STATUS RESTARTS AGE
openmetadata-559bf987f6-gxkdk 1/1 Running 0 4d20h
# Services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
openmetadata ClusterIP 172.20.25.201 <none> 8585/TCP,8586/TCP 4d20h
# Ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
openmetadata nginx openmetadata.dma.aai-dfine.de xxx.elb.amazonaws.com 80, 443 4d20h
```
### 1.3 Alle Ingress-Endpoints im Cluster
```bash
kubectl get ingress --all-namespaces
```
**Erklärung:** Zeigt ALLE konfigurierten externen Zugänge über alle Namespaces hinweg.
---
## Schritt 2: Endpoint-Konfiguration prüfen
### 2.1 Detaillierte Ingress-Informationen
```bash
kubectl describe ingress <ingress-name> -n <namespace>
```
**Beispiel:**
```bash
kubectl describe ingress openmetadata -n openmetadata
```
**Was Sie hier sehen:**
- **Hosts:** Der Domainname (z.B. `openmetadata.dma.aai-dfine.de`)
- **TLS:** Ob HTTPS konfiguriert ist und welches Zertifikat verwendet wird
- **Backends:** Zu welchem Service und Port der Ingress weiterleitet
- **Address:** Der tatsächliche Load Balancer
**Beispiel-Output:**
```
Name: openmetadata
Namespace: openmetadata
Address: aa83990c7ad3548c4b0e28680b0952ba-1924426268.eu-central-1.elb.amazonaws.com
Ingress Class: nginx
TLS:
aai-dfine-certificate-tls terminates openmetadata.dma.aai-dfine.de
Rules:
Host Path Backends
---- ---- --------
openmetadata.dma.aai-dfine.de / openmetadata:8585 (10.10.1.86:8585)
```
### 2.2 Pod-Status überprüfen
```bash
kubectl get pods -n <namespace>
```
**Status-Bedeutungen:**
- `Running`: ✅ Pod läuft normal
- `Pending`: ⏳ Pod startet gerade
- `CrashLoopBackOff`: ❌ Pod startet immer wieder neu (Fehler!)
- `Error`: ❌ Pod hat einen Fehler
### 2.3 Service-Details
```bash
kubectl get svc <service-name> -n <namespace> -o wide
```
**Zeigt:** ClusterIP, Ports, Selectors (welche Pods werden angesprochen)
---
## Schritt 3: Endpoint erreichbar machen
Es gibt **drei Methoden**, um auf einen Kubernetes-Endpoint zuzugreifen:
### Methode 1: Port-Forwarding (Empfohlen für Tests) ⭐
**Wann nutzen?**
- Schneller Zugriff für Tests
- DNS ist nicht konfiguriert
- Lokale Entwicklung
**Vorteile:**
- ✅ Keine Cluster-Änderungen
- ✅ Sicher (nur für Sie erreichbar)
- ✅ Sofort verfügbar
- ✅ Keine DNS-Konfiguration nötig
**Nachteile:**
- ❌ Terminal muss offen bleiben
- ❌ Nur von Ihrem PC erreichbar
**Befehl:**
```bash
kubectl port-forward -n <namespace> svc/<service-name> <lokaler-port>:<service-port>
```
**Beispiel für OpenMetadata:**
```bash
kubectl port-forward -n openmetadata svc/openmetadata 8585:8585
```
**Was passiert:**
1. Kubernetes erstellt einen Tunnel von Ihrem PC zum Service
2. Sie können nun auf `http://localhost:8585` zugreifen
3. Der Tunnel leitet alle Anfragen an den Service im Cluster weiter
**Zugriff:**
```
http://localhost:8585
```
**Beenden:** `Ctrl + C` im Terminal
**Tipp:** Im Hintergrund laufen lassen:
```bash
# Windows PowerShell
Start-Process kubectl -ArgumentList "port-forward -n openmetadata svc/openmetadata 8585:8585" -WindowStyle Hidden
```
---
### Methode 2: Über Ingress mit DNS (Produktiv-Umgebung)
**Wann nutzen?**
- Produktiv-Zugriff
- Mehrere Nutzer
- HTTPS/TLS erforderlich
**Voraussetzungen:**
1. ✅ Ingress ist konfiguriert (siehe Schritt 2.1)
2. ✅ DNS-Eintrag existiert
3. ✅ TLS-Zertifikat ist vorhanden
#### 2.1 DNS-Auflösung testen
```bash
# Windows PowerShell
nslookup openmetadata.dma.aai-dfine.de
# Alternative
Resolve-DnsName openmetadata.dma.aai-dfine.de
```
**Wenn DNS funktioniert:**
```
Server: dns.google
Address: 8.8.8.8
Name: openmetadata.dma.aai-dfine.de
Address: 54.xxx.xxx.xxx
```
**Wenn DNS NICHT funktioniert:**
```
*** dns.google kann openmetadata.dma.aai-dfine.de nicht finden: Non-existent domain
```
#### 2.2 Problem: DNS funktioniert nicht
**Lösung A: Lokale Hosts-Datei (temporär für Tests)**
1. **Load Balancer IP/Hostname finden:**
```bash
kubectl get ingress <ingress-name> -n <namespace>
```
Notieren Sie die `ADDRESS` (z.B. `xxx.elb.amazonaws.com`)
2. **Load Balancer IP auflösen:**
```bash
nslookup xxx.elb.amazonaws.com
```
3. **Windows Hosts-Datei bearbeiten:**
- Datei öffnen als Administrator: `C:\Windows\System32\drivers\etc\hosts`
- Zeile hinzufügen:
```
<IP-Adresse> openmetadata.dma.aai-dfine.de
```
- Speichern
4. **Im Browser öffnen:**
```
https://openmetadata.dma.aai-dfine.de
```
**Lösung B: DNS-Eintrag erstellen lassen (dauerhaft)**
Jemand mit AWS Route53-Zugriff muss einen DNS-Eintrag erstellen:
- **Typ:** CNAME oder A-Record
- **Name:** `openmetadata.dma.aai-dfine.de`
- **Ziel:** Load Balancer Hostname/IP
---
### Methode 3: Direkt zum Load Balancer (ohne DNS)
**Wenn vorhanden:**
1. **Load Balancer URL finden:**
```bash
kubectl get ingress <ingress-name> -n <namespace>
```
2. **Direkt mit curl testen:**
```bash
curl -H "Host: openmetadata.dma.aai-dfine.de" http://<load-balancer-url>
```
**Hinweis:** Funktioniert nicht immer im Browser (Host-Header erforderlich)
---
## Troubleshooting
### Problem: "Hmmm... can't reach this page" / ERR_NAME_NOT_RESOLVED
**Ursache:** DNS-Name kann nicht aufgelöst werden
**Lösung:**
1. DNS testen: `nslookup <hostname>`
2. Falls DNS fehlt → **Port-Forwarding** verwenden (Methode 1)
3. Oder: Hosts-Datei editieren (Methode 2, Lösung A)
---
### Problem: Port-Forwarding schlägt fehl
**Fehlermeldung:** `Unable to listen on port 8585`
**Ursache:** Port ist bereits belegt
**Lösung:**
```bash
# Anderen lokalen Port verwenden
kubectl port-forward -n openmetadata svc/openmetadata 9999:8585
# Dann öffnen: http://localhost:9999
```
---
### Problem: Pod läuft nicht (Status: CrashLoopBackOff)
**Logs anschauen:**
```bash
kubectl logs <pod-name> -n <namespace>
# Letzte 100 Zeilen
kubectl logs <pod-name> -n <namespace> --tail=100
# Vorheriger Container (wenn Pod neu gestartet wurde)
kubectl logs <pod-name> -n <namespace> --previous
```
---
### Problem: 502 Bad Gateway / 503 Service Unavailable
**Ursache:** Service erreicht den Pod nicht
**Prüfen:**
```bash
# 1. Läuft der Pod?
kubectl get pods -n <namespace>
# 2. Sind Endpoints vorhanden?
kubectl get endpoints <service-name> -n <namespace>
# 3. Service-Details
kubectl describe svc <service-name> -n <namespace>
```
---
### Problem: Authentifizierung erforderlich
**Wenn Login-Seite erscheint:**
**Standard-Credentials suchen:**
```bash
# Secrets auflisten
kubectl get secrets -n <namespace>
# Secret anschauen (Werte sind base64-kodiert)
kubectl get secret <secret-name> -n <namespace> -o yaml
# Secret dekodieren
kubectl get secret <secret-name> -n <namespace> -o jsonpath='{.data.password}' | base64 -d
```
**Beispiel OpenMetadata:**
- Standard-User: `admin`
- Standard-Password: `admin`
---
## Nützliche Befehle - Cheat Sheet
### Übersicht verschaffen
```bash
# Alle Namespaces
kubectl get namespaces
# Alles in einem Namespace
kubectl get all -n <namespace>
# Alle Ingress-Endpoints
kubectl get ingress --all-namespaces
```
### Status prüfen
```bash
# Pods mit mehr Details
kubectl get pods -n <namespace> -o wide
# Pod-Logs live verfolgen
kubectl logs -f <pod-name> -n <namespace>
# In Pod einloggen (für Debugging)
kubectl exec -it <pod-name> -n <namespace> -- /bin/bash
```
### Konfiguration anschauen
```bash
# YAML eines Ingress
kubectl get ingress <name> -n <namespace> -o yaml
# Service-Details
kubectl describe svc <name> -n <namespace>
# ConfigMap auslesen
kubectl get configmap <name> -n <namespace> -o yaml
```
### Port-Forwarding
```bash
# Standard
kubectl port-forward -n <namespace> svc/<service-name> <local-port>:<service-port>
# Zu einem Pod (falls Service nicht existiert)
kubectl port-forward -n <namespace> <pod-name> <local-port>:<container-port>
# Alle Interfaces binden (auch im Netzwerk erreichbar)
kubectl port-forward --address 0.0.0.0 -n <namespace> svc/<service> 8585:8585
```
---
## Best Practices
### Für Tests und Entwicklung
✅ **Port-Forwarding** verwenden
- Schnell, sicher, keine Änderungen am Cluster
### Für Produktiv-Zugriff
✅ **Ingress mit DNS** verwenden
- Korrekte DNS-Einträge erstellen lassen
- TLS/HTTPS konfigurieren
- Basic Auth oder OAuth für Authentifizierung
### Sicherheit
⚠️ **Nie direkt auf Pods zugreifen** in Produktion
⚠️ **Immer über Services** routen
⚠️ **Port-Forwarding nicht dauerhaft** laufen lassen
---
## Glossar
| Begriff | Erklärung |
|---------|-----------|
| **Cluster** | Die gesamte Kubernetes-Umgebung mit allen Maschinen |
| **Node** | Eine einzelne Maschine (VM) im Cluster |
| **Pod** | Kleinste Einheit, enthält Container mit Ihrer App |
| **Service** | Stabiler Zugriffspunkt zu einem oder mehreren Pods |
| **Ingress** | HTTP/HTTPS-Zugang von außen, wie ein Router |
| **Namespace** | Logische Trennung/Ordner für Anwendungen |
| **ConfigMap** | Konfigurationsdaten (nicht-sensitiv) |
| **Secret** | Sensible Daten (Passwörter, Tokens) - base64-kodiert |
| **Load Balancer** | Verteilt Traffic auf mehrere Pods (z.B. AWS ELB) |
| **TLS/SSL** | Verschlüsselung für HTTPS |
| **Port-Forward** | Tunnel von lokalem PC zu Kubernetes-Service |
---
## Zusammenfassung
### Quick Start: Auf Anwendung zugreifen
1. **Namespace finden:**
```bash
kubectl get namespaces
```
2. **Ingress prüfen:**
```bash
kubectl get ingress -n <namespace>
```
3. **Port-Forwarding starten:**
```bash
kubectl port-forward -n <namespace> svc/<service-name> 8585:8585
```
4. **Im Browser öffnen:**
```
http://localhost:8585
```
Das war's! 🎉
---
## Weitere Ressourcen
- [Offizielle Kubernetes Dokumentation](https://kubernetes.io/docs/)
- [kubectl Cheat Sheet](https://kubernetes.io/docs/reference/kubectl/cheatsheet/)
- [Kubernetes Port-Forwarding](https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/)
---
*Erstellt am: {{ date:2026-02-10 }}*
*Workspace: `gitops`*
@@ -0,0 +1,299 @@
#IT #Container #Open-Source #Cloud
---
## 1. Was ist Kubernetes in einem Satz?
Kubernetes ist ein Open-SourceSystem zur **Orchestrierung von Containern** (z.B. Docker), das die **Bereitstellung, Skalierung und Verwaltung** von Anwendungen automatisiert.
- Entwickelt von Google, heute von der CNCF (Cloud Native Computing Foundation) verwaltet
- Läuft in der Cloud (AWS, Azure, GCP), im Rechenzentrum (OnPrem) oder lokal (z.B. mit kind, minikube)
---
## 2. Warum braucht man Kubernetes?
### 2.1 Ausgangslage ohne Kubernetes
Bei klassischen Server- oder Container-Setups müssen viele Dinge manuell oder mit Skripten gelöst werden:
- Container starten/stoppen
- Lastverteilung zwischen Instanzen
- Neustart fehlerhafter Instanzen
- Rollout neuer Versionen
- Skalierung bei Lastspitzen
- Konfigurationsmanagement und Secrets
- Self-Healing bei Fehlern
### 2.2 Ziele von Kubernetes
Kubernetes löst diese Probleme, indem es:
1. **Deklaratives Modell** nutzt
- Du beschreibst den „Soll-Zustand“ (z.B. „es sollen 3 Instanzen meiner App laufen“).
- Kubernetes sorgt im Hintergrund dafür, dass dieser Zustand erreicht und gehalten wird.
2. **Automatisierung** von:
- Rollouts und Rollbacks
- Skalierung (horizontaler Ausbau: mehr Instanzen)
- Self-Healing (Pods werden bei Absturz neu gestartet)
- Service Discovery & Load Balancing
3. **Abstraktion von Infrastruktur**:
- Egal ob deine Knoten VMs in der Cloud oder bare-metal-Server sind Kubernetes abstrahiert das weg.
---
## 3. Hohe Ebene: Aufbau eines Kubernetes-Clusters
Ein Kubernetes-Cluster besteht grob aus:
- **Control Plane** (Master-Komponenten)
- **Worker Nodes** (wo die Container wirklich laufen)
### 3.1 Control Plane (Steuerungsebene)
Wichtige Komponenten:
- **kube-apiserver**
- Zentraler Einstiegspunkt
- Alle Befehle von `kubectl` und anderen Komponenten laufen über die API ([[kubectl]])
- **etcd**
- Verteilter Key-Value-Store
- Hält den gesamten Cluster-Zustand (z.B. welche Pods, Deployments, ConfigMaps etc.)
- **kube-scheduler**
- Entscheidet, auf welchem Node neue Pods laufen sollen
- Berücksichtigt Ressourcen (CPU, RAM), Constraints, Affinities etc.
- **kube-controller-manager**
- Mehrere Controller (z.B. für Deployments, Nodes, Endpoints)
- Stellt sicher, dass der Ist-Zustand dem Soll-Zustand entspricht („Reconciliation Loop“)
- **cloud-controller-manager** (optional)
- Integration mit Cloud-Anbietern (z.B. Load Balancer in AWS/Azure/GCP anlegen)
### 3.2 Worker Nodes (Arbeitsebene)
Auf jedem Worker laufen:
- **kubelet**
- Agent auf dem Node
- Kommuniziert mit der API und sorgt lokal dafür, dass die Pods wie gewünscht laufen
- **Container Runtime**
- Führt Container aus: z.B. containerd, CRIO, Docker (früher direkt, heute über CRI)
- **kube-proxy**
- Implementiert das Kubernetes-Service-Netzwerk
- Kümmert sich um Weiterleitung von Netzwerkpaketen zu den richtigen Pods
---
## 4. Zentrale Konzepte in Kubernetes
### 4.1 Pod
- Kleinste deploybare Einheit in Kubernetes
- Ein Pod enthält einen oder mehrere Container, die:
- sich IP-Adresse und Ports teilen
- sich lokale Volumes teilen
- Typischerweise: 1 Container pro Pod (plus evtl. Sidecars)
Beispiel: Ein Pod mit einem [[NGINX]] Container:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: my-nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
```
### 4.2 Deployment
- Deklarative Beschreibung von Pods + Skalierung
- Sagt z.B.: „Es sollen 3 identische Replikate dieses Pods laufen“
- Unterstützt Rollouts und Rollbacks (z.B. `kubectl rollout undo`)
Beispiel-Deployment:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-nginx
template:
metadata:
labels:
app: my-nginx
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
```
### 4.3 Service
- Stabile Netzwerk-Adresse (DNS-Name, virtuelle IP) für eine Gruppe von Pods
- Entkoppelt Clients von einzelnen Pod-IP-Adressen
- Typen:
- **ClusterIP**: intern im Cluster
- **NodePort**: nach außen freigegeben über einen Port jedes Nodes
- **LoadBalancer**: Integration mit einem Cloud-Load-Balancer
Beispiel-Service:
```yaml
apiVersion: v1
kind: Service
metadata:
name: my-nginx-service
spec:
type: ClusterIP
selector:
app: my-nginx
ports:
- port: 80
targetPort: 80
```
### 4.4 Namespace
- Logische Unterteilung innerhalb eines Clusters
- Dient zur:
- Trennung von Umgebungen (dev, test, prod)
- Multi-Tenancy
- Ressourcenkontrolle (ResourceQuotas, Limits)
- Standard-Namespace: `default`, daneben z.B. `kube-system`, `kube-public`
### 4.5 ConfigMap & Secret
- **ConfigMap**: Konfiguration (nicht sensibel), z.B. Properties, ENV-Variablen
- **Secret**: sensible Daten (Passwörter, Tokens, Zertifikate)
- Werden in Pods als ENV oder als Files (Volumes) bereitgestellt
### 4.6 Volume & PersistentVolume
- **Volumes**: Daten, die nicht verschwinden, wenn ein Container neu startet
- **PersistentVolume (PV)**: repräsentiert eine physische/Cloud-Speicher-Ressource
- **PersistentVolumeClaim (PVC)**: „Anforderung“ eines Pods an Speicher (Größe, Klasse)
---
## 5. Wie arbeitet Kubernetes? Das „Desired State“-Modell
1. Du definierst Ressourcen (YAML/JSON), z.B.:
- „Deployment mit 3 Replikas meiner App“
- „Service, der auf Port 80 erreichbar ist“
2. Du übernimmt diese Definition per:
```bash
kubectl apply -f deployment.yaml
```
3. Die API speichert diese Definition in **etcd**.
4. Controller und Scheduler beobachten den Zustand und führen eine **Reconciliation Loop** aus:
- Ist-Zustand (z.B. 2 Pods laufen) vs. Soll-Zustand (3 Pods sollen laufen)
- Kubernetes startet einen weiteren Pod
- Fällt ein Pod aus → wird automatisch ersetzt
---
## 6. Typischer Entwickler-Workflow mit Kubernetes
1. **Container-Image bauen**
- z.B. mit Docker oder Buildpacks
2. **Image registrieren**
- In einer Container Registry (Docker Hub, GitHub Container Registry, ECR, GCR…)
3. **Kubernetes-Manifest(e) schreiben**
- Deployment, Service, ConfigMap, Secret, etc.
4. **Deployen**
- `kubectl apply -f .`
- Oder über CI/CD-Pipelines (GitLab CI, GitHub Actions, Argo CD, Jenkins etc.)
5. **Monitoring & Logging**
- Über Tools wie Prometheus, Grafana, ELK/EFK-Stack, Loki, etc.
---
## 7. Kubernetes im Ökosystem / Erweiterungen
Kubernetes ist eine Basis, auf der vieles aufbaut:
- **Helm**
- „Package Manager“ für Kubernetes
- Erleichtert das Installieren komplexer Anwendungen (Charts)
- **Ingress & Ingress Controller**
- HTTP/HTTPS-Routing auf Services
- Ermöglicht virtuelle Hosts, Pfad-basiertes Routing usw.
- **Service Mesh (z.B. Istio, Linkerd)**
- Feinere Kontrolle über Traffic, Observability, Security (mTLS)
- **Operators**
- Kubernetes-Erweiterungen, die komplexe Anwendungen als „Custom Resources“ managen (z.B. Datenbanken)
- **GitOps (z.B. Argo CD, Flux)**
- Zustände des Clusters werden aus Git-Repositories synchronisiert
---
## 8. Vorteile von Kubernetes
- Hohe **Portabilität** über verschiedene Infrastrukturen
- **Automatisierte Skalierung** und Self-Healing
- **Standardisierte Schnittstellen** (API-first)
- Große **Community** und reiches Ökosystem
- Gut geeignet für **Microservices** und verteile Systeme
---
## 9. Herausforderungen und Komplexität
- **Steile Lernkurve**: viele Konzepte (Pods, Deployments, Services, Ingress, RBAC, Storage…)
- **Betrieb** eines eigenen Clusters ist nicht trivial
- Viele Unternehmen nutzen Managed Services: GKE, AKS, EKS, OpenShift, Rancher etc.
- **Observability**: Logs, Metrics, Tracing sind komplexer als bei einer einzigen VM
- **Sicherheit** (RBAC, NetworkPolicies, Secrets-Management) erfordert Planung
---
## 10. Wie kann man praktisch starten?
Konkrete Schritte, um anzufangen:
1. **Lokale Umgebung**:
- `kind` (Kubernetes in Docker)
- `minikube` oder `k3d`
2. **Übungen**:
- Einen einfachen Webserver als Deployment & Service bereitstellen
- Mit `kubectl get`, `describe`, `logs` spielen
- Scaling testen: `kubectl scale deployment my-deployment --replicas=5`
- Eine neue Version deployen und Rollback ausprobieren
3. **Doku & Lernressourcen**:
- Offizielle Doku: https://kubernetes.io/docs/
- Interaktive Tutorials: Katacoda-ähnliche Labs, Kubernetes Bootcamps, z.B. von Cloud-Anbietern
@@ -0,0 +1,25 @@
„Layer7Logik“ bezieht sich auf Entscheidungen/Routing auf Basis der **Anwendungsebene** (Layer 7 im OSI-Modell).
Kurz zum Kontext:
- **Layer 3 (Netzwerk)**: IP-Adressen
- **Layer 4 (Transport)**: TCP/UDP, Ports (z.B. Port 80, 443)
- **Layer 7 (Anwendung)**: HTTP, HTTPS, gRPC, SMTP etc. also „Inhalt“ der Anfrage
**Layer4Routing**:
Es wird nur nach IP + Port entschieden. Beispiel:
- Alles an `10.0.0.5:80` geht zu Service A.
Der Proxy/Loadbalancer „sieht“ nicht, ob das `/api` oder `/shop` ist.
**Layer7Logik**:
Der Proxy versteht das Protokoll (z.B. HTTP) und kann anhand von Anwendungsdaten entscheiden:
- Hostname: `api.example.com` → Service A, `shop.example.com` → Service B
- Pfad: `/api` → Backend 1, `/app` → Backend 2
- HTTP-Header: bestimmter `User-Agent`, `X-Feature-Flag` → anderes Routing
- Cookies / Session: z.B. „User ist in A/B-Test-Gruppe → anderes Backend“
- Authentifizierung / [[JWT token]] prüfen, bevor weitergeleitet wird
- TLS-Termination: HTTPS entschlüsseln, weiter innen nur HTTP sprechen
Im Kubernetes-Ingress-Kontext heißt „Layer7Logik“ also:
Der Ingress-Controller trifft Routing- und Sicherheitsentscheidungen **auf Basis von HTTP(S)-Details** (Host, Pfad, Header, Cookies usw.), nicht nur auf Basis von IPs und Ports.
@@ -0,0 +1,430 @@
## 1. Grundidee: Was ist nginx gerade im PythonKontext?
nginx („engine x“) ist ein **Webserver** und **Reverse Proxy**, der:
- HTTP(S)-Anfragen aus dem Internet annimmt
- statische Dateien (HTML, CSS, Bilder, JS) direkt ausliefert
- Anfragen für **dynamische Inhalte** (z.B. deine PythonApp) an einen **Anwendungsserver** weiterleitet (z.B. Gunicorn, uWSGI, [[uvicorn]])
Im PythonKontext wird nginx fast immer als **„Vorderseite“ (Frontend) vor einer PythonWebanwendung** eingesetzt.
Typischer Aufbau:
```text
Browser des Nutzers -> nginx -> Gunicorn/uWSGI/uvicorn -> Python-App (Django, Flask, FastAPI, ...)
(Port 80/443) (lokaler Port, z.B. 8000)
```
---
## 2. Einordnung in die Webwelt: Grundbegriffe
Damit nginx einzuordnen ist, müssen ein paar Begriffe klar sein:
### 2.1 Webserver
Ein **Webserver**:
- läuft auf einem Rechner (Server)
- „lauscht“ auf Port 80 (HTTP) oder 443 (HTTPS)
- nimmt HTTP-Anfragen entgegen und schickt HTTP-Antworten zurück
Beispiele:
- **nginx**
- **Apache HTTP Server**
- (leichtere) Caddy, lighttpd
### 2.2 Application Server / WSGI-/ASGI-Server
Ein **Application Server** führt deine **Web-App** aus, also deinen Python-Code.
- Für klassische synchronen Python-Webapps: **WSGI**-Server
- z.B. **[[Gunicorn]]**, **uWSGI**, mod_wsgi
- Für moderne, asynchrone Apps: **ASGI**-Server
- z.B. **[[uvicorn]]**, **[[hypercorn]]**, Daphne
Der App-Server:
- spricht mit deinem Python-Framework (Django, Flask, [[FastAPI]], etc.)
- versteht Anfragen im WSGI/ASGI-Format
- erzeugt dynamische Antworten (z.B. JSON, HTML aus Templates)
### 2.3 Python-Webframework (Django, Flask, [[FastAPI]] …)
Ein **Framework** ist deine Programmierbibliothek, mit der du die Web-App baust:
- Django: „Vollausstattung“ (ORM, Admin, Auth, etc.)
- Flask: minimaler Kern, viel per Erweiterung
- [[FastAPI]]: modern, async, stark bei APIs
**Das Framework ist nicht der Webserver.**
Es definiert nur, wie dein Code auf Anfragen reagieren soll.
---
## 3. Abgrenzung: nginx vs. verwandte Begriffe
### 3.1 nginx vs. Apache
Beide sind **Webserver**, Unterschiede grob:
- **nginx**
- schnell bei vielen gleichzeitigen Verbindungen
- ressourcensparend (eventbasiert)
- sehr gut als Reverse Proxy, Load Balancer, TLS-Terminator
- **Apache**
- älter, sehr weit verbreitet
- modulbasiert, viel Legacy
- kann PHP & Co. direkt ausführen (mod_php, etc.)
Im modernen Python-Umfeld: **nginx + Gunicorn/[[uvicorn]]** ist ein sehr gängiges Setup.
### 3.2 nginx vs. [[Gunicorn]]/uWSGI/[[uvicorn]]
- **nginx**: Webserver / Reverse Proxy
- **[[Gunicorn]]/uWSGI/[[uvicorn]]**: Python-Application-Server
nginx:
- kümmert sich um HTTP(S), TLS, statische Dateien, Load Balancing
- schickt Anfragen an den Application-Server weiter
[[Gunicorn]]/[[uvicorn]]:
- startet deine Python-App
- verarbeitet die Anfragen logikseitig
- rendert Templates, greift auf Datenbanken zu, etc.
### 3.3 nginx vs. Django/Flask/[[FastAPI]]
- nginx: Infrastruktur-Komponente (Server)
- Django/Flask/[[FastAPI]]: Bibliotheken, mit denen du deinen Code schreibst
Eine typische Kombi:
```text
nginx + Gunicorn + Django
nginx + uvicorn + FastAPI
nginx + uWSGI + Flask
```
Jede Komponente hat ihren klaren Aufgabenbereich.
---
## 4. Welche Probleme löst nginx im Python-Setup?
### 4.1 Sichere und stabile Auslieferung deiner Python-Webapp
Problem:
Die eingebaute Entwicklungsserver in Django/Flask sind nur für **lokale Entwicklung** gedacht:
- wenig performant
- kaum Sicherheitsfeatures
- nicht für viele gleichzeitige Nutzer ausgelegt
Lösung:
nginx + App-Server (Gunicorn/uvicorn):
- nginx nimmt alle Anfragen entgegen
- Python-App läuft hinter nginx auf einem internen Port
- Anwendung ist stabiler, sicherer, skalierbarer
### 4.2 Auslieferung statischer Dateien
Problem:
Python-Frameworks sind nicht optimiert, um Millionen von statischen Dateien schnell auszuliefern.
Lösung:
- nginx kann statische Dateien extrem effizient ausliefern
- Python-App wird entlastet
**Beispiel:** Django-Setup:
```text
Browser -> nginx -> (statische Dateien: /static/) direkt von nginx
-> (dynamische URLs: /api/, /admin/) an Gunicorn/Django
```
### 4.3 HTTPS / TLS-Termination
Problem:
Du willst deine Seite unter **https://deinedomain.de** mit Zertifikat ausliefern.
Python-Application-Server kümmern sich eher nicht um Zertifikate.
Lösung:
- nginx bietet HTTPS/TLS an (inkl. Lets Encrypt-Integration)
- entschlüsselt eingehende Anfragen
- leitet sie dann intern als HTTP an Gunicorn/uvicorn weiter
So muss sich deine Python-App nicht um Zertifikate kümmern.
### 4.4 Load Balancing (Lastverteilung)
Problem:
Eine einzelne Instanz deiner Python-App reicht nicht bei hoher Last.
Lösung:
- nginx kann Anfragen auf mehrere App-Server verteilen:
```text
Browser -> nginx -> Gunicorn Instanz 1
-> Gunicorn Instanz 2
-> Gunicorn Instanz 3
```
Damit erreichst du höhere Verfügbarkeit und Kapazität.
### 4.5 Reverse Proxy / Schutz der App
Problem:
Du willst deine App nicht direkt ins Internet hängen (Sicherheitsrisiko, private Ports).
Lösung:
- nginx steht „davor“ und leitet nur definierte Anfragen durch
- interne Ports (z.B. 8000) sind von außen nicht erreichbar
- nginx kann zusätzliche Security-Header, Ratelimits, IP-Filter etc. einsetzen
---
## 5. Herausforderungen bei der Arbeit mit nginx
### 5.1 Konfigurationssyntax & -struktur
- nginx wird über Textdateien konfiguriert (z.B. `/etc/nginx/nginx.conf` und `sites-available/...`)
- die Syntax ist am Anfang ungewohnt:
- `http`, `server`, `location`, `upstream`, `listen`, etc.
- Fehler in der Konfiguration führen dazu, dass nginx nicht startet oder falsch weiterleitet
Praxis-Hinweise:
```bash
sudo nginx -t # Konfiguration testen
sudo systemctl reload nginx # Konfiguration neu laden
```
### 5.2 Rechte & Pfade (Linux-Dateisystem)
Probleme:
- nginx läuft als bestimmter Benutzer (z.B. `www-data`)
- Python-App läuft evtl. als anderer Benutzer (z.B. `myapp`)
- Zugriffsrechte auf Dateien/Ordner (Logs, statische Dateien) müssen passen
Beispiel:
Wenn statische Dateien unter `/var/www/myapp/static/` liegen, muss der nginx-User Lesezugriff haben.
### 5.3 Fehlersuche (Debugging)
- Fehler können an mehreren Stellen auftreten:
- DNS / Domain falsch
- nginx-Konfiguration fehlerhaft
- App-Server (Gunicorn/uvicorn) läuft nicht
- Python-App wirft Fehler
Praxis-Tipp:
- in nginx-Logs schauen:
- `/var/log/nginx/access.log`
- `/var/log/nginx/error.log`
- in App-Logs schauen
- Ports prüfen: `ss -tulpen` oder `netstat -tulpen`
### 5.4 Performance-Tuning
Fortgeschrittener, aber wichtig bei größerem Traffic:
- wie viele Worker-Prozesse nginx nutzt
- Keep-Alive-Einstellungen
- Buffergrößen
- Cache-Konfiguration für statische Inhalte
Am Anfang reicht meist die Standardkonfiguration, später optimiert man bei Bedarf.
---
## 6. Praxisnahe Beispiele
### 6.1 Minimalbeispiel: Flask-App hinter nginx + Gunicorn
**1. Eine einfache Flask-App (Python)**
Datei: `app.py`
```python
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "Hallo, Welt! Das kommt aus Flask hinter nginx."
```
Start des App-Servers (Gunicorn):
```bash
pip install flask gunicorn
gunicorn -w 3 -b 127.0.0.1:8000 app:app
# -w 3: 3 Worker
# -b 127.0.0.1:8000: lauscht auf Port 8000 nur lokal
```
**2. nginx-Konfiguration (vereinfacht)**
Datei: z.B. `/etc/nginx/sites-available/myflaskapp`:
```nginx
server {
listen 80;
server_name example.com; # deine Domain oder IP
# Statische Dateien (wenn du welche hast)
# root /var/www/myflaskapp; # falls du HTML/Assets direkt ablegen willst
location / {
proxy_pass http://127.0.0.1:8000; # Gunicorn
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
Dann:
```bash
sudo ln -s /etc/nginx/sites-available/myflaskapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```
Ablauf:
1. Browser ruft `http://example.com/` auf
2. nginx nimmt Anfrage auf Port 80 entgegen
3. nginx leitet an `http://127.0.0.1:8000` weiter (Gunicorn/Flask)
4. Flask antwortet mit „Hallo, Welt“
5. nginx sendet diese Antwort an den Browser zurück
### 6.2 Beispiel: Django mit statischen Dateien
**1. Django-Setup (stark vereinfacht)**
In `settings.py`:
```python
STATIC_URL = "/static/"
STATIC_ROOT = "/var/www/mydjangoproject/static/"
```
Danach statische Dateien sammeln:
```bash
python manage.py collectstatic
```
**2. nginx-Konfiguration (Ausschnitt)**
```nginx
server {
listen 80;
server_name example.com;
# Statische Dateien direkt von nginx
location /static/ {
alias /var/www/mydjangoproject/static/;
access_log off;
expires 30d;
}
# Alles andere an Django via Gunicorn
location / {
proxy_pass http://127.0.0.1:8001; # hier läuft Gunicorn
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
Vorteil:
- statische Inhalte kommen extrem schnell von nginx
- Django/Gunicorn verarbeitet nur „echte“ App-Logik
### 6.3 Beispiel: HTTPS mit Lets Encrypt (Konzept)
Mit Tools wie **certbot** kannst du für nginx kostenlos TLS-Zertifikate holen.
Grobe Schritte:
```bash
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com
```
certbot:
- holt Zertifikat
- passt nginx-Konfiguration an (Port 443, SSL-Parameter)
- richtet automatische Erneuerung ein
nginx-Konfiguration enthält danach z.B.:
```nginx
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8000;
...
}
}
```
Damit ist deine Python-App per HTTPS erreichbar.
---
## 7. Zusammenfassung
- **nginx** ist ein leistungsfähiger Webserver und Reverse Proxy, der im Python-Kontext typischerweise:
- vor deiner Python-Webanwendung sitzt
- HTTP(S) abwickelt
- statische Dateien effizient ausliefert
- Anfragen an einen Python-Application-Server (Gunicorn, uWSGI, uvicorn) weiterleitet
- TLS/HTTPS, Load Balancing, Security-Features bereitstellt
- **Abgrenzung**:
- nginx ≠ Python-Framework (Django/Flask/[[FastAPI]])
- nginx ≠ Application-Server (Gunicorn/uvicorn)
- nginx = Webserver/Reverse Proxy
- **Gelöste Probleme**:
- sichere Produktion anstelle von Entwicklungsservern
- Performance für statische Inhalte
- TLS/HTTPS, Lastverteilung, Schutz der App
- **Herausforderungen**:
- Konfigurationsdateien verstehen
- Rechte & Pfade korrekt setzen
- Fehler systematisch debuggen
- bei hoher Last Performance tunen
@@ -0,0 +1,360 @@
Im Folgenden bekommst du eine Einführung in OAuth 2, so dass du danach:
- weißt, was OAuth 2 grundsätzlich ist,
- es von verwandten Konzepten wie „Login mit Google“, OpenID Connect oder reiner Authentifizierung unterscheiden kannst,
- verstehst, welche Probleme OAuth 2 löst und welche neuen Herausforderungen es mit sich bringt,
- und ein paar praxisnahe Szenarien im Kopf hast.
---
## 1. Grundsätzliche Definition: Was ist OAuth 2?
**Kurze Definition**:
OAuth 2 ist ein *Autorisierungs*-Framework. Es regelt, wie eine Anwendung (Client) **im Namen eines Benutzers** sicher auf Ressourcen (z.B. APIs, Daten) zugreifen kann, **ohne dass die Anwendung das Passwort des Benutzers kennen muss**.
Es geht also primär um:
- **Zugriffsrechte (Authorization)**
- **Delegation**: „Ich (Nutzer) erlaube App X, auf meine Daten bei Dienst Y zuzugreifen.“
### Zentrales Prinzip
Statt:
- Benutzer gibt sein Passwort direkt bei jeder Drittanbieter-App ein
nutzt man:
- Benutzer loggt sich beim **vertrauenswürdigen Dienst** ein (z.B. Google, GitHub, dein Unternehmens-Identity-Server)
- Dieser Dienst stellt ein **Token** aus (eine Art Eintrittskarte)
- Drittanbieter-App nutzt dieses Token, um beim API-Server Zugriff zu bekommen
Dadurch muss die Drittanbieter-App nie das Passwort sehen sie bekommt **nur einen begrenzten, kontrollierten Zugriff**.
---
## 2. Die wichtigsten Rollen in OAuth 2
Um Beispiele zu verstehen, braucht man die Standardrollen:
1. **Resource Owner**
Der Besitzer der Daten/Ressourcen meist der **Benutzer**.
2. **Client**
Die Anwendung, die im Namen des Benutzers zugreifen möchte
(z.B. eine mobile App, eine Web-App, ein Backend-Service).
3. **Resource Server**
Die API/das System, das die geschützten Ressourcen bereitstellt
(z.B. Google Calendar API, GitHub API, Unternehmens-REST-API).
4. **Authorization Server**
Der Server, der:
- den Benutzer authentifiziert (z.B. Login-Formular) und
- **Tokens** ausstellt (Access Tokens, optional Refresh Tokens).
Oft sind Authorization Server und Resource Server derselbe technische Dienst, aber **konzeptionell** werden sie getrennt betrachtet.
---
## 3. Grund-Mechanik: Wie läuft ein OAuth-2-Flow ab?
Stark vereinfacht am typischen Web-Szenario:
1. Benutzer nutzt eine Drittanbieter-App (Client) und klickt z.B. auf:
„Verbinde dich mit meinem Google-Kalender“.
2. Client leitet den Browser zum **Authorization Server** (z.B. accounts.google.com) weiter:
- mit Angaben wie: „Diese App möchte Zugriff auf Kalenderdaten“.
3. Benutzer loggt sich **beim Authorization Server** ein (falls nicht schon eingeloggt).
4. Benutzer bekommt eine Seite angezeigt:
„Die Anwendung X möchte auf Ihre Kalenderdaten zugreifen. Erlauben? (Ja/Nein)“
5. Wenn Benutzer zustimmt:
- Authorization Server schickt den Benutzer zurück zur App
- Die App bekommt einen **Authorization Code** (bei einem gängigen Flow).
6. Die App tauscht diesen Code im Hintergrund beim Authorization Server gegen ein **Access Token** (und evtl. ein **Refresh Token**) ein.
7. Die App nutzt das Access Token, um beim **Resource Server** (z.B. Google Calendar API) Daten abzufragen.
Der Benutzer muss sein **Passwort nur beim Authorization Server** eingeben nicht bei der Drittanbieter-App.
---
## 4. Abgrenzung zu ähnlichen / verwandten Begriffen
### 4.1 OAuth 2 (Authorization) vs. Authentifizierung (Login)
**Authentifizierung**: „Wer bist du?“
**Autorisierung**: „Worauf darfst du zugreifen?“
- OAuth 2 löst formal **Autorisierung** (Delegation von Zugriffsrechten).
- Viele Systeme nutzen OAuth 2 aber **im Zusammenhang mit Login**, was verwirrend sein kann.
Ein Login mit Google, bei dem eine Anwendung am Ende weiß „dieser User ist Max Mustermann“, basiert meist auf **OpenID Connect**, das **auf OAuth 2 aufsetzt**.
### 4.2 OAuth 2 vs. OpenID Connect (OIDC)
- **OAuth 2**: Spezifiziert, wie Clients **Access Tokens** bekommen, um auf APIs zuzugreifen.
- **OpenID Connect**: Erweiterung auf Basis von OAuth 2, um **Identität** zu transportieren.
OIDC liefert zusätzlich:
- ein **ID Token** (meist ein [[JWT token]]), das Informationen wie:
- User-ID
- E-Mail
- Name
enthält.
Praxis-Beispiele:
- „Mit Google anmelden“ (Login) → **OpenID Connect**
- „Google Kalender-API nutzen“ → **OAuth 2** (Autorisierung für API-Zugriff)
### 4.3 OAuth 2 vs. API-Key
**API-Key**:
- Meist ein statischer Schlüssel, der im Client eingebaut ist.
- Unterscheidet nicht zwischen verschiedenen Benutzern.
- Hat wenig feingranulare Rechte (oft: „alles oder nichts“).
- Sicherheitsrisiko bei Leaks (z.B. im Frontend-Code).
**OAuth 2**:
- Nutzerbezogen (Access Token repräsentiert den Benutzer/das Delegationsrecht).
- Token haben meist begrenzte Lebensdauer.
- Zugriffsrechte (Scopes) sind feiner steuerbar.
### 4.4 OAuth 2 vs. SAML
- **SAML**: Älterer Standard, XML-basiert, häufig in Unternehmensumgebungen für SSO verwendet.
- **OAuth 2 / OIDC**: JSON/HTTP-basiert, leichtergewichtig, stark im Web- und Mobile-Bereich verbreitet.
Grober Merksatz:
- SAML: klassische Unternehmen, Single Sign-On im Browser, ältere Infrastruktur.
- OAuth 2 + OIDC: moderne Web-/Mobile-Apps, REST-APIs, Microservices.
---
## 5. Welche Probleme löst OAuth 2?
### 5.1 Vermeidung von Passwortweitergabe an Drittanbieter
Früher:
Eine App wollte auf Gmail zugreifen => Benutzer musste **sein Gmail-Passwort** in dieser App eingeben.
Risiken:
- App könnte Passwort speichern oder missbrauchen.
- Bei Passwortänderung müsste der Benutzer alles neu einrichten.
- Anbieter (Google) hat keine Kontrolle, welche App das tut.
Mit OAuth 2:
- Benutzer loggt sich nur bei Google ein.
- Drittanbieter-App erhält nur ein **Token mit begrenzten Rechten**, kein Passwort.
**Praxisbeispiel**:
Eine To-Do-App möchte deine Google Kalender-Einträge anzeigen:
Du klickst „Mit Google verbinden“, wirst zu Google geleitet, bestätigst die Berechtigungen und die App sieht danach deine Kalender ohne dein Passwort zu kennen.
### 5.2 Feingranulare Zugriffsrechte (Scopes)
Mit **Scopes** kann eingeschränkt werden, worauf eine App zugreifen darf.
Beispiele:
- `read_calendar`: nur Leserechte auf Kalender
- `write_calendar`: Schreibrechte auf Kalender
- `email`: Zugriff auf deine E-Mail-Adresse
- `profile`: Zugriff auf deine Basisprofildaten
So kann der Benutzer (und auch der Resource Server) klar kontrollieren:
- Eine App darf z.B. **nur lesen**, nicht schreiben.
- Eine App darf **nur auf E-Mail und Profil**, nicht auf Kontakte oder Drive zugreifen.
### 5.3 Zeitlich begrenzte Tokens
**Access Tokens** sind typischerweise kurzlebig (z.B. 560 Minuten).
- Wenn ein Token geleakt wird, ist der Schaden zeitlich begrenzt.
- Über Revocation-Mechanismen kann der Zugriff vorzeitig beendet werden.
Optional gibt es **Refresh Tokens**:
- Länger gültig
- Dienen dazu, neue Access Tokens zu holen
- Können vom Authorization Server gezielt deaktiviert werden (z.B. bei Kompromittierung).
### 5.4 Single Sign-On / bessere User Experience (in Kombination mit OIDC)
In Kombination mit OIDC und Single-Sign-On-Konzepten:
- Benutzer loggt sich einmal beim zentralen Identity Provider ein.
- Mehrere Anwendungen können dann in einer Session auf Tokens zugreifen, ohne den Benutzer jedes Mal neu einzuloggen.
---
## 6. Typische OAuth-2-Flows (vereinfacht)
Es gibt verschiedene **„Flows“**, je nach Art des Clients und Nutzungsszenario. Die wichtigsten:
### 6.1 Authorization Code Flow (heute mit PKCE)
Typisch für:
- Web-Anwendungen mit Backend
- Single Page Applications (mit PKCE)
- Mobile Apps
Ablauf (vereinfacht, ohne technische Details):
1. Anwendung leitet Benutzer zum Authorization Server.
2. Benutzer loggt sich ein und stimmt zu.
3. Authorization Server schickt **Authorization Code** an die Anwendung (über Redirect).
4. Anwendung tauscht Code gegen ein **Access Token** (und optional Refresh Token).
**PKCE** (Proof Key for Code Exchange) ist eine Sicherheits-Erweiterung, um Code-Diebstahl zu verhindern, insbesondere bei mobilen/Browser-basierten Apps.
### 6.2 Client Credentials Flow
Für:
- Machine-to-Machine-Kommunikation (kein Benutzer)
- Hintergrundprozesse, Microservices, Server-zu-Server
Hier gibt es keinen Benutzer.
Der Client identifiziert sich selbst (z.B. mit Client ID + Client Secret) beim Authorization Server und bekommt ein Access Token, um auf eine API zuzugreifen.
**Beispiel**:
Ein Backend-Service ruft periodisch eine interne Unternehmens-API auf, um Daten zu synchronisieren.
### 6.3 Device Code Flow
Für Geräte ohne vollwertigen Browser oder ohne komfortable Eingabemöglichkeit, wie:
- Smart-TVs
- Konsolen
- IoT-Geräte
Ablauf:
- Gerät zeigt einen Code und eine URL an (z.B. „Bitte gehen Sie auf https://example.com/device und geben Sie Code ABCD ein“).
- Benutzer geht an seinem Smartphone/PC auf diese URL, loggt sich dort ein und bestätigt.
- Gerät bekommt anschließend ein Token und kann auf die Ressource zugreifen.
---
## 7. Herausforderungen und typische Stolperfallen
### 7.1 OAuth 2 ist komplex und flexibel
OAuth 2 ist sehr flexibel das ist Stärke und Schwäche zugleich:
- Viele Optionen & Erweiterungen → schnell unübersichtlich.
- Viele Entscheidungen zu treffen: Flows, Token-Formate, Scopes, Lifetimes, PKCE, etc.
Für Einsteiger wirkt es oft „überdimensioniert“, vor allem wenn man nur „einen einfachen Login“ braucht (wo eigentlich OIDC gefragt ist).
### 7.2 Verwechslung von OAuth 2 und Login
Weil viele große Anbieter beides kombiniert haben („Login mit Google“), entsteht oft:
- „OAuth 2 ist ein Login-Protokoll.“ → **Formal falsch**, es ist ein Autorisierungsframework.
- Für „Login“ verwendet man **OpenID Connect**, auch wenn technisch OAuth-2-Mechanismen verwendet werden.
Konsequenz:
Fehlkonzeptionen in Projekten, z.B. versucht man reine OAuth-2-Tokens zu nutzen, um Identität abzuleiten, statt OIDC zu verwenden.
### 7.3 Sicherheitsrisiken bei falscher Implementierung
Einige typische Fehler:
- **Tokens in URLs weitergeben** → landen in Logs, Browser-History, Referrer-Headern.
- **Implicit Flow** für Single-Page-Apps ohne ausreichende Sicherheitsmaßnahmen
→ gilt inzwischen als überholt; empfohlen wird Authorization Code Flow mit PKCE.
- **Keine Einschränkung der Redirect-URIs** → Angreifer können Redirect-URIs manipulieren und Tokens abfangen.
- **Zu lange gültige Tokens** → höheres Risiko bei Leaks.
- **Speichern von Tokens im unsicheren Speicher** (z.B. localStorage in Browsern) → anfällig für XSS.
### 7.4 Komplexität für Endnutzer
Auch für Endnutzer ist die Zustimmung manchmal nicht klar:
- „Diese App möchte auf Ihr Profil, Ihre Kontakte, Ihre Dateien, Ihre E-Mails zugreifen.“
→ Viele klicken aus Gewohnheit auf „Zulassen“, ohne zu verstehen, was das bedeutet.
Das ist eher ein UX-/Privacy-Thema, aber eng mit OAuth 2 verbunden, da die Darstellung der **Scopes** oft technisch und verwirrend ist.
---
## 8. Praxisnahe Beispiele
### Beispiel 1: „Mit Google anmelden“ in einer Web-App
**Situation**:
Du entwickelst eine Web-App, in der sich Nutzer anmelden können. Statt ein eigenes Benutzerkontensystem aufzubauen, willst du „Login mit Google“ anbieten.
**In Wahrheit passiert (typisch)**:
- Die App nutzt **OpenID Connect**:
- OAuth 2 regelt den Token-Flow.
- OIDC liefert ein ID Token mit Infos über den Benutzer.
- Nutzer sieht: Google-Login, eine Consent-Seite, und wird danach in deine App zurückgeleitet.
- Deine App bekommt:
- ein **ID Token** (zur Identifikation des Nutzers)
- ein **Access Token** (um z.B. zusätzlich auf Google APIs zuzugreifen, falls gewünscht).
**OAuth-2-Aspekt**:
Der eigentliche Mechanismus, wie Access Token ausgestellt werden, ist OAuth 2.
### Beispiel 2: Drittanbieter-Tool liest GitHub-Repositories
**Situation**:
Ein Build-Tool oder eine CI/CD-Plattform möchte deine privaten GitHub-Repositories lesen, um Builds auszulösen.
Ablauf:
1. In der CI/CD-Plattform klickst du „Mit GitHub verbinden“.
2. Du wirst zu GitHub weitergeleitet, loggst dich ein.
3. GitHub zeigt dir eine Seite:
„Tool X möchte Zugriff auf:
- Ihre öffentlichen und privaten Repositories
- Ihre Webhooks
…“
4. Du erlaubst.
5. Die CI/CD-Plattform erhält ein Access Token mit bestimmten **Scopes** (z.B. `repo`).
**OAuth-2-Aspekt**:
- Das Access Token erlaubt der CI/CD-Plattform, im Namen deines GitHub-Accounts zu agieren, innerhalb des erlaubten Scopes.
### Beispiel 3: Unternehmensinternes Microservice-System
**Situation**:
In einer Microservice-Architektur gibt es:
- einen zentralen Authorization Server (z.B. Keycloak, Auth0, Azure AD),
- viele Services, die interne APIs bereitstellen.
Szenario:
- Ein Frontend bekommt vom Authorization Server (über einen Login) ein Access Token.
- Dieses Access Token wird vom Frontend bei Aufrufen an das API-Gateway oder direkt an Microservices mitgeschickt.
- Microservices verifizieren das Token und entscheiden anhand von Scopes/Rollen, ob der Zugriff erlaubt ist.
**OAuth-2-Aspekt**:
- Zugriffskontrolle wird zentralisiert.
- Jeder Service muss nicht mehr selbst Benutzer verwalten, sondern nur Access Tokens prüfen.
---
## 9. Zusammenfassung in Stichpunkten
- **OAuth 2** ist ein **Autorisierungs-Framework** (nicht direkt ein Login-Protokoll).
- Es ermöglicht, dass **Drittanbieter-Apps im Namen eines Nutzers** auf Ressourcen zugreifen können, ohne das Passwort des Nutzers zu kennen.
- Wichtige Rollen: **Resource Owner**, **Client**, **Resource Server**, **Authorization Server**.
- Es arbeitet mit **Tokens** (Access Tokens, optional Refresh Tokens) und **Scopes** (feingranulare Rechte).
- Verwandte Standards:
- **OpenID Connect**: für Authentifizierung/Identität (baut auf OAuth 2 auf).
- **SAML**: alternative, ältere Lösung v.a. für SSO in Unternehmen.
- Es löst Probleme wie:
- Passwortweitergabe an Drittanbieter
- Fehlende Feingranularität von Zugriffsrechten
- Mangelnde Kontrolle über Zugriffsdelegation
- Herausforderungen:
- Komplexität und viele Optionen
- Verwechslungsgefahr mit Authentifizierung
- Sicherheitsrisiken bei falscher Implementierung
- UX/Verständlichkeit von Zustimmungsdialogen
- Praxis:
- „Mit Google/GitHub/Facebook anmelden“
- Drittanbieter-Apps, die auf APIs zugreifen
- Microservice-Systeme mit zentralem Identity & Access Management
---
@@ -0,0 +1,530 @@
#infrastructure #Cloud
## 1. Was ist Terraform?
Terraform ist ein Open-Source-Tool (ursprünglich MIT, seit 2023 Business Source License, BSL) von HashiCorp zur **deklarativen** Beschreibung und Verwaltung von Infrastruktur als Code (Infrastructure as Code, IaC).
Mit Terraform kannst du:
- Infrastruktur in Cloud-Providern (AWS, Azure, GCP, …), On-Premise und weiteren Systemen **beschreiben** (als Code).
- Aus dieser Beschreibung eine **gewünschte Zielkonfiguration** (Desired State) definieren.
- Terraform berechnet dann, **welche Änderungen nötig sind**, um vom Ist-Zustand zum Soll-Zustand zu gelangen.
- Diese Änderungen werden mit `terraform apply` **automatisch ausgeführt**.
Terraform ist besonders stark in:
- **Multi-Cloud- und Hybrid-Szenarien**
- **Reproduzierbaren Umgebungen** (z.B. Dev, Test, Prod)
- **Versionierbarer Infrastruktur** (Git)
- **Team-Kollaboration** an Infrastruktur
---
## 2. Grundkonzepte von Terraform
Die wichtigsten Bausteine:
### 2.1 Provider
Provider sind die „Treiber“, mit denen Terraform mit einem externen System spricht, z.B.:
- `aws` Amazon Web Services
- `azurerm` Microsoft Azure
- `google` Google Cloud
- `kubernetes` Kubernetes-Cluster
- `helm`, `docker`, `vault`, `github`, viele weitere
In Terraform-Code bindet man einen Provider ein, z.B.:
```hcl
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "eu-central-1"
}
```
### 2.2 Ressourcen
**Ressourcen** (`resource`) sind die eigentlichen Infrastruktur-Objekte, z.B.:
- `aws_instance` (EC2-VM)
- `aws_s3_bucket`
- `azurerm_resource_group`
- `google_compute_instance`
Beispiel:
```hcl
resource "aws_s3_bucket" "example" {
bucket = "mein-terraform-bucket-12345"
acl = "private"
}
```
`aws_s3_bucket` ist der Ressourcentyp, `"example"` der Name innerhalb der Terraform-Konfiguration.
### 2.3 Datenquellen (Data Sources)
`data`-Blöcke lesen Informationen aus einer bestehenden Umgebung, ohne etwas zu verändern.
```hcl
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
}
owners = ["099720109477"] # Canonical
}
```
Die Daten können dann in Ressourcen verwendet werden.
### 2.4 Variablen und Outputs
**Variablen** (`variable`) erlauben Parametrisierung:
```hcl
variable "region" {
type = string
default = "eu-central-1"
description = "AWS Region"
}
```
Aufgerufen z.B.: `var.region`.
**Outputs** (`output`) geben wichtige Informationen aus (z.B. IP-Adressen):
```hcl
output "instance_ip" {
value = aws_instance.web.public_ip
}
```
### 2.5 Module
Module sind wiederverwendbare Bausteine von Terraform-Konfigurationen (eine Art „Bibliothek“ von Infrastruktur).
- Ein Modul ist einfach ein Ordner mit `.tf`-Dateien.
- Man kann eigene Module oder Community-Module nutzen (z.B. aus dem Terraform Registry).
Beispiel Nutzung eines Moduls:
```hcl
module "network" {
source = "./modules/network"
vpc_cidr = "10.0.0.0/16"
}
```
Oder:
```hcl
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.0.0"
name = "main-vpc"
cidr = "10.0.0.0/16"
azs = ["eu-central-1a", "eu-central-1b"]
}
```
### 2.6 Terraform State
Terraform hält den Zustand der verwalteten Ressourcen in einer **State-Datei** (`terraform.tfstate`) fest.
- Der State ist die „Wahrheit“, mit der Terraform den Ist-Zustand kennt.
- Daran erkennt Terraform, welche Ressource es schon erstellt hat und wie deren IDs, Attribute usw. sind.
- Änderungen am Code werden mit dem State abgeglichen → Terraform generiert einen Plan.
State kann liegen:
- lokal: `terraform.tfstate` im Projektordner
- remote (empfohlen für Teams): z.B. in S3, Azure Storage, GCS, Terraform Cloud, etc.
Beispiel Backend-Konfiguration (Remote State mit S3):
```hcl
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "prod/terraform.tfstate"
region = "eu-central-1"
}
}
```
---
## 3. Typischer Terraform-Workflow
### 3.1 Projektstruktur
Beispiel:
```text
.
├── main.tf # Ressourcen, Module
├── variables.tf # Variablen
├── outputs.tf # Outputs
└── providers.tf # Provider / Backend
```
### 3.2 Wichtige Terraform-Kommandos
1. `terraform init`
- Initialisiert das Projekt
- Lädt Provider-Plugins
- Konfiguriert Backend (State)
2. `terraform plan`
- Zeigt, was Terraform ändern würde (Create/Update/Delete)
- Verändert noch nichts
- Wichtig für Review (z.B. im CI)
3. `terraform apply`
- Führt den Plan aus (Standard: vorher Anzeige + Bestätigung)
- Erzeugt/aktualisiert/löscht Ressourcen
4. `terraform destroy`
- Löscht alle Ressourcen, die Terraform verwaltet
- Vorsicht: de facto „Infrastruktur-Abbau“
Typischer Ablauf:
```bash
terraform init
terraform plan
terraform apply
```
---
## 4. Terraform-Sprache: HCL (HashiCorp Configuration Language)
Terraform benutzt HCL, eine deklarative, blockbasierte Sprache.
### 4.1 Syntax-Grundlagen
Blöcke haben Form:
```hcl
resource "TYP" "NAME" {
argument = "value"
block {
nested_arg = 123
}
}
```
Datentypen:
- `string` `"Text"`
- `number` `42`
- `bool` `true` / `false`
- Listen `["a", "b"]`
- Maps `{ key = "value" }`
- Objekte/Tuples komplexere Typen
### 4.2 Expressions & Referenzen
Referenzen auf andere Ressourcen:
```hcl
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_type
tags = {
Name = "web-${var.environment}"
}
}
```
Referenz-Regel:
- `ressourcentyp.name.attribut`
- z.B. `aws_instance.web.public_ip`
---
## 5. Praktisches Beispiel
Ein minimaler Stack in AWS:
### `providers.tf`
```hcl
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.region
}
```
### `variables.tf`
```hcl
variable "region" {
type = string
default = "eu-central-1"
description = "AWS Region"
}
variable "instance_type" {
type = string
default = "t3.micro"
}
variable "environment" {
type = string
default = "dev"
}
```
### `main.tf`
```hcl
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
}
owners = ["099720109477"]
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_type
tags = {
Name = "web-${var.environment}"
Environment = var.environment
}
}
```
### `outputs.tf`
```hcl
output "web_instance_id" {
value = aws_instance.web.id
}
output "web_instance_ami" {
value = aws_instance.web.ami
}
```
Ablauf:
```bash
terraform init
terraform plan
terraform apply
```
---
## 6. Workspaces, Environments und Modularisierung
### 6.1 Workspaces
Terraform Workspaces ermöglichen getrennte States innerhalb desselben Codes (z.B. `default`, `dev`, `prod`).
```bash
terraform workspace list
terraform workspace new dev
terraform workspace select dev
```
Dann z.B.:
```hcl
variable "environment" {
default = terraform.workspace
}
```
Viele Teams gehen aber eher über **separate State-Dateien / Ordner / Repos** (z.B. `envs/dev`, `envs/prod`), statt Workspaces intensiv zu nutzen.
### 6.2 Module für Wiederverwendung
Struktur-Beispiel:
```text
.
├── main.tf
├── modules
│ ├── network
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ └── compute
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
```
In `main.tf`:
```hcl
module "network" {
source = "./modules/network"
vpc_cidr = "10.0.0.0/16"
}
module "compute" {
source = "./modules/compute"
vpc_id = module.network.vpc_id
subnets = module.network.subnet_ids
}
```
---
## 7. Terraform Cloud / Terraform Enterprise
Neben der CLI gibt es:
- **Terraform Cloud** (SaaS von HashiCorp)
- **Terraform Enterprise** (Self-hosted)
Features:
- Remote-State-Storage
- Remote-Execution (Plans/Applies)
- Policies (Sentinel)
- Team & Governance (RBAC)
- UI für Runs, Logs, States, Variablen
Für kleine Teams reicht oft: Git + Remote State (S3/Azure/GCS) + CI/CD Pipeline.
---
## 8. Typische Anwendungsfälle
- **Cloud-Infrastruktur**:
- VPCs/Netzwerke, Subnets, Security Groups
- Compute (VMs, Managed Kubernetes, Serverless)
- Datenbanken, Caches, Messaging
- **Kubernetes-Infrastruktur**:
- Cluster (EKS/AKS/GKE)
- Add-ons via `kubernetes`-Provider, `helm`-Provider
- **Multi-Cloud-Szenarien**:
- Einheitliches Tool für AWS + Azure + GCP
- **On-Prem / Sonstiges**:
- VMware, OpenStack, F5, GitHub-Repos, DNS (Cloudflare/Route53), Monitoring (Datadog, New Relic), etc.
---
## 9. Vergleich zu anderen Tools
### Terraform vs. CloudFormation / ARM / Bicep
- Terraform:
- Provider-übergreifend (nicht auf eine Cloud beschränkt)
- HCL, verständliche Syntax
- CloudFormation (AWS) / ARM/Bicep (Azure) / Deployment Manager (GCP):
- Cloud-spezifisch, tief integriert
- Gut für reines Single-Cloud-Setup
- Multi-Cloud wird komplex
### Terraform vs. Ansible / Chef / Puppet
- Terraform:
- Fokus: **Provisioning** + Lebenszyklus von Ressourcen
- Deklarativ, fokus auf Infrastruktur
- Ansible/Chef/Puppet:
- Fokus: **Konfiguration** von Servern / Software
- IdR. auf bereits existierende Maschinen
Häufig werden Terraform + Ansible kombiniert:
Terraform baut VMs / Netzwerke, Ansible konfiguriert Software im OS.
### Terraform vs. Pulumi
- Pulumi: IaC mit **allgemeinen Programmiersprachen** (TypeScript, Python, Go, C#)
- Terraform: HCL, deklarativ, stark verbreitete Community
- Pulumi bietet mehr „Programmier-Features“ (Loops, Ifs) direkt in Sprache; Terraform hat ähnliche Mechanismen, aber bewusst begrenzt, um die Konfiguration simpel zu halten.
---
## 10. Best Practices & Stolperfallen
### 10.1 Best Practices
- **State nicht lokal** speichern, sondern Remote (z.B. S3 + DynamoDB Locking, Azure Storage + Locks).
- **State schützen**:
- Zugriff beschränken (IAM/RBAC)
- Backups
- **Struktur / Modularisierung**:
- Wiederverwendbare Module
- Trennung von Environments (dev/stage/prod)
- **Git-Workflow**:
- Terraform-Code in Repos
- PRs/Merge-Requests
- `terraform plan` via CI im PR anzeigen
- **Versionen pinnen**:
- Terraform-Version `required_version`
- Provider-Versionen fixieren (z.B. `~> 5.0`)
- **Kleine, inkrementelle Änderungen**:
- Große Umbauten in mehreren Schritten
- Plan gut reviewen
### 10.2 Typische Probleme
- **State-Drift**:
- Ressourcen werden außerhalb von Terraform geändert (z.B. in der Cloud-Konsole)
- Plan zeigt unerwartete Änderungen
- Lösung: soweit möglich alle Änderungen via Terraform; bei Drift bewusst entscheiden (import, adopt, ignore)
- **Manuelles Löschen von Ressourcen**:
- Terraform „denkt“, Ressource existiert noch
- Beim nächsten Apply werden sie ggf. neu erstellt
- **Zyklen in Abhängigkeiten**:
- Falsche Referenzen können zyklische Abhängigkeiten erzeugen
- **Große States**:
- Sehr viele Ressourcen in einem State → langsamere Plans, unübersichtliche Fehler
- Lösung: Aufteilen in mehrere Terraform-Projekte / States (z.B. pro Domäne/Layer)
---
## 11. Aktuelle Entwicklungen: Lizenz & OpenTofu
HashiCorp hat 2023 die Lizenz von Terraform auf die **Business Source License (BSL)** geändert.
Daraufhin entstand ein **Community-Fork**:
- **OpenTofu** (ehemals OpenTF):
- Komplett Open Source (MPL 2.0)
- CLI & HCL weitgehend kompatibel zu Terraform (Stand heute)
- Ziel: drop-in Replacement für viele Terraform-Usecases
Für einen Einstieg in IaC ist es aber sinnvoll, zuerst die Konzepte anhand von Terraform zu verstehen die meisten davon sind für OpenTofu nahezu identisch.
---
@@ -0,0 +1,358 @@
Hier ist eine kompakte, praxisorientierte Anleitung zu `kubectl` mit den wichtigsten Funktionen und Use Cases.
---
## 1. Was ist `kubectl`?
`kubectl` ist das Kommandozeilen-Tool, um mit einem Kubernetes-Cluster zu kommunizieren.
Damit kannst du:
- Ressourcen erstellen, ändern und löschen (Deployments, Pods, Services, …)
- Logs einsehen und Probleme debuggen
- Rollouts steuern (Deployments updaten/rollback)
- Konfigurationen verwalten (Kontexte, Namespaces, Kubeconfig)
---
## 2. Grundlagen: Aufbau von `kubectl`-Befehlen
Allgemeines Schema:
```bash
kubectl <verb> <ressource> [name] [flags]
```
Beispiele:
```bash
kubectl get pods
kubectl describe pod mein-pod
kubectl delete service mein-service
```
Wichtige Verben:
- `get` Anzeigen
- `describe` Detailinformationen
- `create` / `apply` Ressourcen anlegen/aktualisieren
- `delete` Löschen
- `logs` Logs anzeigen
- `exec` Befehle innerhalb eines Pods ausführen
---
## 3. Konfiguration & Kontexte
### 3.1 Cluster-Zugriff prüfen
```bash
kubectl version
kubectl cluster-info
```
### 3.2 Aktuellen Kontext anzeigen und wechseln
```bash
kubectl config get-contexts
kubectl config current-context
kubectl config use-context mein-context
```
### 3.3 Namespace festlegen
Temporär per Flag:
```bash
kubectl get pods -n my-namespace
```
Standard-Namespace setzen:
```bash
kubectl config set-context --current --namespace=my-namespace
```
---
## 4. Ressourcen anzeigen und inspizieren
### 4.1 Ressourcen auflisten
```bash
kubectl get pods
kubectl get deployments
kubectl get services
kubectl get all
```
Mit mehr Details:
```bash
kubectl get pods -o wide
kubectl get pods -o yaml
```
### 4.2 Detailinformationen zu einer Ressource
```bash
kubectl describe pod mein-pod
kubectl describe deployment mein-deployment
```
Use Case: Debugging (Events, Container-Status, Restart-Gründe).
---
## 5. Deployments & Anwendungen verwalten
### 5.1 Deployment aus YAML erstellen
`deployment.yaml` Beispiel (stark vereinfacht):
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
```
Anwenden:
```bash
kubectl apply -f deployment.yaml
```
### 5.2 Deployment aktualisieren (Rolling Update)
Image ändern:
```bash
kubectl set image deployment/nginx-deployment nginx=nginx:1.26
```
Rollout-Status beobachten:
```bash
kubectl rollout status deployment/nginx-deployment
```
Rollback:
```bash
kubectl rollout undo deployment/nginx-deployment
```
### 5.3 Replica-Anzahl skalieren
```bash
kubectl scale deployment nginx-deployment --replicas=5
```
---
## 6. Services & Zugriff auf Anwendungen
### 6.1 Services anzeigen
```bash
kubectl get svc
```
Beispiel-Service:
```yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: ClusterIP
selector:
app: nginx
ports:
- port: 80
targetPort: 80
```
Anwenden:
```bash
kubectl apply -f service.yaml
```
### 6.2 Port-Forwarding (lokaler Zugriff)
```bash
kubectl port-forward svc/nginx-service 8080:80
# Aufruf im Browser: http://localhost:8080
```
---
## 7. Logs & Debugging
### 7.1 Logs eines Pods
```bash
kubectl logs mein-pod
kubectl logs mein-pod -c container-name
kubectl logs -f mein-pod # -f = "follow"
```
### 7.2 Befehle im Container ausführen
```bash
kubectl exec -it mein-pod -- /bin/sh
# oder
kubectl exec -it mein-pod -- bash
```
Typischer Use Case: Debugging von laufenden Containern, z.B. Netzwerkprobleme, Dateisystem prüfen.
### 7.3 Problem-Analyse mit `describe` & Events
```bash
kubectl describe pod mein-pod
kubectl get events --sort-by=.metadata.creationTimestamp
```
---
## 8. Ressourcen ändern & löschen
### 8.1 Änderungen anwenden
Konfiguration in einer Datei ändern und dann:
```bash
kubectl apply -f deployment.yaml
```
Um tatsächliche Unterschiede zu sehen:
```bash
kubectl diff -f deployment.yaml
```
### 8.2 Ressourcen löschen
```bash
kubectl delete pod mein-pod
kubectl delete -f deployment.yaml
kubectl delete deployment nginx-deployment
```
---
## 9. Konfigurationen & Secrets
### 9.1 ConfigMaps
Erstellen aus einer Datei:
```bash
kubectl create configmap app-config --from-file=config.properties
```
Oder aus Literalwert:
```bash
kubectl create configmap app-config --from-literal=KEY=VALUE
```
ConfigMaps anzeigen:
```bash
kubectl get configmaps
kubectl describe configmap app-config
```
### 9.2 Secrets
```bash
kubectl create secret generic db-secret \
--from-literal=username=user \
--from-literal=password=geheim
```
Achtung: Standard-`kubectl get secret -o yaml` zeigt Base64-codierte, aber nicht verschlüsselte Daten.
---
## 10. Weitere nützliche Features
### 10.1 Autocomplete
Bash-Beispiel:
```bash
source <(kubectl completion bash)
echo 'source <(kubectl completion bash)' >> ~/.bashrc
```
### 10.2 Kustomize (ohne extra Tool, ab neueren kubectl-Versionen)
```bash
kubectl apply -k ./overlays/production
```
Struktur z.B.:
```text
base/
deployment.yaml
kustomization.yaml
overlays/production/
kustomization.yaml
patches.yaml
```
---
## 11. Typische Praxis-Workflows
### 11.1 Neue Version deployen
```bash
git pull
kubectl apply -f k8s/
kubectl rollout status deployment mein-service
kubectl get pods -o wide
```
### 11.2 Fehlerhafte Anwendung debuggen
```bash
kubectl get pods
kubectl describe pod fehler-pod
kubectl logs fehler-pod
kubectl exec -it fehler-pod -- sh
kubectl get events --sort-by=.metadata.creationTimestamp
```
### 11.3 Schnell in einen anderen Namespace/Cluster wechseln
```bash
kubectl config use-context staging-cluster
kubectl config set-context --current --namespace=team-a
kubectl get pods
```
---
Wenn du möchtest, kann ich dir für deinen konkreten Use Case (z.B. “Web-App deployen”, “CI/CD-Pipeline”, “lokales Minikube-Cluster”) eine konkrete Schritt-für-Schritt-Anleitung mit fertigen `kubectl`-Befehlen erstellen.