Dienste


Auf dieser Seite werden Kubernetes-Dienste und ihre Verwendung in Google Kubernetes Engine (GKE) beschrieben. Es gibt verschiedene Arten von Services, mit denen Sie eine Reihe von Pod-Endpunkten in einer einzigen Ressource zusammenfassen können. Informationen zum Erstellen eines Diensts finden Sie unter Anwendungen über Dienste freigeben.

Was ist ein Kubernetes-Service?

Ein Dienst wird dazu eingesetzt, eine Gruppe von Pod-Endpunkten in einer einzigen Ressource zu gruppieren. Sie können verschiedene Zugriffsmöglichkeiten für die Gruppierung konfigurieren. Standardmäßig erhalten Sie eine stabile Cluster-IP-Adresse, über die Clients innerhalb des Clusters Pods im Service kontaktieren können. Ein Client sendet eine Anfrage an die stabile IP-Adresse, die anschließend an einen der Pods im Dienst weitergeleitet wird.

Die Mitglieds-Pods eines Diensts werden mithilfe eines Selektors ermittelt. Damit ein Pod Mitglied des Diensts sein kann, muss der Pod über alle im Selektor angegebenen Labels verfügen. Ein Label ist ein beliebiges Schlüssel/Wert-Paar, das an ein Objekt angehängt ist.

Das folgende Dienstmanifest hat einen Selektor, mit dem zwei Labels festgelegt werden. Im Feld selector wird angegeben, dass jeder Pod mit den beiden Labels app: metrics und Label department:engineering ein Mitglied dieses Dienstes ist.

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: metrics
    department: engineering
  ports:
  ...

Vorteile eines Kubernetes-Service

In einem Kubernetes-Cluster hat jeder Pod eine interne IP-Adresse. Die Pods wechseln jedoch häufig und ihre IP-Adressen ändern sich. Daher ist es nicht sinnvoll, IP-Adressen von Pods direkt zu verwenden. Ein Dienst bietet Ihnen eine stabile IP-Adresse, die für die gesamte Lebensdauer des Diensts gilt, auch wenn sich die IP-Adressen der Mitglieds-Pods ändern.

Außerdem bieten Dienste eine Load-Balancing-Funktion, sodass Clients eine einzelne, stabile IP-Adresse aufrufen und ihre Anfragen auf die Pods verteilt werden, die Mitglieder des Diensts sind.

Arten von Kubernetes-Services

Es gibt fünf Servicetypen:

  • ClusterIP (Standard): Interne Clients senden Anfragen an eine stabile interne IP-Adresse.

  • NodePort: Clients senden Anforderungen an die IP-Adresse eines Knotens über einen oder mehrere nodePort-Werte, die vom Dienst angegeben werden.

  • LoadBalancer: Clients senden Anfragen an die IP-Adresse eines Netzwerk-Load-Balancers.

  • ExternalName: Interne Clients verwenden den DNS-Namen eines Diensts als Alias für einen externen DNS-Namen.

  • Headless: Wenn Sie eine Pod-Gruppierung wünschen, aber keine stabile IP-Adresse benötigen, können Sie einen monitorlosen Dienst verwenden.

Der Typ NodePort ist eine Erweiterung des Typs ClusterIP. Ein Dienst des Typs NodePort hat also eine Cluster-IP-Adresse.

Der Typ LoadBalancer ist eine Erweiterung des Typs NodePort. Ein Dienst vom Typ LoadBalancer hat also eine Cluster-IP-Adresse und einen oder mehrere nodePort-Werte.

Dienste vom Typ ClusterIP

Wenn Sie einen Dienst vom Typ ClusterIP erstellen, erstellt Kubernetes eine stabile IP-Adresse, auf die von Knoten im Cluster aus zugegriffen werden kann.

Hier ist ein Manifest für einen Dienst vom Typ ClusterIP:

apiVersion: v1
kind: Service
metadata:
  name: my-cip-service
spec:
  selector:
    app: metrics
    department: sales
  type: ClusterIP
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

