Go-Anwendung in Cloud Run mit einer Cloud SQL for PostgreSQL-Datenbank verbinden

1. Übersicht

Der Cloud SQL-Go-Connector ist die einfachste Möglichkeit, Ihre Go-Anwendung sicher mit Ihrer Cloud SQL-Datenbank zu verbinden. Cloud Run ist eine vollständig verwaltete serverlose Plattform, mit der Sie zustandslose Container ausführen können, die über HTTP-Anfragen aufrufbar sind. In diesem Codelab wird gezeigt, wie Sie eine Go-Anwendung in Cloud Run sicher mit einem Dienstkonto über die IAM-Authentifizierung mit einer Cloud SQL for PostgreSQL-Datenbank verbinden.

Lerninhalte

In diesem Lab lernen Sie Folgendes:

  • Cloud SQL for PostgreSQL-Datenbank erstellen
  • Go-Anwendung in Cloud Run bereitstellen
  • Anwendung mit dem Go-Connector mit Cloud SQL verbinden

Vorbereitung

  • Für dieses Lab wird davon ausgegangen, dass Sie mit der Cloud Console und mit Cloud Shell-Umgebungen vertraut sind.

2. Hinweis

Cloud-Projekt einrichten

  1. Melden Sie sich in der Google Cloud Console an und erstellen Sie ein neues Projekt oder verwenden Sie ein vorhandenes Projekt. Wenn Sie noch kein Google-Konto haben, müssen Sie eines erstellen.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Der Projektname ist der Anzeigename für die Teilnehmer dieses Projekts. Es handelt sich um einen String, der nicht von Google APIs verwendet wird. Sie können ihn jederzeit aktualisieren.
  • Die Projekt-ID ist für alle Google Cloud-Projekte eindeutig und unveränderlich (kann nach dem Festlegen nicht mehr geändert werden). In der Cloud Console wird automatisch ein eindeutiger String generiert. Normalerweise ist es nicht wichtig, wie dieser String aussieht. In den meisten Codelabs müssen Sie auf die Projekt-ID verweisen (sie wird in der Regel als PROJECT_ID angegeben). Wenn Ihnen die generierte ID nicht gefällt, können Sie eine andere zufällige ID generieren. Alternativ können Sie es mit einem eigenen versuchen und sehen, ob es verfügbar ist. Sie kann nach diesem Schritt nicht mehr geändert werden und bleibt für die Dauer des Projekts bestehen.
  • Zur Information: Es gibt einen dritten Wert, die Projektnummer, die von einigen APIs verwendet wird. Weitere Informationen zu diesen drei Werten
  1. Als Nächstes müssen Sie die Abrechnung in der Cloud Console aktivieren, um Cloud-Ressourcen/-APIs zu verwenden. Die Durchführung dieses Codelabs sollte keine oder nur geringe Kosten verursachen. Wenn Sie Ressourcen herunterfahren möchten, damit Ihnen nach Abschluss dieser Anleitung keine Kosten mehr in Rechnung gestellt werden, können Sie die von Ihnen erstellten Ressourcen oder das gesamte Projekt löschen. Neue Nutzer von Google Cloud kommen für das Programm für kostenlose Testversionen mit einem Guthaben von 300$ infrage.

Umgebung einrichten

Aktivieren Sie Cloud Shell, indem Sie rechts neben der Suchleiste auf das Symbol klicken.

ecdc43ada29e91b.png

Aktivieren Sie die APIs in Cloud Shell:

gcloud services enable compute.googleapis.com sqladmin.googleapis.com \
  run.googleapis.com artifactregistry.googleapis.com \
  cloudbuild.googleapis.com servicenetworking.googleapis.com

Wenn Sie zur Autorisierung aufgefordert werden, klicken Sie auf „Autorisieren“, um fortzufahren.

6356559df3eccdda.png

Es kann einige Minuten dauern, bis dieser Befehl ausgeführt wird. Wenn die Ausführung erfolgreich war, erhalten Sie eine Meldung, die ungefähr so aussieht:

Operation "operations/acf.p2-327036483151-73d90d00-47ee-447a-b600-a6badf0eceae" finished successfully.

3. Dienstkonto einrichten

