Veröffentlicht am

Kubernetes Service Discovery: DNS, Headless Services und Mesh

Teilen:
Authors

Kubernetes Service Discovery: DNS, Headless Services und Service Mesh im Vergleich

TL;DR

  • Kubernetes nutzt CoreDNS als Standard-Mechanismus: Jeder Service bekommt einen DNS-Eintrag unter <name>.<namespace>.svc.cluster.local.
  • ClusterIP ist der Default-Service-Typ und reicht fuer 90% aller internen Kommunikation aus.
  • Headless Services (clusterIP: None) liefern direkte Pod-IPs zurueck -- notwendig fuer StatefulSets und Datenbank-Cluster.
  • Ein Service Mesh (Istio, Linkerd) lohnt sich erst ab ca. 20+ Microservices mit Anforderungen an mTLS, Traffic Splitting oder detailliertes Tracing.
  • Umgebungsvariablen fuer Service Discovery sind ein Legacy-Mechanismus -- bei neuen Projekten ausschliesslich DNS verwenden.

Wie Service Discovery in Kubernetes funktioniert

Wenn ein Pod mit einem anderen Service kommunizieren will, braucht er dessen Adresse. In einer dynamischen Umgebung, in der Pods staendig neu erstellt und zerstoert werden, sind statische IPs keine Option. Kubernetes loest das mit Service-Objekten und DNS.

Jeder Kubernetes-Cluster betreibt CoreDNS als Cluster-internen DNS-Server. Sobald ein Service-Objekt erstellt wird, registriert CoreDNS automatisch einen DNS-Eintrag. Pods koennen den Service dann ueber seinen Namen ansprechen, ohne die tatsaechlichen Pod-IPs zu kennen.

Die DNS-Aufloesung folgt einem klaren Schema:

# Innerhalb des gleichen Namespace
<service-name>

# Namespace-uebergreifend
<service-name>.<namespace>

# Vollqualifiziert (FQDN)
<service-name>.<namespace>.svc.cluster.local

Das ist im Grunde alles. Kein Framework noetig, keine externe Registry -- CoreDNS erledigt das out of the box.

ClusterIP Service: Der Standardfall

Der ClusterIP-Service ist der Default und deckt die meisten Anwendungsfaelle ab. Kubernetes weist dem Service eine virtuelle IP zu, die sich waehrend der gesamten Lebensdauer des Service nicht aendert. Der kube-proxy auf jedem Node sorgt fuer die Weiterleitung an die dahinterliegenden Pods.

apiVersion: v1
kind: Service
metadata:
  name: order-api
  namespace: production
spec:
  selector:
    app: order-api
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: ClusterIP

Ein anderer Pod im gleichen Namespace kann diesen Service so erreichen:

curl http://order-api/v1/orders

Aus einem anderen Namespace heraus:

curl http://order-api.production/v1/orders

Die Lastverteilung uebernimmt kube-proxy per iptables- oder IPVS-Regeln. Das ist kein intelligentes Load Balancing (kein Least-Connections, kein Health-basiertes Routing), aber es funktioniert zuverlaessig fuer die meisten Workloads.

Headless Services: Wenn Sie direkte Pod-IPs brauchen

Fuer bestimmte Workloads reicht ein ClusterIP nicht aus. Datenbank-Cluster, Message Queues oder andere StatefulSets muessen gezielt einzelne Pods ansprechen koennen. Dafuer gibt es Headless Services.

apiVersion: v1
kind: Service
metadata:
  name: postgres
  namespace: production
spec:
  clusterIP: None
  selector:
    app: postgres
  ports:
    - port: 5432

Der entscheidende Unterschied: clusterIP: None. Statt einer einzelnen virtuellen IP liefert DNS jetzt die IPs aller dahinterliegenden Pods zurueck. In Kombination mit einem StatefulSet bekommt jeder Pod einen stabilen DNS-Eintrag:

postgres-0.postgres.production.svc.cluster.local
postgres-1.postgres.production.svc.cluster.local
postgres-2.postgres.production.svc.cluster.local

Das ist essenziell fuer Anwendungen, die Leader-Election oder Replikation zwischen bekannten Nodes durchfuehren muessen.

ClusterIP vs. Headless Service im Vergleich

EigenschaftClusterIP ServiceHeadless Service
Virtuelle IPJa (stabil)Nein
DNS-AntwortEine IP (ClusterIP)Alle Pod-IPs
Load BalancingAutomatisch via kube-proxyMuss die Anwendung selbst machen
Typischer EinsatzStateless APIs, Web-FrontendsStatefulSets, DB-Cluster
Pod-spezifisches DNSNeinJa (mit StatefulSet)
KomplexitaetGeringMittel

ExternalName: Externe Dienste intern verfuegbar machen

