1. 總覽
您可以使用 Cloud SQL Go 連接器,安全地將 Go 應用程式連線至 Cloud SQL 資料庫。Cloud Run 是全代管的無伺服器平台,能夠讓您執行可透過 HTTP 要求叫用的無狀態容器。這個程式碼研究室將示範如何使用 IAM 驗證功能,將 Cloud Run 上的 Go 應用程式安全地連結至 PostgreSQL 適用的 Cloud SQL 資料庫,以及使用 IAM 驗證功能。
學習目標
在本研究室中,您將瞭解如何執行下列操作:
- 建立 PostgreSQL 適用的 Cloud SQL 資料庫
- 將 Go 應用程式部署至 Cloud Run
- 使用 Go 連接器將應用程式連結至 Cloud SQL
必要條件
- 本研究室假設您熟悉 Cloud 控制台和 Cloud Shell 環境。
2. 事前準備
Cloud 專案設定
- 登入 Google Cloud 控制台,建立新專案或重複使用現有專案。如果您還沒有 Google 帳戶,請先建立帳戶。
- 「專案名稱」是這項專案參與者的顯示名稱。這是 Google API 未使用的字元字串。您隨時可以更新這項資訊。
- 所有 Google Cloud 專案的專案 ID 均不得重複,而且設定後即無法變更。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. 設定服務帳戶
建立並設定 Cloud Run 要使用的 Google Cloud 服務帳戶,讓該帳戶具備連線至 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 用戶端角色新增至您剛建立的 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 執行個體使用者角色新增至您剛建立的 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:整數值,表示機器所需的記憶體大小。必須提供尺寸單位 (例如 3072 MB 或 9 GB)。如未指定單位,則會採用 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 要求的時間儲存在資料庫中
- 傳回最後 5 個要求的時間
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 部署作業連結至服務帳戶,且該帳戶具備連線至本程式碼研究室一開始建立的 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}