Mithilfe von kubectl apply -f [MANIFEST_FILE] können Sie den Dienst erstellen. Nachdem Sie den Dienst erstellt haben, können Sie kubectl get service verwenden, um die stabile IP-Adresse anzuzeigen:

NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)
my-cip-service   ClusterIP   10.11.247.213   none          80/TCP

Clients im Cluster rufen den Dienst über die Cluster-IP-Adresse und den TCP-Port auf, der im Feld port des Dienstmanifests angegeben ist. Die Anfrage wird an einen der Mitglieds-Pods an dem TCP-Port weitergeleitet, der im Feld targetPort angegeben ist. Im obigen Beispiel ruft ein Client den Dienst unter 10.11.247.213 am TCP-Port 80 auf. Die Anfrage wird über TCP-Port 8080 an einen der Mitglieds-Pods weitergeleitet. Der Mitglieds-Pod muss über einen Container verfügen, der TCP-Port 8080 überwacht. Wenn kein Container Port 8080 überwacht, wird für die Clients die Meldung "Verbindung fehlgeschlagen" oder "Die Website ist nicht erreichbar" angezeigt.

Dienste vom Typ NodePort

Wenn Sie einen Dienst vom Typ NodePort erstellen, erhalten Sie in Kubernetes den Wert nodePort. Anschließend kann auf den Dienst zugegriffen werden, indem die IP-Adresse eines beliebigen Knotens zusammen mit dem Wert nodePort verwendet wird.

Dies ist ein Manifest für einen Dienst vom Typ NodePort:

apiVersion: v1
kind: Service
metadata:
  name: my-np-service
spec:
  selector:
    app: products
    department: sales
  type: NodePort
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

Nachdem Sie den Dienst erstellt haben, können Sie kubectl get service -o yaml verwenden, um seine Spezifikation und den Wert nodePort anzusehen.

spec:
  clusterIP: 10.11.254.114
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 32675
    port: 80
    protocol: TCP
    targetPort: 8080

Externe Clients rufen den Dienst auf, indem sie die externe IP-Adresse eines Knotens zusammen mit dem durch nodePort angegebenen TCP-Port verwenden. Die Anfrage wird an einen der Mitglieds-Pods am TCP-Port weitergeleitet, der im Feld targetPort angegeben ist.

Angenommen, die externe IP-Adresse eines der Clusterknotens lautet 203.0.113.2. Für das obige Beispiel ruft der externe Client den Dienst unter 203.0.113.2 über TCP-Port 32675 auf. Die Anfrage wird über TCP-Port 8080 an einen der Mitglieds-Pods weitergeleitet. Dafür muss der Mitglieds-Pod einen Container haben, der TCP-Port 8080 überwacht.

Der Diensttyp NodePort ist eine Erweiterung des Diensttyps ClusterIP. Interne Clients haben also zwei Möglichkeiten, den Service aufzurufen:

  • clusterIP und port verwenden
  • IP-Adresse eines Knotens und nodePort verwenden

Für einige Clusterkonfigurationen verwendet der externe Anwendungs-Load-Balancer einen Dienst vom Typ NodePort.

Weitere Informationen finden Sie unter Externen Application Load Balancer mit Ingress einrichten.

Ein externer Anwendungs-Load-Balancer ist ein Proxyserver und unterscheidet sich dadurch grundlegend von einem externen Passthrough-Netzwerk-Load-Balancer. Informationen hierzu finden Sie im Abschnitt Dienst vom Typ LoadBalancer.

Dienst vom Typ LoadBalancer

Weitere Informationen zu Diensten vom Typ LoadBalancer finden Sie unter Konzepte des LoadBalancer-Dienstes.

Dienste vom Typ ExternalName

Ein Dienst vom Typ ExternalName stellt einen internen Alias für einen externen DNS-Namen bereit. Interne Clients senden Anfragen unter Verwendung des internen DNS-Namens und die Anfragen werden an den externen Namen umgeleitet.

Dies ist ein Manifest für einen Dienst vom Typ ExternalName:

apiVersion: v1
kind: Service
metadata:
  name: my-xn-service
spec:
  type: ExternalName
  externalName: example.com

