255 lines
8.6 KiB
Markdown
Executable File
255 lines
8.6 KiB
Markdown
Executable File
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 Layer‑7-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). |