Dienststeuerung einrichten

Auf dieser Seite erfahren Sie, wie Sie die Dienststeuerung für Ihre Pods einrichten.

Informationen zur Funktionsweise der Dienststeuerung finden Sie unter Funktionsweise der Dienststeuerung.

Voraussetzungen

  • GKE-Version 1.30 oder höher.

Beschränkungen

  • Eine ServiceFunctionChain kann höchstens eine Dienstfunktion haben.
  • Wir empfehlen maximal 100 Knoten plus 10 ServiceFunctionChain- und TrafficSelector-Paare.
  • Die GKE-Dienststeuerung ist nur mit Knoten verfügbar, auf denen das Knoten-Image für Container-Optimized OS ausgeführt wird.
  • Die GKE-Dienststeuerung unterstützt nur ausgehende und Ziel-IP-Adressen.
  • Die Dienststeuerung verarbeitet keine Konflikte, die entstehen, wenn mehrere Trafficauswahlen mit identischen Präfixlängen auf dasselbe Subjekt angewendet werden. Um Konflikte zu vermeiden, sollten Sie Ihre Trafficauswahlen proaktiv mit nicht überlappenden IP-Adressbereichen und klar definierten Auswahlkriterien entwerfen.

Dienststeuerung implementieren

Mit der GKE-Dienststeuerung können Sie den Fluss des Netzwerktraffics in einem Cluster anpassen und steuern. In diesem Abschnitt wird anhand eines Web-Gateway-Beispiels gezeigt, wie Sie die Dienststeuerung implementieren.

Angenommen, Sie möchten ein Web-Gateway erstellen, das den Traffic von Endnutzer-Clientgeräten zum Internet schützt. Ein VPN-Terminator leitet den Traffic über einen sicheren Tunnel in das verwaltete Gateway. Der Endnutzer-Traffic wird zur Firewall und dann zum Proxy weitergeleitet. Der Proxy führt eine Quellnetzwerkadressübersetzung (Source Network Address Translation, SNAT) für den Traffic durch, maskiert die ursprüngliche Quelladresse und sendet sie an das Internet.

So implementieren Sie die GKE-Dienststeuerung:

  1. Erstellen Sie eine VPC mit einer MTU von 8896.
  2. Einen GKE-Cluster installieren
  3. Erstellen Sie die Dienstfunktions-Pods und den Dienst.
  4. Erstellen Sie ServiceFunctionChain.
  5. Erstellen Sie die TrafficSelector-Ressource, die auf die ServiceFunctionChain verweist.

Hinweis

Führen Sie die folgenden Aufgaben aus, bevor Sie beginnen:

  • Aktivieren Sie die Google Kubernetes Engine API.
  • Google Kubernetes Engine API aktivieren
  • Wenn Sie die Google Cloud CLI für diesen Task verwenden möchten, installieren und dann initialisieren Sie die gcloud CLI. Wenn Sie die gcloud CLI bereits installiert haben, rufen Sie die neueste Version mit dem gcloud components update Befehl ab. Ältere gcloud CLI-Versionen unterstützen möglicherweise nicht die Ausführung der Befehle in diesem Dokument.

VPC vorbereiten

Bereiten Sie eine VPC vor. Die Dienststeuerung verwendet die Kapselung, um Traffic an die entsprechenden Dienstfunktionen weiterzuleiten. Bei der Kapselung werden jedem Paket zusätzliche Header hinzugefügt, wodurch die Paketgröße zunimmt. Für die Dienststeuerung ist keine spezielle Konfiguration in VPCs erforderlich. Bei der Vorbereitung der VPC empfehlen wir, den Overhead der Kapselung bei der Entscheidung über die MTU-Größe zu berücksichtigen. Weitere Informationen finden Sie unter VPC-Netzwerk mit einer angegebenen MTU.

Mit dem folgenden Befehl wird die MTU-Größe in Ihrer VPC festgelegt:

gcloud compute networks create VPC_NETWORK_NAME --mtu=8896

Ersetzen Sie VPC_NETWORK_NAME durch den Namen des VPC-Netzwerk, das das Subnetz enthält.

GKE-Cluster erstellen

Wenn Sie die erweiterten Verwaltungsfunktionen für Netzwerkrouting und IP-Adressen aktivieren möchten, die für die Implementierung der Dienststeuerung in GKE erforderlich sind, erstellen Sie einen GKE-Cluster, für den GKE Dataplane V2 aktiviert ist:

gcloud container clusters create CLUSTER_NAME \
    --network VPC_NAME \
    --release-channel RELEASE_CHANNEL \
    --cluster-version CLUSTER_VERSION \
    --enable-dataplane-v2 \
    --enable-ip-alias

