Envoy-Sidecar-Service-Mesh einrichten

Diese Konfiguration wird für Vorschaukunden unterstützt, wir empfehlen sie jedoch nicht für neue Cloud Service Mesh-Nutzer. Weitere Informationen finden Sie unter Cloud Service Mesh – Übersicht.

In dieser Anleitung wird gezeigt, wie Sie ein einfaches Service Mesh in Ihrer Flotte konfigurieren. Die Anleitung umfasst folgende Schritte:

  • Envoy-Sidecar-Injektor im Cluster bereitstellen. Der Injektor fügt den Envoy-Proxy-Container in Anwendungs-Pods ein.
  • Gateway API-Ressourcen bereitstellen, die die Envoy-Sidecar-Datei im Service Mesh konfigurieren, um Anfragen an einen Beispieldienst im Namespace store weiterzuleiten.
  • Einfachen Client bereitstellen, um die Bereitstellung zu überprüfen.

Das folgende Diagramm zeigt das konfigurierte Service Mesh.

Envoy-Sidecar-Service-Mesh in einer Flotte
Envoy-Sidecar-Service-Mesh in einer Flotte (zum Vergrößern klicken)

Sie können nur ein Mesh in einem Cluster konfigurieren, da der Mesh-Netzwerk-Name in der Sidecar-Injektor-Konfiguration und der Name der Mesh-Ressource identisch sein müssen.

Envoy-Sidecar-Injektor bereitstellen

So stellen Sie den Sidecar-Injektor bereit:

  1. Projektinformationen konfigurieren

    # The project that contains your GKE cluster.
    export CLUSTER_PROJECT_ID=YOUR_CLUSTER_PROJECT_NUMBER_HERE
    # The name of your GKE cluster.
    export CLUSTER=YOUR_CLUSTER_NAME
    # The channel of your GKE cluster. Eg: rapid, regular, stable.
    export CHANNEL=YOUR_CLUSTER_CHANNEL
    # The location of your GKE cluster, Eg: us-central1 for regional GKE cluster,
    # us-central1-a for zonal GKE cluster
    export LOCATION=ZONE
    
    # The mesh name of the traffic director load balancing API.
    export MESH_NAME=YOUR_MESH_NAME
    # The project that holds the mesh resources.
    export MESH_PROJECT_NUMBER=YOUR_PROJECT_NUMBER_HERE
    
    export TARGET=projects/${MESH_PROJECT_NUMBER}/locations/global/meshes/${MESH_NAME}
    
    gcloud config set project ${CLUSTER_PROJECT_ID}
    

    Um den Wert für MESH_NAME zu ermitteln, weisen Sie ihn so zu, wobei MESH_NAME der Wert des Felds metadata.name in der Mesh-Ressourcenspezifikation ist:

    gketd-MESH_NAME
    

    Wenn der Wert von metadata.name in der Mesh-Ressource beispielsweise butterfly-mesh lautet, legen Sie den Wert von MESH_NAME so fest:

    export MESH_NAME="gketd-butterfly-mesh"
    
  2. Konfigurationen für Mutating Webhook anwenden

    In den folgenden Abschnitten wird beschrieben, wie Sie die MutatingWebhookConfiguration auf den Cluster anwenden. Wenn ein Pod erstellt wird, wird der clusterinterne Admission Controller aufgerufen. Der Admission Controller kommuniziert mit dem verwalteten Sidecar-Injektor, um dem Pod den Envoy-Container hinzuzufügen.

    Wenden Sie die folgenden Webhook-Konfigurationen für Mutationen auf Ihren Cluster an.

    cat <<EOF | kubectl apply -f -
    apiVersion: admissionregistration.k8s.io/v1
    kind: MutatingWebhookConfiguration
    metadata:
      labels:
        app: sidecar-injector
      name: td-mutating-webhook
    webhooks:
    - admissionReviewVersions:
      - v1beta1
      - v1
      clientConfig:
        url: https://meshconfig.googleapis.com/v1internal/projects/${CLUSTER_PROJECT_ID}/locations/${LOCATION}/clusters/${CLUSTER}/channels/${CHANNEL}/targets/${TARGET}:tdInject
      failurePolicy: Fail
      matchPolicy: Exact
      name: namespace.sidecar-injector.csm.io
      namespaceSelector:
        matchExpressions:
        - key: td-injection
          operator: Exists
      reinvocationPolicy: Never
      rules:
      - apiGroups:
        - ""
        apiVersions:
        - v1
        operations:
        - CREATE
        resources:
        - pods
        scope: '*'
      sideEffects: None
      timeoutSeconds: 30
    EOF
    

    Wenn Sie den Sidecar-Injektor anpassen möchten, gehen Sie so vor:

  3. TLS für den Sidecar-Injektor konfigurieren

  4. Sidecar-Injektion aktivieren

  5. Optionen für die automatische Envoy-Injection

