23 Kubernetes Service: Stabilität in einem dynamischen Ökosystem

Kubernetes ist eine Open-Source-Plattform zur Automatisierung von Container-Deployments, Skalierungsprozessen und Betriebsabläufen. Anwendungen laufen in Containern, die zu Pods gruppiert sind, den grundlegenden Einheiten, die innerhalb eines Kubernetes-Clusters bereitgestellt und verwaltet werden.

Services in Kubernetes stellen einen zentralen Bestandteil dar, um Anwendungen stabil und zugänglich zu halten. Sie sorgen für konstante Zugriffspunkte zu den transitorischen Pods und sichern so die Kontinuität und Verfügbarkeit von Anwendungen in der volatilen Welt der Container.

23.1 Dynamische IP-Zuweisung bei Pods

In Kubernetes erhält jeder Pod beim Start eine eindeutige IP-Adresse aus dem internen Netzwerk des Clusters. Diese Adresse bleibt während der Lebensdauer des Pods erhalten. Allerdings sind Pods in Kubernetes ephemeral, das bedeutet, sie können häufig erstellt und vernichtet werden, beispielsweise beim Hoch- und Runterfahren von Services, durch Deployments oder wenn sie durch das Cluster-Management zur Heilung oder Skalierung neu platziert werden. Bei jedem Neustart eines Pods wird eine neue IP-Adresse zugewiesen. Dies stellt eine Herausforderung dar, wenn stabile Endpunkte für die Kommunikation mit Services innerhalb oder außerhalb des Clusters benötigt werden.

23.2 Service-Ressourcen für stabile Adressen

Um dieses Problem zu adressieren, stellt Kubernetes die Service-Ressource bereit. Ein Kubernetes Service ist eine Abstraktion, die einen stabilen Zugangspunkt zu einer logischen Gruppe von Pods, die denselben Service ausführen, definiert. Services ermöglichen es, Netzwerkverkehr an eine Gruppe von Pods zu routen, ohne die spezifischen internen IP-Adressen der Pods kennen zu müssen!

23.2.1 Typen von Kubernetes Services

In diesem Diagramm:

Jeder Service hat einen DNS-Namen im Format service.namespace.svc.cluster.local, der innerhalb des Clusters aufgelöst werden kann. Der namespace ist der Namespace, in dem der Service läuft, und würde entsprechend ersetzt werden.

23.2.2 Funktionsweise eines Kubernetes Service

Ein Kubernetes Service verwendet Labels und Selectors, um eine Verbindung zu den Pods herzustellen. Der Service überwacht kontinuierlich das Cluster, um sicherzustellen, dass die Verkehrsverteilung auf die aktiven Pods erfolgt. Wenn ein Pod terminiert und ein neuer erstellt wird, aktualisiert der Service automatisch seine Endpunktliste, sodass der Verkehr zu den verfügbaren Pods umgeleitet wird. Dadurch können Clients weiterhin über die stabile Adresse des Services kommunizieren, auch wenn sich die dahinter liegenden Pods ändern.

23.3 Implementierung von Services in einem Kubernetes-Cluster

Zur Erstellung eines Services wird eine Konfigurationsdatei im YAML-Format benötigt, die die gewünschten Eigenschaften des Services definiert. Diese Konfigurationsdatei wird an die Kubernetes-API übermittelt, welche dann den Service im Cluster erstellt.

apiVersion: v1
kind: Service
metadata:
  name: mein-service
spec:
  selector:
    app: MeineApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

Im obigen Beispiel wird ein Service namens mein-service definiert, der Traffic auf TCP-Port 80 entgegennimmt und an Pods weiterleitet, die mit app=MeineApp gelabelt sind, auf deren Port 9376.

23.4 Zugriff auf Anwendungen über Kubernetes Services

Kubernetes Services bieten eine abstrahierte Weise, auf eine Gruppe von Pods, die eine Anwendung ausführen, zuzugreifen. Services in Kubernetes garantieren, dass der Netzwerkverkehr zu den Anwendungen konsequent und zuverlässig weitergeleitet wird, auch wenn die Pods, die die Anwendung ausführen, geändert, aktualisiert oder neu gestartet werden.

23.5 tl:dr

Kubernetes Services sind entscheidend für die Netzwerkkommunikation und den Zugriff auf Anwendungen, die in einem Kubernetes-Cluster laufen. Durch die verschiedenen Service-Typen bieten sie eine breite Palette an Möglichkeiten, um Anwendungen sowohl innerhalb des Clusters als auch von außen zugänglich zu machen und gleichzeitig die Verwaltung und das Routing des Verkehrs zu vereinfachen. Durch den Einsatz von ClusterIP, NodePort, Load Balancer und ExternalName kann ein einheitlicher Zugriffspunkt für Anwendungen geschaffen werden, der die Service-Discovery und die Netzwerkkonfiguration stark vereinfacht.

