Как подключить приложение Go в Cloud Run к базе данных Cloud SQL для PostgreSQL

1. Обзор

Коннектор Cloud SQL для Go — это самый простой способ безопасно подключить ваше приложение Go к базе данных Cloud SQL. Cloud Run — это полностью управляемая бессерверная платформа, позволяющая запускать контейнеры без сохранения состояния, вызываемые через HTTP-запросы. В этом практическом занятии будет продемонстрировано, как безопасно подключить приложение Go в Cloud Run к базе данных Cloud SQL для PostgreSQL с помощью учетной записи службы, используя аутентификацию IAM.

Что вы узнаете

В этой лабораторной работе вы научитесь выполнять следующие действия:

  • Создайте базу данных Cloud SQL для PostgreSQL.
  • Разверните приложение Go в Cloud Run.
  • Подключите ваше приложение к Cloud SQL с помощью Go Connector.

Предварительные требования

  • Для выполнения этой лабораторной работы предполагается знакомство со средами Cloud Console и Cloud Shell.

2. Прежде чем начать

Настройка облачного проекта

  1. Войдите в консоль Google Cloud и создайте новый проект или используйте существующий. Если у вас еще нет учетной записи Google, вам необходимо ее создать .

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Название проекта — это отображаемое имя участников данного проекта. Это строка символов, не используемая API Google. Вы можете изменить её в любое время.
  • Идентификатор проекта уникален для всех проектов Google Cloud и является неизменяемым (его нельзя изменить после установки). Консоль Cloud автоматически генерирует уникальную строку; обычно вам неважно, какая она. В большинстве практических заданий вам потребуется указать идентификатор проекта (обычно он обозначается как PROJECT_ID ). Если сгенерированный идентификатор вас не устраивает, вы можете сгенерировать другой случайный идентификатор. В качестве альтернативы вы можете попробовать свой собственный и посмотреть, доступен ли он. После этого шага его нельзя изменить, и он останется неизменным на протяжении всего проекта.
  • К вашему сведению, существует третье значение — номер проекта , который используется некоторыми API. Подробнее обо всех трех значениях можно узнать в документации .
  1. Далее вам потребуется включить оплату в консоли Cloud для использования ресурсов/API Cloud. Выполнение этого практического задания не должно стоить дорого, если вообще что-либо. Чтобы отключить ресурсы и избежать дополнительных расходов после завершения этого урока, вы можете удалить созданные ресурсы или удалить весь проект. Новые пользователи Google Cloud имеют право на бесплатную пробную версию стоимостью 300 долларов США .

Настройка среды

Активируйте Cloud Shell, нажав на значок справа от строки поиска.

ecdc43ada29e91b.png

В Cloud Shell включите API:

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

Если появится запрос на авторизацию, нажмите «Авторизовать», чтобы продолжить.

6356559df3eccdda.png

Выполнение этой команды может занять несколько минут, но в итоге должно отобразиться сообщение об успешном завершении, похожее на это:

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

3. Создайте учетную запись службы.

Создайте и настройте учетную запись службы Google Cloud для использования Cloud Run, чтобы она имела необходимые разрешения для подключения к Cloud SQL.

  1. Для создания новой учетной записи службы выполните команду gcloud iam service-accounts create следующим образом:
    gcloud iam service-accounts create quickstart-service-account \
      --display-name="Quickstart Service Account"
    
  2. Чтобы добавить роль клиента Cloud SQL в созданную учетную запись службы Google Cloud, выполните команду gcloud projects add-iam-policy-binding следующим образом. В Cloud Shell выражение ${GOOGLE_CLOUD_PROJECT} будет заменено именем вашего проекта. При желании вы также можете выполнить эту замену вручную.
    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. Чтобы добавить роль пользователя экземпляра Cloud SQL к только что созданной учетной записи службы Google Cloud, выполните команду gcloud projects add-iam-policy-binding следующим образом.
    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. Чтобы добавить роль Log Writer к только что созданной учетной записи службы Google Cloud, выполните команду gcloud projects add-iam-policy-binding следующим образом.
    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

