23 Services definieren

OpenShift Services implementieren Service Discovery und Load Balancing-Mechanismen für Container-basierte Anwendungen durch stabile Netzwerk-Abstraktion über dynamische Pod-Landschaften. Diese Konstrukte entkoppeln Service-Konsumenten von spezifischen Pod-Instanzen und ermöglichen resiliente, skalierbare Anwendungsarchitekturen.

23.1 Was sind Services und warum sind sie notwendig?

Services fungieren als persistente Netzwerk-Endpunkte, die sich ändernde Pod-Kollektionen über Label-Selektoren abstrahieren. Diese Indirektion ermöglicht nahtlose Anwendungsskalierung und Rolling Updates ohne Service-Consumer-Änderungen oder Verbindungsunterbrechungen.

23.1.1 Das Pod-IP-Problem

Pods in OpenShift haben dynamische IP-Adressen, die sich bei jedem Neustart ändern. Direkte Pod-zu-Pod-Kommunikation über IP-Adressen ist daher unpraktikabel und fehleranfällig. Services lösen dieses Problem durch stabile Virtual IPs und DNS-Namen.

23.1.2 Service-Discovery-Mechanismus

Die Service-Architektur implementiert automatische Endpoint-Discovery durch kontinuierliche Überwachung von Pod-Status und -Verfügbarkeit. Diese dynamische Endpoint-Verwaltung gewährleistet Traffic-Routing ausschließlich zu gesunden Pod-Instanzen.

Cluster-interne DNS-Integration ermöglicht Service-Discovery über DNS-Namen anstelle von IP-Adressen. Anwendungen können Services über Namen wie database-service.production.svc.cluster.local erreichen, was portable Anwendungsdefinitionen unterstützt.

23.2 Service-Typen und Verwendungsszenarien

OpenShift bietet verschiedene Service-Typen für unterschiedliche Konnektivitätsanforderungen. Die Wahl des Service-Typs bestimmt, wie und von wo aus der Service erreichbar ist.

23.2.1 ClusterIP Services

ClusterIP Services bieten cluster-interne Konnektivität und fungieren als Standard-Service-Typ für Mikroservice-Kommunikation. Diese Services erhalten virtuelle IP-Adressen, die ausschließlich innerhalb des Cluster-Netzwerks erreichbar sind.

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

Verwendung: Interne Kommunikation zwischen Microservices, Datenbank-Services, APIs ohne externen Zugriff.

23.2.2 NodePort Services

NodePort Services erweitern ClusterIP-Funktionalität um externe Erreichbarkeit über dedizierte Ports auf allen Cluster-Nodes. Diese Service-Art ermöglicht externe Zugriffe ohne zusätzliche Load Balancer-Infrastruktur.

apiVersion: v1
kind: Service
metadata:
  name: webapp-nodeport
spec:
  type: NodePort
  selector:
    app: webapp
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 30080  # Optional, wird automatisch zugewiesen wenn nicht angegeben

Verwendung: Entwicklungsumgebungen, einfache externe Zugriffe, wenn kein Load Balancer verfügbar ist.

23.2.3 LoadBalancer Services

LoadBalancer Services integrieren mit Cloud-Provider Load Balancing-Services für managed externe Konnektivität. Diese Integration abstrahiert Cloud-spezifische Load Balancer-Konfiguration und ermöglicht portable Anwendungsdefinitionen.

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

Verwendung: Produktionsanwendungen in Cloud-Umgebungen, wenn externe IP-Adresse und professioneller Load Balancer benötigt wird.

23.2.4 ExternalName Services

ExternalName Services ermöglichen DNS-basierte Integration externer Services in cluster-interne Service Discovery-Mechanismen. Diese Proxy-Services unterstützen Hybrid-Architektur-Szenarien mit externen Abhängigkeiten.

apiVersion: v1
kind: Service
metadata:
  name: external-database
spec:
  type: ExternalName
  externalName: database.company.com
  ports:
  - port: 5432

Verwendung: Integration externer Datenbanken, Legacy-Services, Cloud-Services über DNS-Namen.

23.2.5 Service-Typ-Vergleich

Service-Typ Erreichbarkeit Verwendung Load Balancer Externe IP
ClusterIP Nur intern Standard Microservices Intern Nein
NodePort Extern über Node-IPs Entwicklung, Tests Extern erforderlich Nein
LoadBalancer Extern über LB-IP Produktion (Cloud) Automatisch Ja
ExternalName DNS-Weiterleitung Externe Integration N/A N/A