23.5.1 ClusterIP für den internen Zugriff

Beginnen wir mit dem Standardtyp eines Services, dem ClusterIP. Dieser Service-Typ ist ideal für Anwendungen, die nur innerhalb des Clusters erreichbar sein sollen. Ein typischer Anwendungsfall könnte ein interner Datenbankdienst sein, der nicht öffentlich exponiert werden soll.

apiVersion: v1
kind: Service
metadata:
  name: datenbank-service
spec:
  selector:
    app: datenbank
  ports:
    - protocol: TCP
      port: 3306
      targetPort: 3306

In diesem Beispiel erstellt die Konfiguration einen Service, der auf TCP-Port 3306 lauscht und den Verkehr an den Port 3306 der Pods weiterleitet, die mit dem Label app: datenbank markiert sind.

23.6 NodePort für den externen Zugriff

Um eine Anwendung von außerhalb des Kubernetes-Clusters zugänglich zu machen, kann ein NodePort-Service verwendet werden. Ein NodePort-Service macht einen bestimmten Port auf jedem Node des Clusters verfügbar, und der Verkehr an diesen Port wird an die entsprechenden Pods weitergeleitet.

apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  type: NodePort
  selector:
    app: webapp
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 30007

In diesem Fall wird der Service web-service auf Port 80 erstellt, der den Verkehr an Pods weiterleitet, die auf Port 8080 lauschen und das Label app: webapp haben. Der Verkehr kann diesen Service über <Node-IP>:30007 erreichen, wobei <Node-IP> die IP-Adresse eines beliebigen Knotens im Cluster ist.

23.6.1 LoadBalancer für Integration mit Cloud-Providern

Für Anwendungen, die eine nahtlose Integration mit Cloud-Providern wie AWS, GCP oder Azure benötigen, bietet sich ein LoadBalancer-Service an. Dieser Service-Typ weist den Cloud-Provider an, einen externen Load Balancer zu erstellen, der den Verkehr an den Kubernetes Service weiterleitet.

apiVersion: v1
kind: Service
metadata:
  name: externer-service
spec:
  type: LoadBalancer
  selector:
    app: webapp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

Der LoadBalancer-Service wird automatisch eine externe IP-Adresse vom Cloud-Provider erhalten, die von außerhalb des Clusters verwendet werden kann, um auf die webapp-Anwendung zuzugreifen.

23.6.2 ExternalName für Dienste außerhalb des Clusters

Der ExternalName-Service ist ein spezieller Service-Typ, der es ermöglicht, einen Alias zu definieren, der auf einen DNS-Namen zeigt. Dies ist nützlich, wenn ein Kubernetes-Service auf einen Dienst verweisen soll, der außerhalb des Kubernetes-Clusters gehostet wird.

apiVersion: v1
kind: Service
metadata:
  name: externer-datenbank-service
spec:
  type: ExternalName
  externalName: db.beispiel.com

Hier verweist der externer-datenbank-service auf eine Datenbank, die unter db.beispiel.com gehostet wird. Anwendungen innerhalb des Clusters können diesen Service nutzen, um mit der externen Datenbank zu kommunizieren, als wäre sie Teil des Clusters.

23.7 Integration von Pods und Services in Kubernetes

Services in Kubernetes ermöglichen den Zugriff auf Anwendungen, die in Pods ausgeführt werden. Die Konfiguration eines Services umfasst Selektoren, die festlegen, welche Pods vom Service bedient werden. Im Folgenden wird die Einrichtung von Services zusammen mit den Pods dargestellt, die diese Services erfüllen.

23.7.1 Beispiel: ClusterIP Service mit Backend Pods

Stellen Sie sich vor, Sie haben eine Anwendung mit einem Backend, das über einen ClusterIP-Service innerhalb des Clusters erreichbar sein soll.

23.7.1.1 Backend Pods Konfiguration

apiVersion: v1
kind: Pod
metadata:
  name: backend-pod-1
  labels:
    app: backend
spec:
  containers:
  - name: backend-container
    image: backend-image:1.0
    ports:
    - containerPort: 80

---
apiVersion: v1
kind: Pod
metadata:
  name: backend-pod-2
  labels:
    app: backend
spec:
  containers:
  - name: backend-container
    image: backend-image:1.0
    ports:
    - containerPort: 80

23.7.1.2 ClusterIP Service Konfiguration

