Pub/Sub-Proxy für mobile Clients in GKE einrichten


In dieser Anleitung erfahren Sie, wie Sie Nachrichten von mobilen oder clientseitigen Anwendungen in Pub/Sub veröffentlichen, indem Sie anstelle von clientseitigen Anmeldedaten einen Proxy für die Authentifizierungs- und Autorisierungslogik verwenden.

Mit der Identitäts- und Zugriffsverwaltung (Identity and Access Management, IAM) können Sie zwar Nachrichten vom Client zu Pub/Sub authentifizieren, solche langlebigen Anmeldedaten laufen aber nicht ab. In clientseitigen Anwendungen können diese Anmeldedaten durch Techniken wie App-Dekompilierung und Reverse Engineering ermittelt werden.

Stattdessen können Sie die Authentifizierungs- und Autorisierungslogik auf einen Proxy übertragen, der die folgenden Aufgaben ausführt:

  • Eingehende Anfragen authentifizieren, um Nutzer zu validieren
  • Anfragen zusammen mit den entsprechenden IAM-Berechtigungen an Pub/Sub weiterleiten

In dieser Anleitung erfahren Sie, wie Sie einen Pub/Sub-Proxy in Google Kubernetes Engine (GKE) implementieren. Diese Anleitung richtet sich an Anwendungsentwickler und Systemarchitekten, die das Design für mobile oder clientseitige Anwendungen definieren und implementieren. Dabei wird davon ausgegangen, dass Sie mit den grundlegenden Kubernetes-Konzepten und mit Cloud Endpoints vertraut sind.

Anfragefluss für diese Anleitung

Um zu verstehen, wie Pub/Sub in eine Streamingpipeline passt, sollten Sie eine Clickstream-Analyse in Betracht ziehen. In diesem Anwendungsfall möchten Sie möglicherweise wissen, wie Nutzer mit Ihrer App interagieren. Dazu erfassen Sie die Nutzeraktivität in Echtzeit. Das folgende Diagramm zeigt den Datenfluss.

Diagramm: Der Pub/Sub-Proxy empfängt Nachrichten vom Client, bevor die Daten zusammengefasst werden

Die von der Anwendung erfassten Daten werden über einen Proxy an Pub/Sub übertragen. Pub/Sub kann nachgeschaltete Abonnenten wie Dataflow oder Dataproc haben, die die Daten für eine aussagekräftige Analyse zusammenfassen.

Das folgende Diagramm zeigt eine detaillierte Ansicht des Anfrageflusses, dem diese Anleitung folgt.

Diagramm: Interaktion von Pipelinekomponenten bei einer Nutzeranfrage

In den nächsten Abschnitten wird erläutert, wie die verschiedenen Komponenten in diesem Diagramm zusammenarbeiten.

Nutzerauthentifizierung

Apps können verschiedene Methoden zur Authentifizierung von Nutzern verwenden. Der Authentifizierungsablauf hängt jeweils von Ihrer Anwendung ab. In dieser Anleitung wird nur eine mögliche Lösung zur Authentifizierung von Nutzern gezeigt. Als Begleitmaterial zu dieser Anleitung gibt es eine Implementierung dieser Lösung.

Anfragen von der Client-App an den Pub/Sub-Proxy

Das App-Backend generiert ein kurzlebiges Authentifizierungstoken, das der Client lokal speichert (z. B. mithilfe des Android-Schlüsselspeichersystems oder der iOS-Schlüsselbunddienste). In dieser Anleitung werden zur Authentifizierung der Client-App OpenID Connect-ID-Tokens (OIDC-ID-Tokens) verwendet. Google gibt die OIDC-ID-Tokens aus und signiert es.

Die clientseitige Anwendung sendet eine Anfrage mit diesem OIDC-ID-Token an den Pub/Sub-Proxy. Der Pub/Sub-Proxy validiert das Token und leitet die Anfrage mit den entsprechenden IAM-Anmeldedaten an Pub/Sub weiter.