23.3 Load Balancing und Traffic Distribution

Standard-Load Balancing implementiert Round-Robin-Distribution über verfügbare Pod-Endpoints ohne Berücksichtigung individueller Pod-Lasten oder Kapazitäten. Diese einfache Strategie eignet sich für homogene Workloads mit ähnlichen Performance-Charakteristika.

23.3.1 Session Affinity

Session Affinity-Konfigurationen ermöglichen Client-zu-Pod-Persistenz für Anwendungen mit Session-State-Anforderungen:

apiVersion: v1
kind: Service
metadata:
  name: stateful-webapp
spec:
  selector:
    app: webapp
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800  # 3 Stunden
  ports:
  - port: 80
    targetPort: 8080

Hinweis: Session Affinity sollte vermieden werden, da sie die Skalierbarkeit einschränkt. Stateless Anwendungsdesign ist preferable.

23.3.2 Erweiterte Load Balancing-Strategien

Weighted Load Balancing und erweiterte Traffic-Management können über Service Mesh-Integration (Istio, OpenShift Service Mesh) oder Ingress-Controller implementiert werden. Diese Lösungen bieten granulare Kontrolle über Traffic-Verteilung für Canary Deployments und A/B-Tests.

23.4 Multi-Port Services und Port-Management

Multi-Port Services ermöglichen die Exposition mehrerer Anwendungsports über einen einzelnen Service mit benannten Port-Definitionen. Diese Funktionalität unterstützt komplexe Anwendungen mit verschiedenen Protokoll-Endpunkten.

apiVersion: v1
kind: Service
metadata:
  name: multi-port-service
spec:
  selector:
    app: multi-app
  ports:
  - name: http
    port: 80
    targetPort: 8080
    protocol: TCP
  - name: https
    port: 443
    targetPort: 8443
    protocol: TCP
  - name: metrics
    port: 9090
    targetPort: 9090
    protocol: TCP

23.4.1 Port-Mapping-Flexibilität

Target Port-Spezifikationen entkoppeln Service Port-Definitionen von Container Port-Implementierungen:

ports:
- port: 80          # Service Port (extern sichtbar)
  targetPort: 8080   # Container Port (interne Anwendung)
  name: http
- port: 443
  targetPort: https  # Referenz auf benannten Container-Port
  name: https

Diese Abstraktionsebene ermöglicht Anwendungsportabilität ohne Änderung der Service-Definition bei Container-Port-Änderungen.

23.4.2 Protokoll-Unterstützung

Protocol-spezifische Service-Definitionen unterstützen verschiedene Traffic-Types:

ports:
- port: 80
  protocol: TCP    # Standard
- port: 53
  protocol: UDP    # DNS-Services
- port: 9999
  protocol: SCTP   # Stream Control Transmission Protocol

23.5 Service Discovery-Integration

DNS-basierte Service Discovery ermöglicht Anwendungen, Services über fully qualified domain names (FQDN) innerhalb des Cluster-Namespace zu referenzieren. Diese DNS-Integration abstrahiert IP-Address-Management vollständig.

23.5.1 DNS-Namen für Services

Services sind automatisch über verschiedene DNS-Namen erreichbar:

# Kurzer Name (innerhalb desselben Namespace)
backend-service

# Namespace-qualifiziert
backend-service.production

# Vollqualifizierter Name
backend-service.production.svc.cluster.local

23.5.2 Environment Variable-basierte Discovery

Für Legacy-Anwendungen injiziert OpenShift automatisch Service-Informationen als Umgebungsvariablen:

BACKEND_SERVICE_SERVICE_HOST=172.30.1.100
BACKEND_SERVICE_SERVICE_PORT=80
BACKEND_SERVICE_PORT_80_TCP=tcp://172.30.1.100:80

23.5.3 Service Discovery-Beispiel

# Anwendung, die andere Services konsumiert
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  template:
    spec:
      containers:
      - name: frontend
        image: nginx
        env:
        - name: BACKEND_URL
          value: "http://backend-service:80"  # DNS-basierter Service-Zugriff
        - name: DATABASE_URL
          value: "postgresql://database-service:5432/mydb"

23.6 Health Checking und Endpoint-Management

Readiness Probe-Integration gewährleistet, dass nur gesunde Pods Traffic über Service-Endpoints empfangen. Diese Health Check-Mechanismen implementieren automatische Fehlerisolation und Self-Healing-Funktionalitäten.

23.6.1 Automatisches Endpoint-Management