Wenn ein Microservice auf eine externe Datenbank oder SaaS-API zugreifen muss, koennen Sie einen ExternalName-Service erstellen. Das gibt Ihnen einen internen DNS-Alias:

apiVersion: v1
kind: Service
metadata:
  name: external-db
  namespace: production
spec:
  type: ExternalName
  externalName: db.example.eu-central-1.rds.amazonaws.com

Pods koennen jetzt external-db als Hostnamen verwenden. Der Vorteil: Wenn sich der externe Endpunkt aendert, muessen Sie nur das Service-Objekt aktualisieren, nicht jede einzelne Anwendungskonfiguration.

CoreDNS Debugging: Wenn die Aufloesung nicht funktioniert

Bevor Sie an der Anwendung suchen, pruefen Sie immer zuerst, ob DNS korrekt funktioniert. Dafuer starten Sie einen Debug-Pod:

# DNS-Aufloesung testen
kubectl run dns-debug --rm -it --image=busybox:1.36 --restart=Never -- nslookup order-api.production.svc.cluster.local

# CoreDNS-Pods pruefen
kubectl get pods -n kube-system -l k8s-app=kube-dns

# CoreDNS-Logs bei Problemen
kubectl logs -n kube-system -l k8s-app=kube-dns --tail=50

# DNS-Policy eines Pods pruefen
kubectl get pod <pod-name> -o yaml | grep -A5 dnsPolicy

Typische DNS-Probleme und ihre Ursachen:

SymptomWahrscheinliche UrsacheLoesung
NXDOMAINService existiert nicht oder falscher Namespacekubectl get svc -A pruefen
TimeoutCoreDNS-Pod nicht gesund oder NetworkPolicy blocktCoreDNS-Pods und Logs pruefen
Falsche IPVeralteter DNS-CachePod neu starten, ndots pruefen
Langsame AufloesungZu hoher ndots-Wertndots: 2 in dnsConfig setzen

Ein haeufiges Performance-Problem: Die Default-ndots: 5 Einstellung fuehrt dazu, dass jede DNS-Anfrage zuerst mehrere Suchdomaenen durchprobiert. Das koennen Sie mit einer expliziten dnsConfig optimieren:

spec:
  dnsConfig:
    options:
      - name: ndots
        value: "2"

Wann ein Service Mesh sinnvoll wird

CoreDNS und ClusterIP-Services decken die grundlegende Kommunikation ab. Aber ab einer gewissen Komplexitaet stossen Sie an Grenzen: kein automatisches mTLS zwischen Services, kein feingranulares Traffic Splitting, kein verteiltes Tracing ohne Instrumentierung.

Hier kommen Service Meshes wie Istio oder Linkerd ins Spiel. Sie injizieren einen Sidecar-Proxy (Envoy bei Istio, linkerd2-proxy bei Linkerd) in jeden Pod, der den gesamten Netzwerkverkehr abfaengt und steuert.

Istio vs. Linkerd -- eine ehrliche Einschaetzung:

KriteriumIstioLinkerd
RessourcenverbrauchHoch (100-200 MB pro Sidecar)Gering (20-30 MB pro Sidecar)
KomplexitaetHoch, steile LernkurveModerat, schneller Einstieg
Feature-UmfangSehr umfangreichFokussiert auf Kern-Features
mTLSJa, vollstaendigJa, per Default
Traffic SplittingJa, sehr feingranularJa, ueber TrafficSplit CRD
MulticlusterJaJa (ab 2.14)
CNCF-StatusGraduatedGraduated

Faustregeln fuer die Entscheidung:

  • Unter 10 Microservices: Kein Service Mesh noetig. NetworkPolicies und manuelle mTLS-Konfiguration reichen.
  • 10-30 Microservices: Linkerd evaluieren. Geringer Overhead, schnelle Installation.
  • 30+ Microservices mit komplexem Traffic Management: Istio in Betracht ziehen.

Service Types im Ueberblick: Wann welchen verwenden

Neben ClusterIP und Headless gibt es weitere Service-Typen, die fuer die Service Discovery relevant sind:

Service-TypErreichbarkeitTypischer EinsatzDNS-Verhalten
ClusterIPNur internAPIs, Backends, MicroservicesLoest zu virtueller IP auf
HeadlessNur internStatefulSets, DB-ClusterLoest zu allen Pod-IPs auf
NodePortExtern via Node-IP:PortEntwicklung, TestsWie ClusterIP + externer Port
LoadBalancerExtern via Cloud-LBProduktions-IngressWie ClusterIP + externe IP
ExternalNameIntern als AliasExterne AbhaengigkeitenCNAME auf externen Host