Nachrichten veröffentlichen

Nachdem die Client-App erfolgreich authentifiziert wurde, sendet der Pub/Sub-Proxy eine Veröffentlichungsanfrage an Pub/Sub. Mithilfe von IAM prüft Pub/Sub, ob der Aufrufer (der Pub/Sub-Proxy) die erforderlichen Berechtigungen zum Senden von Veröffentlichungsanfragen hat. In dieser Anleitung verwendet der Pub/Sub-Proxy das Compute Engine-Standarddienstkonto zur Authentifizierung bei Pub/Sub. Das Compute Engine-Standarddienstkonto hat die IAM-Rolle Bearbeiter (roles/editor), die Publisher-Zugriffauf den Pub/Sub-Proxy bietet.

Ziele

  • GKE-Cluster erstellen, um einen Pub/Sub-Proxy auszuführen
  • Pub/Sub-Thema erstellen
  • Pub/Sub-Proxy bereitstellen
  • Endpoints für die Authentifizierung von Anfragen an den Pub/Sub-Proxy konfigurieren
  • Prüfen, ob Nachrichten in Pub/Sub veröffentlicht werden

Kosten

In diesem Dokument verwenden Sie die folgenden kostenpflichtigen Komponenten von Google Cloud:

Mit dem Preisrechner können Sie eine Kostenschätzung für Ihre voraussichtliche Nutzung vornehmen. Neuen Google Cloud-Nutzern steht möglicherweise eine kostenlose Testversion zur Verfügung.

Nach Abschluss der in diesem Dokument beschriebenen Aufgaben können Sie weitere Kosten vermeiden, indem Sie die erstellten Ressourcen löschen. Weitere Informationen finden Sie unter Bereinigen.

Vorbereitung

  1. Rufen Sie in der Google Cloud Console die Seite für die Projektauswahl auf.

    Zur Projektauswahl

  2. Wählen Sie ein Google Cloud-Projekt aus oder erstellen Sie eines.

  3. Die Abrechnung für das Google Cloud-Projekt muss aktiviert sein.

  4. Aktivieren Sie Cloud Shell in der Google Cloud Console.

    Cloud Shell aktivieren

    Unten in der Google Cloud Console wird eine Cloud Shell-Sitzung gestartet und eine Eingabeaufforderung angezeigt. Cloud Shell ist eine Shell-Umgebung, in der das Google Cloud CLI bereits installiert ist und Werte für Ihr aktuelles Projekt bereits festgelegt sind. Das Initialisieren der Sitzung kann einige Sekunden dauern.

  5. Definieren Sie die Umgebungsvariablen, die Sie für diese Anleitung benötigen:
        export PROJECT=$(gcloud config get-value project)
        export REGION=us-central1
        export ZONE=${REGION}-b
        export CLUSTER=pubsub-proxy
        export TOPIC=proxy-test
        export SERVICE_ACCOUNT=publish-test
        export ENDPOINTS_SERVICE="pubtest.endpoints.${PROJECT}.cloud.goog"
        export GENERATE_TOKEN="https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts"
  6. Aktivieren Sie die APIs für Cloud Build, Compute Engine, Google Kubernetes Engine, Artefaktanalyse, Container Registry, Endpoints, Service Management, Service Control und Pub/Sub:
        gcloud services enable \
            cloudbuild.googleapis.com \
            compute.googleapis.com \
            container.googleapis.com \
            containeranalysis.googleapis.com \
            containerregistry.googleapis.com \
            endpoints.googleapis.com \
            servicemanagement.googleapis.com \
            servicecontrol.googleapis.com \
            pubsub.googleapis.com

Pub/Sub-Thema erstellen

  • Erstellen Sie in Cloud Shell ein Pub/Sub-Thema, in dem Sie Nachrichten veröffentlichen wollen:

    gcloud pubsub topics create $TOPIC
    

