1. 總覽
Cloud SQL Go 連接器是將 Go 應用程式安全連線至 Cloud SQL 資料庫最簡單的方式。Cloud Run 是全代管無伺服器平台,能讓您執行可透過 HTTP 要求叫用的無狀態容器。本程式碼研究室將示範如何使用 IAM 驗證機制,透過服務帳戶將 Cloud Run 上的 Go 應用程式安全連線至 PostgreSQL 適用的 Cloud SQL 資料庫。
學習目標
在本實驗室中,您將瞭解如何執行下列操作:
- 建立 PostgreSQL 適用的 Cloud SQL 資料庫
- 將 Go 應用程式部署至 Cloud Run
- 使用 Go 連接器將應用程式連結至 Cloud SQL
必要條件
- 本實驗室假設您已熟悉 Cloud 控制台和 Cloud Shell 環境。
2. 事前準備
設定 Cloud 專案
- 登入 Google Cloud 控制台,然後建立新專案或重複使用現有專案。如果沒有 Google 帳戶,請先建立帳戶。



- 專案名稱是這個專案參與者的顯示名稱。這是 Google API 未使用的字元字串。你隨時可以更新該位置資訊。
- 專案 ID 在所有 Google Cloud 專案中都是不重複的,而且設定後即無法變更。Cloud 控制台會自動產生不重複的字串,通常您不需要在意這個字串。在大多數程式碼研究室中,您需要參照專案 ID (通常會標示為
PROJECT_ID)。如果您不喜歡產生的 ID,可以產生另一個隨機 ID。你也可以嘗試自訂名稱,看看是否可用。完成這個步驟後就無法變更,且專案期間都會維持這個設定。 - 請注意,部分 API 會使用第三個值,也就是「專案編號」。如要進一步瞭解這三種值,請參閱說明文件。
- 接著,您需要在 Cloud 控制台中啟用帳單,才能使用 Cloud 資源/API。完成本程式碼研究室的費用應該不高,甚至完全免費。如要關閉資源,避免產生本教學課程以外的費用,您可以刪除自己建立的資源,或刪除整個專案。Google Cloud 新使用者可參加價值$300 美元的免費試用計畫。
環境設定
按一下搜尋列右側的圖示,啟用 Cloud Shell。

在 Cloud Shell 中啟用 API:
gcloud services enable compute.googleapis.com sqladmin.googleapis.com \
run.googleapis.com artifactregistry.googleapis.com \
cloudbuild.googleapis.com servicenetworking.googleapis.com
如果系統提示您授權,請點選「授權」繼續操作。

這個指令可能需要幾分鐘才能完成,但最終應該會產生類似以下的成功訊息:
Operation "operations/acf.p2-327036483151-73d90d00-47ee-447a-b600-a6badf0eceae" finished successfully.
3. 設定服務帳戶
建立及設定 Google Cloud 服務帳戶,供 Cloud Run 使用,確保該帳戶具備連線至 Cloud SQL 的正確權限。
- 執行下列
gcloud iam service-accounts create指令,建立新的服務帳戶:gcloud iam service-accounts create quickstart-service-account \ --display-name="Quickstart Service Account" - 執行 gcloud projects add-iam-policy-binding 指令,將「Cloud SQL Client」(Cloud SQL 用戶端) 角色新增至您剛建立的 Google Cloud 服務帳戶。在 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" - 執行下列 gcloud projects add-iam-policy-binding 指令,將「Cloud SQL Instance User」(Cloud SQL 執行個體使用者) 角色新增至您剛建立的 Google Cloud 服務帳戶。
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \ --member="serviceAccount:quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \ --role="roles/cloudsql.instanceUser" - 執行下列 gcloud projects add-iam-policy-binding 指令,將「記錄檔寫入者」角色新增至您剛建立的 Google Cloud 服務帳戶。
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:整數值,表示機器所需的記憶體量。請提供大小單位 (例如 3072MB 或 9GB)。如未指定單位,系統會假設您使用的是 GB。
- –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 指令,在 quickstart-instance 中建立 Cloud SQL 資料庫。
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. 準備應用程式
準備可回應 HTTP 要求的 Go 應用程式。
- 在 Cloud Shell 建立名為
helloworld的新目錄,然後前往該目錄:mkdir helloworld cd helloworld - 執行
go mod init來初始化新的 Go 應用程式。go mod init github.com/GoogleCloudPlatform/golang-samples/run/helloworld - 安裝 Cloud SQL Go 連接器依附元件。
go get cloud.google.com/go/cloudsqlconn go get cloud.google.com/go/cloudsqlconn/postgres/pgxv4 - 建立包含應用程式程式碼的
main.go檔案。這組代碼可執行下列操作:- 接受 HTTP 要求
- 連線至資料庫
- 將 HTTP 要求的時間儲存在資料庫中
- 傳回最近五次要求的時間
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. 部署 Cloud Run 應用程式
執行下列指令來部署應用程式:
- –region:執行個體所在的區域位置 (例如:us-central1、asia-east1、us-east1)。
- –source:要部署的原始碼。在本例中,
.是指目前資料夾helloworld中的原始碼。 - --set-env-vars:設定應用程式使用的環境變數,將應用程式導向 Cloud SQL 資料庫。
- --service-account:將 Cloud Run 部署作業繫結至服務帳戶,該帳戶具有連線至本 Codelab 開頭建立的 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
幾分鐘後,應用程式應會提供網址供您造訪。
前往該網址,即可查看應用程式的運作情形。每次造訪網址或重新整理頁面時,系統都會以 JSON 格式傳回最近五次造訪記錄。
7. 恭喜
您已在 Cloud Run 上部署 Go 應用程式,並連線至 Cloud SQL 上執行的 PostgreSQL 資料庫。
涵蓋內容:
- 建立 PostgreSQL 適用的 Cloud SQL 資料庫
- 將 Go 應用程式部署至 Cloud Run
- 使用 Go 連接器將應用程式連線至 Cloud SQL
清除所用資源
如要避免系統向您的 Google Cloud 帳戶收取本教學課程所用資源的費用,請刪除含有相關資源的專案,或者保留專案但刪除個別資源。如要刪除整個專案,請執行:
gcloud projects delete ${GOOGLE_CLOUD_PROJECT}