Выполните команду gcloud sql instances create , чтобы создать экземпляр Cloud SQL.

  • –database-version : Тип и версия механизма базы данных. Если не указано иное, используется значение по умолчанию API. См. документацию по версиям баз данных gcloud, чтобы узнать о доступных версиях.
  • –cpu : Желаемое количество ядер в системе.
  • –memory : Целочисленное значение, указывающее, какой объем памяти требуется на компьютере. Необходимо указать единицу измерения (например, 3072 МБ или 9 ГБ). Если единица измерения не указана, используется ГБ.
  • –region : Региональное расположение экземпляра (например: us-central1, asia-east1, us-east1).
  • –database-flags : Позволяет устанавливать флаги. В данном случае мы включаем cloudsql.iam_authentication , чтобы Cloud Run мог подключаться к Cloud SQL, используя учетную запись службы, которую мы создали ранее.
    gcloud sql instances create quickstart-instance \
      --database-version=POSTGRES_14 \
      --cpu=1 \
      --memory=4GB \
      --region=us-central1 \
      --database-flags=cloudsql.iam_authentication=on
    

Выполнение этой команды может занять несколько минут.

Выполните команду gcloud sql databases create , чтобы создать базу данных Cloud SQL в quickstart-instance .

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

Создайте пользователя базы данных PostgreSQL для учетной записи службы, которую вы создали ранее, чтобы получить доступ к базе данных.

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

5. Подготовьте заявление.

Подготовьте Go-приложение, которое будет обрабатывать HTTP-запросы.

  1. В Cloud Shell создайте новую директорию с именем helloworld , затем перейдите в эту директорию:
    mkdir helloworld
    cd helloworld
    
  2. Запустите команду go mod init , чтобы инициализировать новое приложение Go.
    go mod init github.com/GoogleCloudPlatform/golang-samples/run/helloworld
    
  3. Установите зависимость Cloud SQL Go Connector.
    go get cloud.google.com/go/cloudsqlconn
    go get cloud.google.com/go/cloudsqlconn/postgres/pgxv4
    
  4. Создайте файл main.go с кодом приложения. Этот код способен:
    • Принимать HTTP-запросы
    • Подключитесь к базе данных
    • Сохраните время HTTP-запроса в базе данных.
    • Возвращает время выполнения последних пяти запросов.
    Выполните следующую команду в 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
    

Этот код создает базовый веб-сервер, который прослушивает порт, определенный переменной среды PORT. Теперь приложение готово к развертыванию.

6. Развертывание облачного приложения

Выполните указанную ниже команду для развертывания вашего приложения:

  • –region : Региональное расположение экземпляра (например: us-central1, asia-east1, us-east1).
  • –source : Исходный код для развертывания. В данном случае . обозначает исходный код в текущей папке helloworld .
  • –set-env-vars : Устанавливает переменные среды, используемые приложением для направления его работы к базе данных Cloud SQL.
  • –service-account : Привязывает развертывание Cloud Run к учетной записи службы с правами доступа к базе данных Cloud SQL, созданной в начале этого практического занятия.
  • –allow-unauthenticated : Разрешает неаутентифицированные запросы, чтобы приложение было доступно из интернета.
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

Если появится запрос, нажмите y и Enter , чтобы подтвердить продолжение:

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

Через несколько минут приложение должно предоставить вам URL-адрес для перехода по ссылке.

Перейдите по указанному URL-адресу, чтобы увидеть работу вашего приложения. При каждом посещении URL-адреса или обновлении страницы вы будете видеть данные о пяти последних посещениях в формате JSON.

7. Поздравляем!

Вы развернули приложение Go в Cloud Run, которое может подключаться к базе данных PostgreSQL, работающей в Cloud SQL.

Что мы рассмотрели:

  • Создание базы данных Cloud SQL для PostgreSQL
  • Развертывание приложения Go в Cloud Run
  • Подключение вашего приложения к Cloud SQL с помощью Go Connector

Уборка

Чтобы избежать списания средств с вашего аккаунта Google Cloud за ресурсы, используемые в этом руководстве, либо удалите проект, содержащий эти ресурсы, либо сохраните проект и удалите отдельные ресурсы. Если вы хотите удалить весь проект, выполните следующую команду:

gcloud projects delete ${GOOGLE_CLOUD_PROJECT}