Fuer die interne Service Discovery sind nur ClusterIP und Headless relevant. NodePort und LoadBalancer sind Mechanismen, um Services nach aussen zu exponieren -- sie aendern nichts an der internen Discovery.

NetworkPolicies und Service Discovery

Ein haeufig uebersehener Punkt: NetworkPolicies koennen die Service Discovery brechen, wenn sie nicht korrekt konfiguriert sind. Wenn Sie eine Default-Deny-Policy fuer Ihren Namespace setzen, muessen Sie explizit den DNS-Traffic zu CoreDNS erlauben:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53

Ohne diese Regel koennen Pods im Namespace keine DNS-Anfragen mehr stellen und finden keinen anderen Service -- obwohl die Services korrekt konfiguriert sind. Das fuehrt zu verwirrenden Timeouts, die auf den ersten Blick nicht nach einem DNS-Problem aussehen.

Stellen Sie sicher, dass Sie auch den Traffic zum eigentlichen Ziel-Service erlauben:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-backend-access
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: frontend
  policyTypes:
    - Egress
  egress:
    - to:
        - podSelector:
            matchLabels:
              app: order-api
      ports:
        - protocol: TCP
          port: 8080

Multicluster Service Discovery

Sobald Sie mehr als einen Kubernetes-Cluster betreiben, wird Service Discovery komplexer. Ein Service in Cluster A muss einen Service in Cluster B finden koennen. Es gibt mehrere Ansaetze:

Service Mesh mit Multicluster-Support: Istio und Linkerd koennen Services cluster-uebergreifend erreichbar machen. Das funktioniert, fuegt aber die Komplexitaet eines Service Mesh hinzu.

Kubernetes MCS API (Multi-Cluster Services): Ein relativ neues API, das ServiceExport und ServiceImport Objekte definiert. Damit koennen Services explizit fuer andere Cluster freigegeben werden. Die Implementierung haengt vom Cloud-Provider ab.

Externer DNS mit gemeinsamer Domain: Der pragmatischste Ansatz fuer viele Teams. Jeder Cluster registriert seine Services per ExternalDNS in einer gemeinsamen DNS-Zone (z.B. Route53 oder Cloud DNS). Services finden sich dann ueber regulaere DNS-Namen.

Fuer die meisten Teams mit zwei bis drei Clustern ist der externe DNS-Ansatz der einfachste Einstieg.

Umgebungsvariablen: Der Legacy-Weg

Kubernetes injiziert fuer jeden Service, der vor einem Pod existiert, automatisch Umgebungsvariablen im Format <SERVICE_NAME>_SERVICE_HOST und <SERVICE_NAME>_SERVICE_PORT. Dieser Mechanismus hat zwei gravierende Nachteile:

Services, die nach dem Pod-Start erstellt werden, sind nicht sichtbar. Und bei vielen Services im Namespace wird die Umgebung schnell unuebersichtlich. Verwenden Sie diesen Mechanismus nur, wenn Sie eine Legacy-Anwendung migrieren, die Umgebungsvariablen erwartet und nicht auf DNS umgestellt werden kann.

Es gibt sogar Szenarien, in denen Umgebungsvariablen aktiv Probleme verursachen. Bei Namespaces mit mehr als 50 Services kann die Anzahl der Umgebungsvariablen die OS-Limits erreichen. In solchen Faellen koennen Sie den Mechanismus komplett deaktivieren:

spec:
  enableServiceLinks: false
  containers:
    - name: app
      image: myapp:v1

Zusammenfassung: Entscheidungshilfe

Fuer die meisten Kubernetes-Deployments ist die Service-Discovery-Strategie einfach:

  1. ClusterIP + CoreDNS als Basis fuer alle internen Services verwenden.
  2. Headless Services fuer StatefulSets und Workloads, die direkte Pod-Adressierung brauchen.
  3. ExternalName Services als Alias fuer externe Abhaengigkeiten.
  4. Service Mesh erst einfuehren, wenn konkrete Anforderungen an mTLS, Traffic Splitting oder Observability bestehen.

Starten Sie einfach und erweitern Sie bei Bedarf. Die meisten Teams, die sofort mit Istio anfangen, verbringen mehr Zeit mit dem Mesh als mit der eigentlichen Anwendung.

Weiterführende Artikel


Wenn Sie Unterstuetzung bei der Architektur Ihrer Service-Kommunikation brauchen oder eine Service-Mesh-Evaluierung planen, sprechen Sie uns an. Wir helfen bei Konzeption, Implementierung und Betrieb -- hier Kontakt aufnehmen.

Kubernetes-Beratung gesucht?

Wir helfen deutschen Unternehmen bei der Kubernetes-Implementierung, Migration und Optimierung. DSGVO-konform und praxiserprobt.

📖 Verwandte Artikel

Weitere interessante Beiträge zu ähnlichen Themen