Jak połączyć aplikację w języku Go w Cloud Run z bazą danych Cloud SQL for PostgreSQL

1. Omówienie

Oprogramowanie sprzęgające Cloud SQL Go to najprostszy sposób na bezpieczne połączenie aplikacji w języku Go z bazą danych Cloud SQL. Cloud Run to w pełni zarządzana bezserwerowa platforma, która umożliwia uruchamianie bezstanowych kontenerów wywoływanych przez żądania HTTP. W ramach tego ćwiczenia w Codelabs pokażemy, jak bezpiecznie połączyć aplikację w języku Go w Cloud Run z bazą danych Cloud SQL for PostgreSQL za pomocą konta usługi przy użyciu uwierzytelniania uprawnień.

Czego się nauczysz

Z tego modułu nauczysz się:

  • Tworzenie bazy danych Cloud SQL for PostgreSQL
  • Wdrażanie aplikacji w języku Go w Cloud Run
  • Połącz aplikację z Cloud SQL za pomocą oprogramowania sprzęgającego Go

Wymagania wstępne

  • W tym module zakładamy, że znasz środowiska konsoli Cloud i Cloud Shell.

2. Zanim zaczniesz

Konfigurowanie projektu Cloud

  1. Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub wykorzystaj już istniejący. Jeśli nie masz jeszcze konta Google, musisz je utworzyć.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Nazwa projektu jest wyświetlaną nazwą uczestników tego projektu. To ciąg znaków, który nie jest używany przez interfejsy API Google. W każdej chwili możesz ją zmienić.
  • Identyfikator projektu jest unikalny we wszystkich projektach Google Cloud i nie można go zmienić (po jego ustawieniu nie można go zmienić). Cloud Console automatycznie wygeneruje unikalny ciąg znaków. zwykle nieważne, co ona jest. W większości ćwiczeń z programowania konieczne jest odwołanie się do identyfikatora projektu (zwykle nazywa się on PROJECT_ID). Jeśli nie podoba Ci się wygenerowany identyfikator, możesz wygenerować kolejny losowy. Możesz też spróbować własnych sił i sprawdzić, czy jest dostępna. Potem nie będzie można go zmienić. Pozostanie ono przez czas trwania projektu.
  • Dostępna jest trzecia wartość, numer projektu, z którego korzystają niektóre interfejsy API. Więcej informacji o wszystkich 3 wartościach znajdziesz w dokumentacji.
  1. Następnie musisz włączyć płatności w Cloud Console, aby korzystać z zasobów Cloud/interfejsów API. Ukończenie tego ćwiczenia z programowania nie powinno kosztować zbyt wiele. Aby wyłączyć zasoby, aby nie naliczać opłat po zakończeniu tego samouczka, możesz usunąć utworzone zasoby lub cały projekt. Nowi użytkownicy Google Cloud mogą skorzystać z programu bezpłatnego okresu próbnego o wartości 300 USD.

Konfiguracja środowiska

Aktywuj Cloud Shell, klikając ikonę po prawej stronie paska wyszukiwania.

ecdc43ada29e91b.png

W Cloud Shell włącz interfejsy API:

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

Jeśli pojawi się prośba o autoryzację, kliknij „Autoryzuj”. aby kontynuować.

6356559df3eccdda.png

Ukończenie tego polecenia może zająć kilka minut, ale w końcu powinno wyświetlić się pomyślnie komunikat podobny do tego:

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

3. Skonfiguruj konto usługi

Utwórz i skonfiguruj konto usługi Google Cloud, które będzie używane przez Cloud Run, aby miało odpowiednie uprawnienia do łączenia się z Cloud SQL.

  1. Uruchom polecenie gcloud iam service-accounts create w ten sposób, aby utworzyć nowe konto usługi:
    gcloud iam service-accounts create quickstart-service-account \
      --display-name="Quickstart Service Account"
    
  2. Uruchom następujące polecenie gcloud projects add-iam-policy-binding w ten sposób, aby dodać rolę Klient Cloud SQL do właśnie utworzonego konta usługi Google Cloud. W Cloud Shell wyrażenie ${GOOGLE_CLOUD_PROJECT} zostanie zastąpione nazwą Twojego projektu. Jeśli wolisz, możesz też zrobić to ręcznie.
    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. Aby dodać rolę Użytkownik instancji Cloud SQL do nowo utworzonego konta usługi Google Cloud, uruchom polecenie add-iam-policy-binding w ramach narzędzia gcloud projects.
    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. Aby dodać rolę zapisującego logi do nowo utworzonego konta usługi Google Cloud, uruchom polecenie add-iam-policy-binding w gcloud projects.
    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. Skonfiguruj Cloud SQL