GKE-Cluster erstellen

  1. Erstellen Sie in Cloud Shell einen GKE-Cluster:

    gcloud container clusters create $CLUSTER \
        --zone $ZONE \
        --scopes "https://www.googleapis.com/auth/cloud-platform"
    
  2. Rufen Sie Anmeldedaten für den ausgeführten Cluster ab:

    gcloud container clusters get-credentials $CLUSTER \
        --zone $ZONE \
        --project $PROJECT
    

Container-Image erstellen

  1. Klonen Sie in Cloud Shell das Code-Repository:

    git clone https://github.com/GoogleCloudPlatform/solutions-pubsub-proxy-rest
    
  2. Erstellen Sie mit Cloud Build ein Container-Image aus dem Quellcode und speichern Sie es dann in Container Registry:

    cd solutions-pubsub-proxy-rest && \
        gcloud builds submit --tag gcr.io/$PROJECT/pubsub-proxy:v1
    

Statische externe IP-Adresse erstellen

  1. Erstellen Sie in Cloud Shell eine statische externe IP-Adresse, die später dem Load-Balancer des Pub/Sub-Proxys zugewiesen wird:

    gcloud compute addresses create service-ip --region $REGION
    
  2. Speichern Sie die statische IP-Adresse in der Umgebungsvariablen PROXY_IP:

    PROXY_IP=$(gcloud compute addresses describe service-ip \
        --region $REGION --format='value(address)')
    

Endpoints bereitstellen

Der Pub/Sub-Proxy authentifiziert Anfragen von Nutzern mithilfe von Endpoints. Endpoints verwendet den Extensible Service Proxy (ESP), um API-Verwaltungsfunktionen wie Authentifizierung, Monitoring, Tracing und API-Lebenszyklusverwaltung bereitzustellen. In dieser Anleitung wird Endpoints nur für die Authentifizierung eingehender Anfragen an den Pub/Sub-Proxy verwendet.

In dieser Anleitung stellen Sie den ESP als Sidecar mit dem Pub/Sub-Proxy bereit. Der ESP fängt eingehende Anfragen ab und authentifiziert sie, bevor sie an den Pub/Sub-Proxy weitergeleitet werden.

  1. Ersetzen Sie in Cloud Shell den Platzhalter [PROJECT_ID] in der Datei openapi.yaml durch Ihre Google Cloud-Projekt-ID:

    sed -i -e "s/\[PROJECT_ID\]/$PROJECT/g" openapi.yaml
    
  2. Ersetzen Sie in der OpenAPI-Manifestdatei den Platzhalter [IP_ADDRESS] durch den Wert von PROXY_IP:

    sed -i -e "s/\[IP_ADDRESS\]/$PROXY_IP/g" openapi.yaml
    
  3. Stellen Sie die OpenAPI-Dienstdefinition in Endpoints bereit:

    gcloud endpoints services deploy openapi.yaml
    

    Der vorherige Befehl erstellt:

    • Einen verwalteten Dienst mit dem Namen, den Sie im Feld "Host" in der openapi.yaml-Datei angegeben haben (pubtest.endpoints.project-id.cloud.goog), wobei project-id die ID Ihres Google Cloud-Projekts ist.
    • Einen DNS-A-Eintrag, der den Dienstnamen und die IP-Adresszuordnung des Pub/Sub-Proxy-Load-Balancers verwendet, die in der Erweiterung x-google-endpoints in der Datei openapi.yaml definiert sind.

    Während der Bereitstellung wird eine Warnung angezeigt, die Sie ignorieren können, da in dieser Anleitung anstelle von API-Schlüsseln OIDC-ID-Tokens für die Authentifizierung verwendet werden.

    WARNING: openapi.yaml: Operation 'post' in path '/publish': Operation does
    not require an API key; callers may invoke the method without specifying an
    associated API-consuming project. To enable API key all the
    SecurityRequirement Objects
    (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-requirement-object)
    inside security definition must reference at least one SecurityDefinition
    of type : 'apiKey'.
    
  4. Prüfen Sie, ob der Dienst korrekt bereitgestellt wurde:

    gcloud endpoints services describe ${ENDPOINTS_SERVICE}
    

    Die Ausgabe sieht etwa so aus:

    [...]
    producerProjectId: project-id
    serviceConfig:
      documentation:
        summary: Pub/Sub proxy exposed as an Endpoint API
    [...]
      name: pubtest.endpoints.project-id.cloud.goog
      title: PubSub Proxy
      usage: {}
    serviceName: pubtest.endpoints.project-id.cloud.goog
    

    Dabei gilt:

    • project-id: Die ID Ihres Google Cloud-Projekts.