apiVersion: v1
kind: Service
metadata:
  name: backend-service
spec:
  selector:
    app: backend
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

In diesem Beispiel wird der backend-service so konfiguriert, dass er alle Anfragen auf Port 80 an Pods weiterleitet, die mit app: backend gelabelt sind.

23.7.2 Beispiel: NodePort Service mit Frontend Pods

Für den Zugriff auf eine Frontend-Anwendung von außerhalb des Kubernetes-Clusters verwenden Sie einen NodePort-Service.

23.7.2.1 Frontend Pods Konfiguration

apiVersion: v1
kind: Pod
metadata:
  name: frontend-pod-1
  labels:
    app: frontend
spec:
  containers:
  - name: frontend-container
    image: frontend-image:1.0
    ports:
    - containerPort: 8080

---
apiVersion: v1
kind: Pod
metadata:
  name: frontend-pod-2
  labels:
    app: frontend
spec:
  containers:
  - name: frontend-container
    image: frontend-image:1.0
    ports:
    - containerPort: 8080

23.7.2.2 NodePort Service Konfiguration

apiVersion: v1
kind: Service
metadata:
  name: frontend-service
spec:
  type: NodePort
  selector:
    app: frontend
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 30007

Hier werden Anfragen an den frontend-service auf Port 80 von jedem Node im Cluster an die Ports 8080 der mit app: frontend gelabelten Pods weitergeleitet.

23.8 Beispiel: LoadBalancer Service für eine Webanwendung

Für eine Webanwendung, die öffentlich zugänglich sein soll, kann ein LoadBalancer-Service konfiguriert werden.

23.8.0.1 Webanwendung Pods Konfiguration

apiVersion: v1
kind: Pod
metadata:
  name: webapp-pod-1
  labels:
    app: webapp
spec:
  containers:
  - name: webapp-container
    image: webapp-image:1.0
    ports:
    - containerPort: 8080

---
apiVersion: v1
kind: Pod
metadata:
  name: webapp-pod-2
  labels:
    app: webapp
spec:
  containers:
  - name: webapp-container
    image: webapp-image:1.0
    ports:
    - containerPort: 8080

23.8.0.2 LoadBalancer Service Konfiguration

apiVersion: v1
kind: Service
metadata:
  name: webapp-service
spec:
  type: LoadBalancer
  selector:
    app: webapp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

Der webapp-service nutzt den Typ LoadBalancer, um eine öffentliche IP-Adresse bereitzustellen, unter der die mit app: webapp gelabelten Pods auf Port 8080 erreichbar sind.

In allen diesen Beispielen bilden die Services eine Brücke zwischen den Anforderungen der Nutzer und den dynamisch verwalteten Pods. Sie bieten einen stabilen Zugangspunkt, selbst wenn sich die hinter den Services liegenden Pods verändern, da die Services die Anfragen nahtlos an die aktuellen Pod-Instanzen weiterleiten. Durch die Verwendung von Services wird sichergestellt, dass die Kommunikation zu den Anwendungen auch dann bestehen bleibt, wenn die Pods neu gestartet werden und dadurch neue IP-Adressen erhalten. Services stellen somit die zentrale Komponente in der Netzwerkarchitektur von Kubernetes dar, indem sie einen stabilen und zuverlässigen Mechanismus für die Service-Discovery und Lastverteilung bieten.

23.9 ClusterIP Service für einen Nginx-Webserver

Ein ClusterIP Service kann verwendet werden, um einen Nginx-Webserver innerhalb eines Kubernetes-Clusters erreichbar zu machen. Hier ist ein konkretes Beispiel für die Konfiguration eines solchen Szenarios:

23.9.1 Nginx Pod Konfiguration

Erstellen Sie zunächst die Definition für einen Nginx Pod. Dieser Pod wird über ein Label verfügen, das vom Service-Selektor verwendet wird, um den Traffic an diesen Pod weiterzuleiten.

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx-container
    image: nginx:latest
    ports:
    - containerPort: 80

23.9.2 ClusterIP Service Konfiguration für Nginx

Nachdem der Pod definiert ist, wird ein ClusterIP Service erstellt, der Netzwerkzugriff auf den Nginx Pod über einen stabilen internen Cluster-IP ermöglicht.

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

Dieser Service leitet Anfragen, die an den ClusterIP auf Port 80 eingehen, an den Port 80 des Nginx Pods, der durch den Selektor app: nginx identifiziert wird, weiter. Der Service ist innerhalb des Clusters über den Namen nginx-service erreichbar, welcher durch den DNS-Dienst von Kubernetes aufgelöst wird.