Ersetzen Sie Folgendes:

  • CLUSTER_NAME ist der Name des Clusters.
  • VPC_NAMEist der Name der VPC, mit der Sie den Cluster verknüpfen möchten.
  • RELEASE_CHANNEL ist der Name der Release-Version.
  • VERSION ist die GKE-Version; die 1.30 oder höher sein muss. Sie können auch das Flag --release-channel verwenden, um einen Release-Kanal auszuwählen. Die Release-Version muss die Standardversion 1.30 oder höher sein.

ServiceFunction-Pods erstellen

Um Ihre Dienstkette einzurichten, stellen Sie den VPN-Terminator-Pod und die erforderlichen Dienstfunktions-Pods in Ihrem Cluster bereit. Pods kapseln die containerisierten Anwendungen ein, die Ihre Netzwerkfunktionen ausführen.

Der VPN-Terminator-Pod ist oft die erste Dienstfunktion in der Kette, die den Traffic beendet, der über das VPN in den Cluster gelangt. Anschließend werden die anderen Dienstfunktionen wie Firewalls und Load Balancing zur weiteren Verarbeitung weitergeleitet, bevor das endgültige Ziel erreicht wird.

In der folgenden Beispielkonfigurationsdatei werden die folgenden drei Komponenten definiert, die für die Verwaltung des Netzwerktraffics in einem Cluster unerlässlich sind:

  • VPN-Pod: Richtet einen VPN-Endpunkt (Virtual Private Network) in Ihrem Cluster ein, der eine sichere und verschlüsselte Kommunikation zwischen dem Cluster und externen Netzwerken ermöglicht.
  • Firewallbereitstellung: Stellt mehrere Replikate eines Firewall-Pods bereit, die Sicherheit und Load Balancing bieten.
  • Proxy-DaemonSet:Stellt auf jedem Knoten Ihres Clusters einen Proxy-Pod bereit, sodass der Netzwerktraffic lokal verarbeitet werden kann, bevor er an andere Dienste wie die Firewall weitergeleitet wird.

Speichern Sie das folgende Beispielmanifest als service_function.yaml:

apiVersion: v1
kind: Pod
  name: vpn
  namespace: vpn
  labels:
    app: vpn
spec:
  containers:
  -   name: vpn
    image: openvpn
    ports:
    -   containerPort: 51820
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: firewall
  namespace: firewall
spec:
  replicas: 3
  selector:
    matchLabels:
      app: firewall
  template:
    metadata:
      labels:
        app: firewall
    spec:
      containers:
      -   name: firewall
        image: firewall
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: proxy
  namespace: proxy
spec:
  selector:
    matchLabels:
      app: proxy
  template:
    metadata:
      labels:
        app: proxy
    spec:
      containers:
      -   name: proxy
        image: proxy

Wenden Sie das Manifest an:

kubectl apply -f service_function.yaml

ServiceFunctionChains erstellen

Um eine Sequenz von Netzwerkfunktionen für den Traffic zu definieren, erstellen Sie eine Pipeline, in der jede Funktion wie Firewall, Proxy und Load Balancer ihre bestimmte Aufgabe ausführt, bevor der Traffic an die nächste weitergeleitet wird.

Speichern Sie das folgende Beispielmanifest als ServiceFunctionChain.yaml:

apiVersion: networking.gke.io/v1
kind: ServiceFunctionChain
metadata:
  name: firewall
spec:
  sessionAffinity:
    clientIpNoDestination:
      timeoutSeconds: 3600 # 1hr
  serviceFunctions:
  -   name: firewall
    namespace: firewall
    podSelector:
      matchLabels:
        app: firewall
---
apiVersion: networking.gke.io/v1
kind: ServiceFunctionChain
metadata:
  name: proxy
spec:
  sessionAffinity:
    clientIpNoDestination: {}
  serviceFunctions:
  -   name: proxy
    namespace: proxy
    podSelector:
      matchLabels:
        app: proxy

Wenden Sie das Manifest an:

kubectl apply -f ServiceFunctionChain.yaml

Die Dienstfunktionen werden inline in der ServiceFunctionChain mit dem Feld serviceFunctions definiert. Eine Dienstfunktion ist eine Endpunktauswahl.

Ressource TrafficSelector erstellen

Wenn Sie definieren möchten, wo und welcher Traffic für die Dienststeuerung ausgewählt wird, erstellen Sie die TrafficSelector-Ressource, die auf die ServiceFunctionChains verweist, die auf den ausgewählten Traffic angewendet werden sollen.

Speichern Sie das folgende Beispielmanifest als TrafficSelector.yaml:

apiVersion: networking.gke.io/v1
kind: TrafficSelector
metadata:
  name: vpn-to-firewall