Proxy bereitstellen

  1. Generieren Sie in Cloud Shell ein selbst signiertes SSL-Zertifikat, um HTTPS-Verbindungen zum Proxy zuzulassen.

    openssl req -x509 -nodes -days 365 \
        -newkey rsa:2048 -keyout ./nginx.key \
        -out ./nginx.crt \
        -subj "/CN=${ENDPOINTS_SERVICE}"
    
  2. Erstellen Sie mit dem SSL-Zertifikat und dem privaten Schlüssel ein Kubernetes-Secret:

    kubectl create secret generic nginx-ssl \
        --from-file=./nginx.crt \
        --from-file=./nginx.key
    
  3. Ersetzen Sie den Platzhalter [PROJECT_ID] in der Manifestdatei der Bereitstellung durch Ihre Google Cloud-Projekt-ID:

    sed -i -e "s/\[PROJECT_ID\]/$PROJECT/g" kube/deployment.yaml
    
  4. Ersetzen Sie den Platzhalter [IP_ADDRESS] in der Dienstmanifestdatei durch den Wert PROXY_IP:

    sed -i -e "s/\[IP_ADDRESS\]/$PROXY_IP/g" kube/service.yaml
    
  5. Stellen Sie den Proxy bereit:

    kubectl apply -f kube/
    
  6. Prüfen Sie, ob die Bereitstellung erfolgreich war:

    kubectl rollout status deployment/pubsub-proxy
    

    Die Ausgabe sieht etwa so aus:

    [...]
    deployment "pubsub-proxy" successfully rolled out
    
  7. Prüfen Sie, ob im Pod zwei Container (ESP und Pub/Sub-Proxy) ausgeführt werden:

    kubectl get pods $(kubectl get pod \
        -l app=pubsub-proxy \
        -o jsonpath="{.items[0].metadata.name}") \
        -o jsonpath={.spec.containers[*].name}
    

    Die Ausgabe sieht etwa so aus:

    esp  pubsub-proxy
    
  8. Achten Sie auf den Wert von EXTERNAL-IP, der von <pending> in die zuvor erstellte statische externe IP-Adresse geändert wird:

    kubectl get svc pubsub-proxy -w
    

    Die Ausgabe sieht etwa so aus:

    NAME          TYPE          CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
    pubsub-proxy  LoadBalancer  10.7.247.212  <pending>     443:31104/TCP  6m32s
    pubsub-proxy  LoadBalancer  10.7.247.212  <PROXY_IP>    443:31104/TCP  6m5s
    

    Drücken Sie CTRL+C, um die Wiedergabe zu beenden.

    Nachdem der Pub/Sub-Proxy erfolgreich bereitgestellt wurde, wird er unter https://${ENDPOINTS_SERVICE}/publish verfügbar gemacht. Es kann einige Minuten dauern, bis die neue DNS-Konfiguration verteilt wurde.

  9. Prüfen Sie die DNS-Konfiguration:

    watch nslookup ${ENDPOINTS_SERVICE}
    

    Die Ausgabe sieht etwa so aus:

    Server:   169.254.169.254
    Address:  169.254.169.254#53
    
    Non-authoritative answer:
    Name: pubtest.endpoints.project-id.cloud.goog
    Address: gke-load-balancer-ip
    

    Dabei gilt:

    • gke-load-balancer-ip ist die IP-Adresse Ihres GKE-Load-Balancers (Proxy-IP).

    Drücken Sie CTRL+C, um die Wiedergabe zu beenden.