Uruchom polecenie gcloud sql instances create, aby utworzyć instancję Cloud SQL.

  • –database-version: typ i wersja silnika bazy danych. Jeśli wartość nie zostanie określona, używana jest wartość domyślna interfejsu API. Aby sprawdzić bieżące dostępne wersje, zapoznaj się z dokumentacją wersji bazy danych gcloud.
  • –cpu: liczba rdzeni komputera.
  • –memory: liczba całkowita wskazująca ilość pamięci wymaganej przez komputer. Należy podać jednostkę rozmiaru (na przykład 3072 MB lub 9 GB). Jeśli nie podasz żadnych jednostek, przyjmuje się, że GB jest GB.
  • –region: regionalna lokalizacja instancji (na przykład us-central1, asia-east1, us-east1).
  • –database-flags: umożliwia ustawianie flag. W tym przypadku włączymy funkcję cloudsql.iam_authentication, aby umożliwić Cloud Run połączenie się z Cloud SQL przy użyciu utworzonego wcześniej konta usługi.
    gcloud sql instances create quickstart-instance \
      --database-version=POSTGRES_14 \
      --cpu=1 \
      --memory=4GB \
      --region=us-central1 \
      --database-flags=cloudsql.iam_authentication=on
    

Wykonanie tego polecenia może zająć kilka minut.

Uruchom polecenie gcloud sql databases create, aby utworzyć bazę danych Cloud SQL w narzędziu quickstart-instance.

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

Aby uzyskać dostęp do bazy danych, utwórz użytkownika bazy danych PostgreSQL dla utworzonego wcześniej konta usługi.

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

5. Przygotowanie aplikacji

Przygotuj aplikację w języku Go, która odpowiada na żądania HTTP.

  1. W Cloud Shell utwórz nowy katalog o nazwie helloworld, a następnie przejdź do tego katalogu:
    mkdir helloworld
    cd helloworld
    
  2. Uruchom go mod init, aby zainicjować nową aplikację w języku Go.
    go mod init github.com/GoogleCloudPlatform/golang-samples/run/helloworld
    
  3. Zainstaluj zależność oprogramowania sprzęgającego Cloud SQL Go.
    go get cloud.google.com/go/cloudsqlconn
    go get cloud.google.com/go/cloudsqlconn/postgres/pgxv4
    
  4. Utwórz plik main.go z kodem aplikacji. Ten kod umożliwia:
    • Akceptuj żądania HTTP
    • Połącz z bazą danych
    • Zapisywanie czasu żądania HTTP w bazie danych
    • Zwróć czas ostatnich 5 żądań
    . Uruchom to polecenie w Cloud Shell:
    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
    

Ten kod tworzy podstawowy serwer WWW, który nasłuchuje na porcie określonym przez zmienną środowiskową PORT. Aplikacja jest teraz gotowa do wdrożenia.

6. Wdrażanie aplikacji Cloud Run

Uruchom to polecenie, aby wdrożyć aplikację:

  • –region: regionalna lokalizacja instancji (na przykład us-central1, asia-east1, us-east1).
  • –source: kod źródłowy do wdrożenia. W tym przypadku . odnosi się do kodu źródłowego w bieżącym folderze helloworld.
  • –set-env-vars: ustawia zmienne środowiskowe używane przez aplikację do kierowania aplikacji do bazy danych Cloud SQL.
  • –konto-usługi: łączy wdrożenie w Cloud Run z kontem usługi z uprawnieniami do połączenia z bazą danych Cloud SQL utworzoną na początku tego ćwiczenia z programowania.
  • –allow-unauthenticated: zezwala na nieuwierzytelnione żądania, aby aplikacja była dostępna w internecie.
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

Jeśli pojawi się pytanie, naciśnij y i Enter, aby potwierdzić, że chcesz kontynuować:

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

Po kilku minutach aplikacja powinna udostępnić URL, który możesz otworzyć.

Przejdź do adresu URL, aby zobaczyć, jak działa Twoja aplikacja. Za każdym razem, gdy odwiedzisz URL lub odświeżysz stronę, zobaczysz pięć ostatnich wizyt zwróconych w formacie JSON.

7. Gratulacje

Masz wdrożoną w Cloud Run aplikację w języku Go, która może połączyć się z bazą danych PostgreSQL działającą w Cloud SQL.

Omówione zagadnienia:

  • Tworzenie bazy danych Cloud SQL for PostgreSQL
  • Wdrażanie aplikacji w języku Go w Cloud Run
  • Łączenie aplikacji z Cloud SQL za pomocą oprogramowania sprzęgającego Go

Czyszczenie danych

Aby uniknąć obciążenia konta Google Cloud opłatami za zasoby zużyte w tym samouczku, możesz usunąć projekt zawierający te zasoby lub zachować projekt i usunąć poszczególne zasoby. Jeśli chcesz usunąć cały projekt, możesz uruchomić te polecenia:

gcloud projects delete ${GOOGLE_CLOUD_PROJECT}