store-Dienst bereitstellen

In diesem Abschnitt stellen Sie den store-Dienst im Mesh-Netzwerk bereit.

  1. Speichern Sie in der Datei store.yaml das folgende Manifest:

    kind: Namespace
    apiVersion: v1
    metadata:
      name: store
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: store
      namespace: store
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: store
          version: v1
      template:
        metadata:
          labels:
            app: store
            version: v1
        spec:
          containers:
          - name: whereami
            image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1
            ports:
            - containerPort: 8080
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: store
      namespace: store
    spec:
      selector:
        app: store
      ports:
      - port: 8080
        targetPort: 8080
    
  2. Wenden Sie das Manifest auf gke-1 an:

    kubectl apply -f store.yaml
    

Service Mesh erstellen

  1. Speichern Sie in der Datei mesh.yaml das folgende mesh-Manifest. Der Name der mesh-Ressource muss mit dem in der Injektor-Konfigurationszuordnung angegebenen Mesh-Netzwerknamen übereinstimmen. In dieser Beispielkonfiguration wird der Name td-mesh an beiden Stellen verwendet:

    apiVersion: net.gke.io/v1alpha1
    kind: TDMesh
    metadata:
      name: td-mesh
      namespace: default
    spec:
      gatewayClassName: gke-td
      allowedRoutes:
        namespaces:
          from: All
    
  2. Wenden Sie das mesh-Manifest auf gke-1 an. Dadurch wird ein logisches Mesh-Netzwerk mit dem Namen td-mesh erstellt:

    kubectl apply -f mesh.yaml
    
  3. Speichern Sie in der Datei store-route.yaml das folgende HTTPRoute-Manifest. Das Manifest definiert eine HTTPRoute-Ressource, die HTTP-Traffic, der den Hostnamen example.com angibt, an einen Kubernetes-Dienst store im Namespace store weiterleitet:

    apiVersion: gateway.networking.k8s.io/v1alpha2
    kind: HTTPRoute
    metadata:
      name: store-route
      namespace: store
    spec:
      parentRefs:
      - name: td-mesh
        namespace: default
        group: net.gke.io
        kind: TDMesh
      hostnames:
      - "example.com"
      rules:
      - backendRefs:
        - name: store
          namespace: store
          port: 8080
    
  4. Wenden Sie das Routenmanifest auf gke-1 an:

    kubectl apply -f store-route.yaml
    