Wenn einer der vorherigen Schritte zu einem Fehler führt, lesen Sie die Schritte zur Fehlerbehebung.

Authentifizierungstoken generieren

Das folgende Verfahren zum Generieren eines Authentifizierungstokens dient als Beispiel. Für Ihre Produktionsumgebung benötigen Sie eine Möglichkeit, mit Nutzer ihre eigenen Authentifizierungstoken generieren können. Beispielcode zum programmatischen Abrufen eines OIDC-ID-Tokens finden Sie in der Dokumentation zu Identity-Aware Proxy.

So generieren Sie ein Authentifizierungstoken:

  1. Erstellen Sie ein Google Cloud-Dienstkonto, für das Sie ein OIDC-ID-Token generieren:

    gcloud iam service-accounts create \
        $SERVICE_ACCOUNT \
        --display-name $SERVICE_ACCOUNT
    
  2. Rufen Sie die E-Mail-Identität des Dienstkontos ab:

    SA_EMAIL=${SERVICE_ACCOUNT}@${PROJECT}.iam.gserviceaccount.com
    
  3. Weisen Sie dem Dienstkonto die IAM-Rolle Ersteller von Dienstkonto-Tokens (roles/iam.serviceAccountTokenCreator) zu:

    gcloud iam service-accounts add-iam-policy-binding $SA_EMAIL \
        --member user:$(gcloud config get-value account) \
        --role roles/iam.serviceAccountTokenCreator
    
  4. Generieren Sie mithilfe der IAM Credentials API ein OIDC-ID-Token.

    TOKEN=$(curl -s ${GENERATE_TOKEN}/${SA_EMAIL}:generateIdToken \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
        -d '{"audience": "'${ENDPOINTS_SERVICE}'", "includeEmail": "true"}' | jq -r ".token")
    

    Der Endpoints-Dienstname wird im Feld audience angegeben. Die audience-Anforderung identifiziert den Empfänger, für den das Token bestimmt ist.

  5. Prüfen Sie, ob das Token erfolgreich erstellt wurde:

    echo $TOKEN
    

    Das JSON-Webtoken (JWT) sieht in etwa so aus:

    eyJhbGciOiJSUzI1NiIsImtpZCI6IjY4NjQyODlm[...].eyJhdWQiOiJwdWJ0ZXN0LmVuZHBvaW50cy52aXR
    hbC1vY3RhZ29uLTEwOTYxMi5jbG91ZC5nb[...].SjBI4TZjZAlYo6lFKkrvfAcVUp_AJzFKoSsjNbmD_n[...]
    

Pub/Sub über einen Proxy aufrufen

  1. Veröffentlichen Sie in Cloud Shell eine Testnachricht:

    curl -i -k -X POST https://${ENDPOINTS_SERVICE}/publish \
        -H "Authorization: Bearer $TOKEN" \
        -H "Content-Type: application/json" \
        -d '{"topic": "'$TOPIC'", "messages": [ {"attributes": {"key1": "value1", "key2" : "value2"}, "data": "test data"}]}'
    

    Die Ausgabe sieht etwa so aus:

    HTTP/2 200
    server: nginx
    date: Sun, 02 Jun 2019 03:53:46 GMT
    ...
    
  2. Prüfen Sie, ob die Nachricht erfolgreich im Pub/Sub-Thema veröffentlicht wurde:

    kubectl logs -f --tail=5 deployment/pubsub-proxy -c pubsub-proxy
    

    In den Bereitstellungslogs des Pub/Sub-Proxys wird die Nachricht Successfully published angezeigt:

    2019-06-02 03:49:39.723:INFO:oejs.Server:main: Started @2554ms
    Jun 02, 2019 3:53:44 AM com.google.pubsub.proxy.publish.PublishMessage
    getPublisher
    INFO: Creating new publisher for: proxy-test
    Jun 02, 2019 3:53:47 AM
    com.google.pubsub.proxy.publish.PublishMessage$1 onSuccess
    INFO: Successfully published: 569006136173844
    