Services überwachen kontinuierlich die Readiness-Probes ihrer Pods und entfernen nicht-bereite Pods automatisch aus der Endpoint-Liste:

# Pod mit Readiness Probe
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: webapp
    readinessProbe:
      httpGet:
        path: /health
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10

Nur Pods, die ihre Readiness Probe erfolgreich bestehen, erhalten Traffic über den Service.

23.6.2 Endpoint-Objekte

Services erstellen automatisch Endpoint-Objekte, die die aktuelle Liste der verfügbaren Pod-IPs enthalten:

# Endpoint-Status anzeigen
oc get endpoints backend-service

NAME              ENDPOINTS                                       AGE
backend-service   10.128.2.15:8080,10.128.2.16:8080,10.128.2.17:8080   5m

23.6.3 Custom Endpoints

Für Services ohne Selektoren können manuelle Endpoints definiert werden, um externe Services zu integrieren:

apiVersion: v1
kind: Service
metadata:
  name: external-service
spec:
  ports:
  - port: 80

---
apiVersion: v1
kind: Endpoints
metadata:
  name: external-service
subsets:
- addresses:
  - ip: 192.168.1.100
  - ip: 192.168.1.101
  ports:
  - port: 80

23.7 Service-Security und Network Policies

Service-basierte Network Policies definieren granulare Traffic-Kontrollen zwischen Services basierend auf Labels und Namespaces. Diese Policy-Definitionen implementieren Zero-Trust-Networking-Prinzipien auf Service-Ebene.

23.7.1 Beispiel Network Policy für Service-Kommunikation

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 8080

23.7.2 Service Account Integration

Service Account-Integration ermöglicht Identity-basierte Service-Authentifizierung für Service-to-Service-Kommunikation:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: backend-sa

---
apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      serviceAccountName: backend-sa  # Pod verwendet spezifischen ServiceAccount
      containers:
      - name: backend
        # Container kann sich mit ServiceAccount-Token authentifizieren

23.8 Service-Monitoring und Troubleshooting

Service-Level Metrics ermöglichen Monitoring von Traffic-Patterns, Latency und Fehlerrates auf Service-Abstraktionsebene. Diese aggregierten Metriken unterstützen Application Performance Management (APM).

23.8.1 Service-Metriken überwachen

# Service-Endpoints prüfen
oc get endpoints service-name

# Service-Details anzeigen
oc describe service service-name

# Service-Traffic testen
oc port-forward service/backend-service 8080:80
curl http://localhost:8080

# Pod-Logs für Service-Troubleshooting
oc logs -l app=backend --tail=50

23.8.2 Häufige Service-Probleme

Keine Endpoints verfügbar: - Pod-Readiness-Probes fehlschlagen - Label-Selektoren stimmen nicht überein - Pods sind nicht im Running-Status

DNS-Auflösung funktioniert nicht: - CoreDNS-Pod-Probleme - Network Policies blockieren DNS-Traffic - Falsche Service-Namen

Traffic erreicht Pods nicht: - Port-Mapping-Fehler zwischen Service und Container - Network Policies blockieren Traffic - Pod-Firewall-Regeln

23.9 Service-Definition Best Practices

23.9.1 Naming Conventions

Konsistente Service-Namenskonventionen erleichtern Service Discovery und Management:

# Empfohlene Namenskonventionen
metadata:
  name: backend-api-service    # Beschreibend und eindeutig
  labels:
    app: backend
    component: api
    tier: backend

23.9.2 Port-Definitionen

Benannte Ports verbessern Lesbarkeit und Wartbarkeit:

ports:
- name: http      # Eindeutige Namen
  port: 80
  targetPort: http  # Referenz auf Container-Port-Namen
- name: metrics
  port: 9090
  targetPort: metrics

23.9.3 Selector-Design

Label-Selektoren sollten spezifisch genug sein, um ungewollte Pod-Auswahl zu vermeiden:

selector:
  app: webapp          # Zu allgemein
  
selector:
  app: webapp
  component: frontend  # Besser: spezifischer
  version: v1

23.9.4 Performance-Optimierungen

Endpoint-Slicing für große Services aktivieren (standardmäßig in neueren OpenShift-Versionen):

apiVersion: v1
kind: Service
metadata:
  name: large-service
  annotations:
    service.kubernetes.io/topology-aware-hints: auto
spec:
  # Service-Definition

Topology-aware Routing für Multi-Zone-Deployments nutzen, um Netzwerk-Latenz zu reduzieren und Cross-Zone-Traffic zu minimieren.