Deployment validieren

  1. Prüfen Sie den Mesh-Status und die Ereignisse, um festzustellen, ob die Mesh- und HTTPRoute-Ressourcen erfolgreich bereitgestellt wurden:

    kubectl describe tdmesh td-mesh
    

    Die Ausgabe sieht etwa so aus:

    ...
    
    Status:
      Conditions:
        Last Transition Time:  2022-04-14T22:08:39Z
        Message:
        Reason:                MeshReady
        Status:                True
        Type:                  Ready
        Last Transition Time:  2022-04-14T22:08:28Z
        Message:
        Reason:                Scheduled
        Status:                True
        Type:                  Scheduled
    Events:
      Type    Reason  Age   From                Message
      ----    ------  ----  ----                -------
      Normal  ADD     36s   mc-mesh-controller  Processing mesh default/td-mesh
      Normal  UPDATE  35s   mc-mesh-controller  Processing mesh default/td-mesh
      Normal  SYNC    24s   mc-mesh-controller  SYNC on default/td-mesh was a success
    
  2. Prüfen Sie mit dem folgenden Befehl, ob die Sidecar-Injektion im Standard-Namespace aktiviert ist:

    kubectl get namespace default --show-labels
    

    Wenn die Sidecar-Injektion aktiviert ist, wird in der Ausgabe Folgendes angezeigt:

    istio-injection=enabled
    

    Wenn die Sidecar-Injektion nicht aktiviert ist, finden Sie weitere Informationen unter Sidecar-Injektionen aktivieren.

  3. Stellen Sie zum Prüfen der Bereitstellung einen Client-Pod bereit, der als Client für den zuvor definierten store-Dienst fungiert. Speichern Sie in der Datei client.yaml Folgendes:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        run: client
      name: client
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          run: client
      template:
        metadata:
          labels:
            run: client
        spec:
          containers:
          - name: client
            image: curlimages/curl
            command:
            - sh
            - -c
            - while true; do sleep 1; done
    
  4. Stellen Sie die Spezifikation bereit:

    kubectl apply -f client.yaml
    

    Der im Cluster ausgeführte Sidecar-Injektor fügt automatisch einen Envoy-Container in den Client-Pod ein.

  5. Führen Sie den folgenden Befehl aus, um zu prüfen, ob der Envoy-Container eingefügt wurde:

    kubectl describe pods -l run=client
    

    Die Ausgabe sieht etwa so aus:

    ...
    Init Containers:
      # Istio-init sets up traffic interception for the Pod.
      istio-init:
    ...
      # td-bootstrap-writer generates the Envoy bootstrap file for the Envoy container
      td-bootstrap-writer:
    ...
    Containers:
    # client is the client container that runs application code.
      client:
    ...
    # Envoy is the container that runs the injected Envoy proxy.
      envoy:
    ...
    

Nachdem der Client-Pod bereitgestellt wurde, senden Sie eine Anfrage vom Client-Pod an den store-Dienst.

  1. Rufen Sie den Namen des Client-Pods ab:

    CLIENT_POD=$(kubectl get pod -l run=client -o=jsonpath='{.items[0].metadata.name}')
    
    # The VIP where the following request will be sent. Because all requests
    # from the client container are redirected to the Envoy proxy sidecar, you
    # can use any IP address, including 10.0.0.2, 192.168.0.1, and others.
    VIP='10.0.0.1'
    
  2. Senden Sie eine Anfrage an den Store-Dienst und geben Sie die Antwortheader aus:

    TEST_CMD="curl -v -H 'host: example.com' $VIP"
    
  3. Führen Sie den Testbefehl im Clientcontainer aus:

    kubectl exec -it $CLIENT_POD -c client -- /bin/sh -c "$TEST_CMD"
    

    Die Ausgabe sieht etwa so aus:

    < Trying 10.0.0.1:80...
    < Connected to 10.0.0.1 (10.0.0.1) port 80 (#0)
    < GET / HTTP/1.1
    < Host: example.com
    < User-Agent: curl/7.82.0-DEV
    < Accept: */*
    <
    < Mark bundle as not supporting multiuse
    < HTTP/1.1 200 OK
    < content-type: application/json
    < content-length: 318
    < access-control-allow-origin: *
    < server: envoy
    < date: Tue, 12 Apr 2022 22:30:13 GMT
    <
    {
      "cluster_name": "gke-1",
      "zone": "us-west1-a",
      "host_header": "example.com",
      ...
    }
    

Nächste Schritte