Erstellen und konfigurieren Sie ein Google Cloud-Dienstkonto, das von Cloud Run verwendet werden soll, damit es die richtigen Berechtigungen zum Herstellen einer Verbindung zu Cloud SQL hat.

  1. Führen Sie den Befehl gcloud iam service-accounts create so aus, um ein neues Dienstkonto zu erstellen:
    gcloud iam service-accounts create quickstart-service-account \
      --display-name="Quickstart Service Account"
    
  2. Führen Sie den Befehl „gcloud projects add-iam-policy-binding“ wie unten beschrieben aus, um dem Google Cloud-Dienstkonto, das Sie gerade erstellt haben, die Rolle Cloud SQL-Client hinzuzufügen. In Cloud Shell wird der Ausdruck ${GOOGLE_CLOUD_PROJECT} durch den Namen Ihres Projekts ersetzt. Sie können den Austausch auch manuell vornehmen, wenn Sie sich damit wohler fühlen.
    gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
      --member="serviceAccount:quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
      --role="roles/cloudsql.client"
    
  3. Führen Sie den Befehl „gcloud projects add-iam-policy-binding“ wie unten beschrieben aus, um dem Google Cloud-Dienstkonto, das Sie gerade erstellt haben, die Rolle Cloud SQL-Instanznutzer hinzuzufügen.
    gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
      --member="serviceAccount:quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
      --role="roles/cloudsql.instanceUser"
    
  4. Führen Sie den Befehl „gcloud projects add-iam-policy-binding“ wie unten beschrieben aus, um dem soeben erstellten Google Cloud-Dienstkonto die Rolle Logautor hinzuzufügen.
    gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
      --member="serviceAccount:quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
      --role="roles/logging.logWriter"
    

4. Cloud SQL einrichten

Führen Sie den Befehl gcloud sql instances create aus, um eine Cloud SQL-Instanz zu erstellen.

  • –database-version: Der Typ und die Version des Datenbankmoduls. Falls nicht angegeben, wird der API-Standard verwendet. Die derzeit verfügbaren Versionen finden Sie in der Dokumentation zu gcloud-Datenbankversionen.
  • –cpu: Die Anzahl der in der Maschine gewünschten Kerne.
  • –memory: Ganzzahliger Wert, der angibt, wie viel Arbeitsspeicher in der Maschine gewünscht ist. Es sollte eine Größeneinheit angegeben werden (z. B. 3.072 MB oder 9 GB). Wenn keine Einheiten angegeben sind, wird von GB ausgegangen.
  • –region: Regionaler Standort der Instanz, z. B. us-central1, asia-east1, us-east1.
  • –database-flags: Ermöglicht das Festlegen von Flags. In diesem Fall aktivieren wir cloudsql.iam_authentication, damit Cloud Run über das zuvor erstellte Dienstkonto eine Verbindung zu Cloud SQL herstellen kann.
    gcloud sql instances create quickstart-instance \
      --database-version=POSTGRES_14 \
      --cpu=1 \
      --memory=4GB \
      --region=us-central1 \
      --database-flags=cloudsql.iam_authentication=on
    

Die Ausführung dieses Befehls kann einige Minuten dauern.

Führen Sie den Befehl gcloud sql databases create aus, um eine Cloud SQL-Datenbank in der quickstart-instance zu erstellen.

gcloud sql databases create quickstart_db \
  --instance=quickstart-instance

Erstellen Sie einen PostgreSQL-Datenbanknutzer für das Dienstkonto, das Sie zuvor erstellt haben, um auf die Datenbank zuzugreifen.

gcloud sql users create quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam \
  --instance=quickstart-instance \
  --type=cloud_iam_service_account

5. Anwendung vorbereiten

Bereiten Sie eine Go-Anwendung vor, die auf HTTP-Anfragen reagiert.

  1. Erstellen Sie in Cloud Shell ein neues Verzeichnis mit dem Namen helloworld und öffnen Sie es:
    mkdir helloworld
    cd helloworld
    
  2. Führen Sie go mod init aus, um eine neue Go-Anwendung zu initialisieren.
    go mod init github.com/GoogleCloudPlatform/golang-samples/run/helloworld
    
  3. Installieren Sie die Cloud SQL Go-Connector-Abhängigkeit.
    go get cloud.google.com/go/cloudsqlconn
    go get cloud.google.com/go/cloudsqlconn/postgres/pgxv4
    
  4. Erstellen Sie eine main.go-Datei mit dem Anwendungscode. Dieser Code kann Folgendes:
    • HTTP-Anfragen annehmen
    • Verbindung zur Datenbank herstellen
    • Zeitpunkt der HTTP-Anfrage in der Datenbank speichern
    • Zeitpunkte der letzten fünf Anfragen zurückgeben
    Führen Sie in Cloud Shell den folgenden Befehl aus:
    cat > main.go << "EOF"
    package main
    
    import (
      "database/sql"
      "encoding/json"
      "fmt"
      "log"
      "net/http"
      "os"
      "time"
    
      "cloud.google.com/go/cloudsqlconn"
      "cloud.google.com/go/cloudsqlconn/postgres/pgxv4"
    )
    
    // visitData is used to pass data to the HTML template.
    type visitData struct {
      RecentVisits []visit
    }
    
    // visit contains a single row from the visits table in the database.
    // Each visit includes a timestamp.
    type visit struct {
      VisitTime time.Time
    }
    
    // getDB creates a connection to the database
    // based on environment variables.
    func getDB() (*sql.DB, func() error) {
      cleanup, err := pgxv4.RegisterDriver("cloudsql-postgres", cloudsqlconn.WithIAMAuthN())
      if err != nil {
        log.Fatalf("Error on pgxv4.RegisterDriver: %v", err)
      }
    
      dsn := fmt.Sprintf("host=%s user=%s dbname=%s sslmode=disable", os.Getenv("INSTANCE_CONNECTION_NAME"), os.Getenv("DB_USER"), os.Getenv("DB_NAME"))
      db, err := sql.Open("cloudsql-postgres", dsn)
      if err != nil {
        log.Fatalf("Error on sql.Open: %v", err)
      }
    
      createVisits := `CREATE TABLE IF NOT EXISTS visits (
        id SERIAL NOT NULL,
        created_at timestamp NOT NULL,
        PRIMARY KEY (id)
      );`
      _, err = db.Exec(createVisits)
      if err != nil {
        log.Fatalf("unable to create table: %s", err)
      }
    
      return db, cleanup
    }
    
    func main() {
      port := os.Getenv("PORT")
      if port == "" {
        port = "8080"
      }
      log.Printf("Listening on port %s", port)
      db, cleanup := getDB()
      defer cleanup()
    
      http.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
        // Insert current visit
        _, err := db.Exec("INSERT INTO visits(created_at) VALUES(NOW())")
        if err != nil {
          log.Fatalf("unable to save visit: %v", err)
        }
    
        // Get the last 5 visits
        rows, err := db.Query("SELECT created_at FROM visits ORDER BY created_at DESC LIMIT 5")
        if err != nil {
          log.Fatalf("DB.Query: %v", err)
        }
        defer rows.Close()
    
        var visits []visit
        for rows.Next() {
          var visitTime time.Time
          err := rows.Scan(&visitTime)
          if err != nil {
            log.Fatalf("Rows.Scan: %v", err)
          }
          visits = append(visits, visit{VisitTime: visitTime})
        }
        response, err := json.Marshal(visitData{RecentVisits: visits})
        if err != nil {
          log.Fatalf("renderIndex: failed to parse totals with json.Marshal: %v", err)
        }
        w.Write(response)
      })
      if err := http.ListenAndServe(":"+port, nil); err != nil {
        log.Fatal(err)
      }
    }
    
    EOF
    