Wenn Sie einen Dienst erstellen, erzeugt Kubernetes einen DNS-Namen, den interne Clients verwenden können, um den Dienst aufzurufen. Im obigen Beispiel lautet der DNS-Name "my-xn-service.default.svc.cluster.local". Wenn ein interner Client eine Anfrage an "my-xn-service.default.svc.cluster.local" sendet, wird die Anfrage an "example.com" umgeleitet.

Der Diensttyp ExternalName unterscheidet sich grundlegend von den anderen Diensttypen. Tatsächlich entspricht ein Dienst des Typs ExternalName nicht der Definition von Diensten, die zu Beginn dieses Themas angegeben wurde. Ein Dienst vom Typ ExternalName ist nicht mit einer Gruppe von Pods verknüpft und hat keine stabile IP-Adresse. Stattdessen stellt ein Dienst vom Typ ExternalName eine Zuordnung von einem internen zu einem externen DNS-Namen dar.

Headless Service

Ein monitorloser (Headless) Service ist ein Kubernetes-Diensttyp, der keine Cluster-IP-Adresse zuweist. Stattdessen verwendet ein monitorloser Service das DNS, um die IP-Adressen der Pods verfügbar zu machen, die dem Service zugeordnet sind. Auf diese Weise können Sie eine direkte Verbindung zu den Pods herstellen, statt einen Proxy zu verwenden.

Monitorlose Dienste sind für eine Vielzahl von Szenarien nützlich, darunter:

  • Load-Balancing für Pods: Sie können monitorlose Dienste verwenden, um das Load-Balancing über Pods hinweg zu ermöglichen. Erstellen Sie zur Implementierung einen Service mit einem Selektor, der den Pods entspricht, für die Sie ein Load-Balancing vornehmen möchten. Der Dienst verteilt dann den Traffic gleichmäßig auf alle Pods, die dem Selektor entsprechen.

  • Service Discovery: Sie können einen monitorlosen Dienst verwenden, um die Service Discovery zu implementieren. Erstellen Sie zur Implementierung einen Dienst mit einem Namen und einem Selektor. Der DNS-Eintrag für den monitorlosen Dienst enthält alle IP-Adressen der Pods hinter dem Dienst, die dem Selektor entsprechen. Clients können diese DNS-Einträge nutzen, um die IP-Adressen der Pods zu finden, die mit dem Dienst verknüpft sind.

  • Direkter Pod-Zugriff: Clients können direkt eine Verbindung zu den Pods herstellen, die mit einem monitorlosen Dienst verknüpft sind. Dies kann für Dienste nützlich sein, die direkten Zugriff auf die zugrunde liegenden Pods benötigen, z. B. Load-Balancer und DNS-Server.

  • Flexibilität: Monitorlose Dienste können zum Erstellen einer Vielzahl verschiedener Topologien, darunter Load-Balancer, DNS-Server und verteilte Datenbanken, verwendet werden.

Wenn Sie spezielle Netzwerkanforderungen für Ihre Arbeitslasten haben, die nicht mithilfe von monitorlosen Diensten mit Selektoren gelöst werden können, besteht auch die Möglichkeit, monitorlose Dienste ohne Selektoren zu verwenden. Monitorlose Dienste sind ein nützliches Tool für den Zugriff auf Dienste, die sich nicht im Kubernetes-Cluster selbst befinden, da die Steuerungsebene keine EndpointSlice-Objekte erstellt. Weitere Informationen finden Sie unter Dienst ohne Selektoren.

Das folgende Beispiel ist ein Manifest für einen monitorlosen Dienst:

apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  clusterIP: None
  selector:
    app: nginx
  ports:
  - name: http
    port: 80
    targetPort: 80

Nachdem Sie einen monitorlosen Dienst erstellt haben, können Sie die IP-Adressen der Pods ermitteln, die mit dem Dienst verknüpft sind. Fragen Sie dazu das DNS ab. Der folgende Befehl listet beispielsweise die IP-Adressen der Pods auf, die dem nginx-Dienst zugeordnet sind:

dig +short nginx.default.svc.cluster.local

Ein weiteres Beispiel, in dem die Kubernetes-Abfrageerweiterung verwendet wird:

dig +short +search nginx

Sie können einen monitorlosen Dienst mit einem einzigen Befehl erstellen. Monitorlose Dienste lassen sich einfach aktualisieren und skalieren.

kubectl create service clusterip my-svc --clusterip="None" --dry-run=client -o yaml > [file.yaml]

Dienstabstraktion

Ein Dienst ist kein Prozess, mit dem eine bestimmte Netzwerkschnittstelle überwacht wird. In diesem Sinne handelt es sich dabei um eine Abstraktion. Ein Teil der Abstraktion ist in den iptables-Regeln der Clusterknoten implementiert. Je nach Diensttyp werden andere Teile der Abstraktion entweder durch einen externen Passthrough-Netzwerk-Load-Balancer oder einen externer Anwendungs-Load-Balancer implementiert.

Beliebige Dienstports

Der Wert des Felds port in einem Dienstmanifest ist beliebig. Der Wert von targetPort ist dagegen nicht beliebig. Jeder Mitglieds-Pod muss einen Container haben, der targetPort überwacht.

Dies ist ein Dienst vom Typ LoadBalancer mit einem port-Wert von 50.000:

apiVersion: v1
kind: Service
metadata:
  name: my-ap-service
spec:
  clusterIP: 10.11.241.93
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 30641
    port: 50000
    protocol: TCP
    targetPort: 8080
  selector:
    app: parts
    department: engineering
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 203.0.113.200

Ein Client ruft den Dienst unter 203.0.113.200 über TCP-Port 50000 auf. Die Anfrage wird über TCP-Port 8080 an einen der Mitglieds-Pods weitergeleitet.

Mehrere Ports

Das Feld ports eines Dienstes ist ein Array von ServicePort-Objekten. Das ServicePort-Objekt hat folgende Felder:

  • name
  • protocol
  • port
  • targetPort
  • nodePort

Wenn Sie mehr als einen ServicePort haben, muss jeder ServicePort einen eindeutigen Namen haben.

Dies ist ein Dienst vom Typ LoadBalancer mit zwei ServicePort-Objekten:

apiVersion: v1
kind: Service
metadata:
  name: my-tp-service
spec:
  clusterIP: 10.11.242.196
  externalTrafficPolicy: Cluster
  ports:
  - name: my-first-service-port
    nodePort: 31233
    port: 60000
    protocol: TCP
    targetPort: 50000
  - name: my-second-service-port
    nodePort: 31081
    port: 60001
    protocol: TCP
    targetPort: 8080
  selector:
    app: tests
    department: engineering
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 203.0.113.201

Wenn ein Client den Dienst im obigen Beispiel unter 203.0.113.201 über TCP-Port 60000 aufruft, wird die Anfrage über TCP-Port 50000 an einen Mitglieds-Pod weitergeleitet. Erfolgt der Aufruf unter 203.0.113.201 jedoch über TCP-Port 60001, wird die Anfrage über TCP-Port 8080 an einen Mitglieds-Pod weitergeleitet.

Dafür muss jeder Mitglieds-Pod einen Container haben, der TCP-Port 50000 überwacht, und einen Container, der TCP-Port 8080 überwacht. Sie können entweder einen einzelnen Container mit zwei Threads verwenden oder zwei Container auf demselben Pod.

Dienstendpunkte

Wenn Sie einen Dienst erstellen, erzeugt Kubernetes ein Endpoints-Objekt, das denselben Namen wie der Dienst trägt. Kubernetes verwendet das Endpoints-Objekt, um nachzuverfolgen, welche Pods Mitglieder des Diensts sind.

Single-Stack- und Dual-Stack-Dienste

Sie können einen IPv6-Service vom Typ ClusterIP oder NodePort erstellen. GKE unterstützt Dual-Stack-Dienste vom Typ LoadBalancer während der Vorschau, die kein SLA und keinen technischen Support bietet.

Für jeden dieser Diensttypen können Sie die Felder ipFamilies und ipFamilyPolicy entweder als IPv4-, IPv6- oder als Dual-Stack-Dienst definieren.

Nächste Schritte