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

1. Übersicht

Mit dem Cloud SQL Go-Connector können Sie Ihre Go-Anwendung ganz einfach sicher mit Ihrer Cloud SQL-Datenbank verbinden. Cloud Run ist eine vollständig verwaltete serverlose Plattform, mit der Sie zustandslose Container ausführen können, die sich über HTTP-Anfragen aufrufen lassen. In diesem Codelab wird gezeigt, wie Sie eine Go-Anwendung in Cloud Run mithilfe der IAM-Authentifizierung sicher mit einem Dienstkonto 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 über den Go-Connector mit Cloud SQL verbinden

Vorbereitung

  • In diesem Lab wird davon ausgegangen, dass Sie mit der Cloud Console und 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. Falls Sie noch kein Google-Konto haben, müssen Sie ein Konto erstellen.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Der Projektname ist der Anzeigename für die Projektteilnehmer. Es handelt sich um eine Zeichenfolge, die von Google APIs nicht verwendet wird. Sie können sie jederzeit aktualisieren.
  • Die Projekt-ID ist für alle Google Cloud-Projekte eindeutig und unveränderlich. Sie kann nach dem Festlegen nicht mehr geändert werden. Die Cloud Console generiert automatisch einen eindeutigen String. ist Ihnen meist egal, was es ist. In den meisten Codelabs musst du auf die Projekt-ID verweisen, die üblicherweise als PROJECT_ID gekennzeichnet ist. Wenn Ihnen die generierte ID nicht gefällt, können Sie eine weitere zufällige ID erstellen. Alternativ können Sie einen eigenen verwenden und nachsehen, ob er verfügbar ist. Sie kann nach diesem Schritt nicht mehr geändert werden und bleibt für die Dauer des Projekts bestehen.
  • Zur Information gibt es noch einen dritten Wert, die Projektnummer, die von manchen APIs verwendet wird. Weitere Informationen zu allen drei Werten finden Sie in der Dokumentation.
  1. Als Nächstes müssen Sie in der Cloud Console die Abrechnung aktivieren, um Cloud-Ressourcen/APIs verwenden zu können. Dieses Codelab sollte möglichst wenig kosten. Wenn Sie Ressourcen herunterfahren möchten, um über diese Anleitung hinaus keine Kosten zu verursachen, können Sie die von Ihnen erstellten Ressourcen oder das gesamte Projekt löschen. Neue Google Cloud-Nutzer haben Anspruch auf eine kostenlose Testversion mit 300$Guthaben.

Umgebung einrichten

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

ecdc43ada29e91b.png

Aktivieren Sie in Cloud Shell die APIs:

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

Die Ausführung dieses Befehls kann einige Minuten dauern, sollte jedoch am Ende eine Meldung wie diese erhalten:

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 erforderlichen 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 folgt aus, um dem gerade erstellten Google Cloud-Dienstkonto die Rolle Cloud SQL-Client hinzuzufügen. In Cloud Shell wird der Ausdruck ${GOOGLE_CLOUD_PROJECT} durch den Namen Ihres Projekts ersetzt. Du kannst den Austausch auch manuell vornehmen, wenn du damit einverstanden bist.
    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“ so aus, um dem gerade erstellten Google Cloud-Dienstkonto 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 folgt aus, um dem gerade 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: Typ und Version des Datenbankmoduls. Falls nicht angegeben, wird der API-Standard verwendet. Die aktuell verfügbaren Versionen finden Sie in der Dokumentation zu den gcloud-Datenbankversionen.
  • -cpu: Die Anzahl der in der Maschine gewünschten Kerne.
  • -memory: Ganzzahl, die angibt, wie viel Arbeitsspeicher auf der Maschine benötigt wird 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 mit dem zuvor erstellten 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 im 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 für den Zugriff auf die Datenbank erstellt haben.

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

5. Antrag vorbereiten

Go-Anwendung vorbereiten, die auf HTTP-Anfragen antwortet

  1. Erstellen Sie in Cloud Shell ein neues Verzeichnis mit dem Namen helloworld und wechseln Sie zu diesem Verzeichnis:
    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 Abhängigkeit des Cloud SQL Go-Connectors.
    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. Der Code kann:
    • HTTP-Anfragen akzeptieren
    • Verbindung zur Datenbank herstellen
    • Zeitpunkt der HTTP-Anfrage in der Datenbank speichern
    • Zeitpunkt 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 die Umgebungsvariablen fest, die von der Anwendung verwendet werden, um die Anwendung zur Cloud SQL-Datenbank zu leiten.
  • –service-account: Bindet die Cloud Run-Bereitstellung mit dem Dienstkonto und hat die Berechtigungen zum Herstellen einer Verbindung zur Cloud SQL-Datenbank, die zu Beginn dieses Codelabs erstellt wurde.
  • –allow-unAuthenticate: Lässt nicht authentifizierte Anfragen zu, sodass 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 in der Anwendung eine URL angezeigt werden, 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 im JSON-Format 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 über den 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 folgenden Befehl ausführen:

gcloud projects delete ${GOOGLE_CLOUD_PROJECT}