Mit diesem Code wird ein einfacher Webserver erstellt, der den von der Umgebungsvariable PORT definierten Port überwacht. Die Anwendung kann jetzt bereitgestellt werden.

6. Cloud Run-Anwendung bereitstellen

Führen Sie den folgenden Befehl aus, um die Anwendung bereitzustellen:

  • –region: Regionaler Standort der Instanz, z. B. us-central1, asia-east1, us-east1.
  • –source: Der Quellcode, der bereitgestellt werden soll. In diesem Fall bezieht sich . auf den Quellcode im aktuellen Ordner helloworld.
  • –set-env-vars: Legt Umgebungsvariablen fest, die von der Anwendung verwendet werden, um sie zur Cloud SQL-Datenbank weiterzuleiten.
  • –service-account: Verknüpft die Cloud Run-Bereitstellung mit dem Dienstkonto mit Berechtigungen zum Herstellen einer Verbindung zur Cloud SQL-Datenbank, die am Anfang dieses Codelabs erstellt wurde.
  • –allow-unauthenticated: Ermöglicht nicht authentifizierte Anfragen, damit die Anwendung über das Internet zugänglich ist.
gcloud run deploy helloworld \
  --region=us-central1 \
  --source=. \
  --set-env-vars INSTANCE_CONNECTION_NAME="${GOOGLE_CLOUD_PROJECT}:us-central1:quickstart-instance" \
  --set-env-vars DB_NAME="quickstart_db" \
  --set-env-vars DB_USER="quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam" \
  --service-account="quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
  --allow-unauthenticated

Wenn Sie dazu aufgefordert werden, drücken Sie y und Enter, um zu bestätigen, dass Sie fortfahren möchten:

Do you want to continue (Y/n)? y

Nach einigen Minuten sollte die Anwendung eine URL bereitstellen, die Sie aufrufen können.

Rufen Sie die URL auf, um Ihre Anwendung in Aktion zu sehen. Jedes Mal, wenn Sie die URL aufrufen oder die Seite aktualisieren, werden die fünf letzten Besuche als JSON zurückgegeben.

7. Glückwunsch

Sie haben eine Go-Anwendung in Cloud Run bereitgestellt, die eine Verbindung zu einer PostgreSQL-Datenbank herstellen kann, die in Cloud SQL ausgeführt wird.

Behandelte Themen:

  • Cloud SQL for PostgreSQL-Datenbank erstellen
  • Go-Anwendung in Cloud Run bereitstellen
  • Anwendung mit dem Go-Connector mit Cloud SQL verbinden

Bereinigen

Damit Ihrem Google Cloud-Konto die in dieser Anleitung verwendeten Ressourcen nicht in Rechnung gestellt werden, können Sie entweder das Projekt löschen, das die Ressourcen enthält, oder das Projekt beibehalten und die einzelnen Ressourcen löschen. Wenn Sie das gesamte Projekt löschen möchten, können Sie Folgendes ausführen:

gcloud projects delete ${GOOGLE_CLOUD_PROJECT}