Fehlerbehebung

  1. Prüfen Sie in Cloud Shell den Status der beiden Container im Pub/Sub-Proxy-Pod:

    kubectl describe pods $(kubectl get pod -l app=pubsub-proxy \
        -o jsonpath="{.items[0].metadata.name}")
    

    In der Logausgabe lautet der Status der Container Running:

    [...]
    Containers:
      esp:
    [...]
      State:  Running
        Started:  Fri, 21 Jun 2019 16:41:30 +0530
      Ready:  True
      Restart Count:  0
    [...]
      pubsub-proxy:
        State:  Running
          Started:  Fri, 21 Jun 2019 16:41:42 +0530
        Ready:  True
        Restart Count:  0
    [...]
    
  2. (Optional) Sehen Sie sich die Containerlogs an, um festzustellen, ob andere Fehler vorliegen. Führen Sie beispielsweise den folgenden Befehl aus, um die Pub/Sub-Proxy-Logs zu prüfen:

    kubectl logs -f --tail=10 deployment/pubsub-proxy -c pubsub-proxy
    

Hilfe zur Fehlerbehebung finden Sie in den folgenden Dokumenten:

Bereinigen

Wenn Sie Kosten für Ihr Google Cloud-Konto für die in dieser Anleitung verwendeten Ressourcen vermeiden möchten, können Sie das Google Cloud-Projekt, das Sie für diese Anleitung erstellt haben, oder die mit dieser Anleitung verknüpften Ressourcen löschen.

Google Cloud-Projekt löschen

Am einfachsten vermeiden Sie weitere Kosten, indem Sie das für die Anleitung erstellte Projekt löschen.

  1. Wechseln Sie in der Google Cloud Console zur Seite Ressourcen verwalten.

    Zur Seite „Ressourcen verwalten“

  2. Wählen Sie in der Projektliste das Projekt aus, das Sie löschen möchten, und klicken Sie dann auf Löschen.
  3. Geben Sie im Dialogfeld die Projekt-ID ein und klicken Sie auf Shut down (Beenden), um das Projekt zu löschen.

Ressourcen löschen

Wenn Sie das in dieser Anleitung verwendete Google Cloud-Projekt beibehalten möchten, löschen Sie die einzelnen Ressourcen:

  1. Löschen Sie den GKE-Cluster in Cloud Shell:

    gcloud container clusters delete $CLUSTER --zone $ZONE --async
    
  2. Löschen Sie heruntergeladenen Code, Artefakte und andere Abhängigkeiten:

    cd .. && rm -rf solutions-pubsub-proxy-rest
    
  3. Löschen Sie das Image in Container Registry:

    gcloud container images list-tags \
        gcr.io/$PROJECT/pubsub-proxy \
        --format 'value(digest)' | \
        xargs -I {} gcloud container images delete \
        --force-delete-tags --quiet \
        gcr.io/${PROJECT}/pubsub-proxy@sha256:{}
    
  4. Löschen Sie das Pub/Sub-Thema:

    gcloud pubsub topics delete $TOPIC
    
  5. Löschen Sie das Dienstkonto:

    gcloud iam service-accounts delete $SA_EMAIL
    
  6. Löschen Sie Endpoints:

    gcloud endpoints services delete ${ENDPOINTS_SERVICE}
    
  7. Löschen Sie die statische IP-Adresse:

    gcloud compute addresses delete service-ip --region $REGION
    

Nächste Schritte