spec:
  serviceFunctionChain: firewall
  subject:
    pods:
      namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: vpn
      podSelector:
        matchLabels:
          app: vpn
  egress:
    to:
      ipBlock:
        cidr: 0.0.0.0/0
    ports:
    -   allPorts:
        protocol: UDP
    -   allPorts:
        protocol: TCP
---
apiVersion: networking.gke.io/v1
kind: TrafficSelector
metadata:
  name: firewall-to-proxy
spec:
  serviceFunctionChain: proxy
  subject:
    pods:
      namespaceSelector:
        kubernetes.io/metadata.name: firewall
      podSelector:
        app: firewall
  egress:
    to:
      ipBlock:
        cidr: 0.0.0.0/0
    ports:
    -   allPorts:
        protocol: UDP
    -   allPorts:
        protocol: TCP

Wenden Sie das Manifest an:

kubectl apply -f TrafficSelector.yaml

Fehlerbehebung bei der Dienststeuerung

In diesem Abschnitt wird beschrieben, wie Sie Probleme im Zusammenhang mit der GKE-Dienststeuerung beheben.

Netzwerktraffic fließt nicht

Sie können die folgenden Maßnahmen ergreifen, um das Problem zu beheben:

Schritt 1: Prüfen, ob servicePathId auf ServiceFunctionChain festgelegt ist

Prüfen Sie, ob servicePathId auf ServiceFunctionChain festgelegt ist. Jedem ServiceFunctionChain-Objekt wird eine eindeutige servicePathId zugewiesen, wie im folgenden Beispiel gezeigt:

apiVersion: networking.gke.io/v1
kind: ServiceFunctionChain
metadata:
  name: firewall
spec:
  serviceFunctions:
  - name: firewall
    namespace: firewall
    podSelector:
      matchLabels:
        app: firewal
status:
  servicePathId: 1

Schritt 2: Prüfen, ob ein Kubernetes-Service pro Service-Funktion erstellt wird

Für jede Dienstfunktion wird automatisch ein ClusterIP-Dienst erstellt. Sie können die Liste der Dienste mit kubectl aufrufen:

kubectl get svc -A -l networking.gke.io/managed-by=service-steering-controller.gke.io

Schritt 3: Prüfen, ob für jede Dienstfunktion ein bpf-Zuordnungseintrag auf jedem Knoten erstellt wird, um die Dienst-IP-Adresse zu speichern

Für jede Dienstfunktion wird ein bpf-Zuordnungseintrag auf jedem Knoten erstellt, um die Dienst-IP-Adresse zu speichern.

Rufen Sie den Namen des anetd-Pods ab:

kubectl get pods -n kube-system -o wide -l k8s-app=cilium

Notieren Sie den Namen des Pods, der anetd ähnelt.

Führen Sie dazu diesen Befehl aus:

kubectl -n kube-system exec -it ANETD-POD-NAME -- cilium bpf sfcpath list

Ersetzen Sie ANETD-POD-NAME durch den Namen des anetd-Pods.

Die Ausgabe sieht in etwa so aus:

PATH     SERVICE FUNCTION ADDRESS
(1, 1)   10.4.10.124

Schritt 4: Prüfen, ob bpf-Karteneinträge in der sfcselect-Zuordnung erstellt wurden

Wenn auf einem Knoten Pods ausgewählt sind, die von einem TrafficSelector ausgewählt wurden, werden bpf-Karteneinträge in der sfcselect-Zuordnung erstellt. Im folgenden Beispiel wird gezeigt, dass der TCP/UDP-Traffic von einem beliebigen Port des Endpunkts (Pod) 3783 zur Ziel-IP-Adresse 10.0.2.12 an eine ServiceFunctionChain weitergeleitet wird.

Führen Sie dazu diesen Befehl aus:

kubectl -n kube-system exec -it ANETD-POD-NAME -- cilium bpf sfcselect list

Ersetzen Sie ANETD-POD-NAME durch den tatsächlichen Namen des anetd-Pods in Ihrem Cluster.

Die Ausgabe sieht in etwa so aus:

SELECTOR                            PATH
3783, egress, 0/TCP, 10.0.2.12/32   /32 (1, 1)
3783, egress, 0/UDP, 10.0.2.12/32   /32 (1, 1)

Schritt 5: Netzwerkverkehr mit tcpdump auf Port 7081 erfassen und analysieren

Die Dienststeuerung führt eine Geneve-Kapselung unter UDP-Port 7081 durch. Sie können tcpdump auf den relevanten Knoten verwenden, um den Trafficfluss zu analysieren und festzustellen, wo das Problem auftreten könnte.

Nächste Schritte