從 Cloud Run 連線至 Private CloudSQL

1. 總覽

在本研究室中,您將建立 Cymbal Eats 選單服務,公開符合 REST 樣式的 API 來新增、更新、刪除及列出選單項目。您將建立 Cloud SQL 資料庫做為選單服務的後端資料庫,並在 Cloud Run 中執行。由於 Cloud Run 與 Cloud SQL 資料庫並非位於相同的虛擬私有雲,因此您必須設定無伺服器虛擬私有雲存取連接器,讓 Cloud Run 透過私人 IP 位址與 Cloud SQL 通訊。

19c7b05f35789fda.png

學習目標

在本研究室中,您將瞭解如何執行下列操作:

  • 設定私人虛擬私有雲網路
  • 建立 Private Postgres Cloud SQL 資料庫
  • 將 CloudRun 連線至私人虛擬私有雲
  • 在 Cloud Run 上部署服務,連結至 Cloud SQL 資料庫

2. 設定和需求

自修環境設定

  1. 登入 Google Cloud 控制台,建立新專案或重複使用現有專案。如果您還沒有 Gmail 或 Google Workspace 帳戶,請先建立帳戶

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • 「專案名稱」是這項專案參與者的顯示名稱。這是 Google API 未使用的字元字串。您可以隨時更新。
  • 所有 Google Cloud 專案的專案 ID 均不得重複,而且設定後即無法變更。Cloud 控制台會自動產生一個不重複的字串。但通常是在乎它何在在大部分的程式碼研究室中,您必須參照專案 ID (通常為 PROJECT_ID)。如果您對產生的 ID 不滿意,可以隨機產生一個 ID。此外,您也可以自行嘗試,看看系統是否提供該付款方式。在完成這個步驟後就無法變更,而且在專案期間仍會保持有效。
  • 資訊中的第三個值是專案編號,部分 API 會使用這個編號。如要進一步瞭解這三個值,請參閱說明文件
  1. 接下來,您需要在 Cloud 控制台中啟用計費功能,才能使用 Cloud 資源/API。執行這個程式碼研究室並不會產生任何費用,如果有的話。如要關閉資源,以免系統產生本教學課程結束後產生的費用,您可以刪除自己建立的資源,或刪除整個專案。Google Cloud 的新使用者符合 $300 美元免費試用計畫的資格。

環境設定

  1. 建立專案和資源相關環境變數
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
export PROJECT_NAME=$(gcloud projects describe $PROJECT_ID --format='value(name)')
export REGION=us-east1
export MENU_SERVICE_NAME=menu-service

export SERVERLESS_VPC_CONNECTOR=cymbalconnector
export DB_INSTANCE_NAME=menu-catalog
export DB_INSTANCE_PASSWORD=password123
export DB_DATABASE=menu-db
export DB_USER=menu-user
export DB_PASSWORD=menupassword123
  1. 複製存放區並前往目錄
git clone https://github.com/GoogleCloudPlatform/cymbal-eats.git && cd cymbal-eats/menu-service
  1. 啟用服務
gcloud services enable \
    sqladmin.googleapis.com \
    run.googleapis.com \
    vpcaccess.googleapis.com \
    servicenetworking.googleapis.com

3. 設定私人存取權

私人服務存取權會以虛擬私有雲對等互連連結的形式,在虛擬私有雲網路與 Cloud SQL 執行個體所在的基礎 Google Cloud 虛擬私有雲網路之間進行對等互連。私人連線會允許虛擬私有雲網路中的 VM 執行個體,以及您使用的服務,只透過內部 IP 位址進行通訊。如要存取透過私人服務存取權使用的服務,VM 執行個體不需要網際網路連線或外部 IP 位址。

  1. 分配 IP 位址範圍
gcloud compute addresses create google-managed-services-default \
    --global \
    --purpose=VPC_PEERING \
    --prefix-length=20 \
    --network=projects/$PROJECT_ID/global/networks/default

輸出範例

Created [https://www.googleapis.com/compute/v1/projects/cymbal-eats-2-348215/global/addresses/google-managed-services-default].
  1. 建立私人連線。
gcloud services vpc-peerings connect \
    --service=servicenetworking.googleapis.com \
    --ranges=google-managed-services-default \
    --network=default \
    --project=$PROJECT_ID

輸出範例

Operation "operations/pssn.p24-528514492617-2f2b507f-e4e5-4d53-a4de-9ddaceb4e92f" finished successfully.

4. 設定 Cloud SQL

Cloud SQL 是全代管資料庫服務,可協助您輕鬆設定、維護及管理雲端中的 PostgreSQL 和 MySQL 關聯資料庫。每個 Cloud SQL 執行個體都是由在 Google Cloud 主機伺服器上運作的虛擬機器 (VM) 提供技術支援。高可用性選項還包含在設定與主要 VM 相同的另一個可用區中的待命 VM。資料庫存放在連線至 VM 的可擴充網路儲存裝置 (稱為「永久磁碟」)。系統會為每個 VM 指派一個靜態 IP 位址,確保在 Cloud SQL 執行個體的生命週期內,應用程式連線的 IP 位址不會保持不變。

219cb722c2dd1b82.png

您將建立使用私人 IP 位址的 Postgres Cloud SQL 資料庫。

建立資料庫和使用者

  1. 建立 Postgres Cloud SQL 執行個體以使用私人 IP
gcloud sql instances create $DB_INSTANCE_NAME \
    --project=$PROJECT_ID \
    --network=projects/$PROJECT_ID/global/networks/default \
    --no-assign-ip \
    --database-version=POSTGRES_12 \
    --cpu=2 \
    --memory=4GB \
    --region=$REGION \
    --root-password=${DB_INSTANCE_PASSWORD}

輸出範例

Created [https://sqladmin.googleapis.com/sql/v1beta4/projects/cymbal1/instances/menu-instance].
NAME: menu-instance
DATABASE_VERSION: POSTGRES_12
LOCATION: us-east1-a
TIER: db-custom-2-4096
PRIMARY_ADDRESS: -
PRIVATE_ADDRESS: 10.8.80.5
STATUS: RUNNABLE
  1. 將資料庫新增至資料庫執行個體
gcloud sql databases create $DB_DATABASE --instance=$DB_INSTANCE_NAME

輸出範例

Created database [menu-db].
instance: menu-catalog
name: menu-db
project: cymbal1
  1. 建立 SQL 使用者
gcloud sql users create ${DB_USER} \
    --password=$DB_PASSWORD \
    --instance=$DB_INSTANCE_NAME

輸出範例

Created user [menu-user].
  1. 儲存資料庫 IP 位址
export DB_INSTANCE_IP=$(gcloud sql instances describe $DB_INSTANCE_NAME \
    --format=json | jq \
    --raw-output ".ipAddresses[].ipAddress")
  1. 將 Cloud SQL 用戶端角色新增至 Compute Engine 服務帳戶
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com" \
--role="roles/cloudsql.client"

輸出範例

Updated IAM policy for project [cymbal1].
[...]

5. 無伺服器虛擬私有雲

無伺服器虛擬私有雲存取功能可讓您從 Cloud Run、App Engine 或 Cloud Functions 等無伺服器環境直接連線至虛擬私有雲網路。設定無伺服器虛擬私有雲存取功能之後,無伺服器環境就能使用內部 DNS 和內部 IP 位址 (根據 RFC 1918 和 RFC 6598 定義) 將要求傳送至虛擬私有雲網路。這些要求的回應也會使用您的內部網路。

您將建立無伺服器虛擬私有雲存取連接器,讓 Cloud Run 服務連線至 Cloud SQL。

19c7b05f35789fda.png

  1. 在 Cloud SQL 執行個體所在的虛擬私有雲網路,建立無伺服器虛擬私有雲存取連接器。
gcloud compute networks vpc-access connectors create ${SERVERLESS_VPC_CONNECTOR} \
    --region=${REGION} \
    --range=10.8.0.0/28

輸出範例

Created connector [cymbalconnector].

6. 部署至 Cloud Run

您將建構 Docker 映像檔並部署至 Cloud Run,並且將 Cloud Run 連線至無伺服器虛擬私有雲連接器,以便存取 Cloud SQL 資料庫。

  1. 使用 maven 編譯應用程式
./mvnw package -DskipTests

輸出範例

[...]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  42.864 s
[INFO] Finished at: 2022-04-28T16:15:33Z
[INFO] ------------------------------------------------------------------------
  1. 建構 Docker 映像檔:
docker build -f src/main/docker/Dockerfile.jvm \
    --tag gcr.io/$PROJECT_NAME/menu-service .

輸出範例

[...]
Successfully built 4ef5d7a3befc
Successfully tagged gcr.io/cymbal1/menu-service:latest
  1. 將 Docker 映像檔推送至 Container Registry:
docker push gcr.io/$PROJECT_NAME/menu-service

輸出範例

Using default tag: latest
The push refers to repository [gcr.io/cymbalsql/menu-service]
17b374963800: Pushed
d9a51c06430d: Pushed
fff5d2a2cfc9: Pushed
f21fceb558c6: Pushed
5ffbbbf218dd: Pushed
60609ec85f86: Layer already exists
f2c4302f03b8: Layer already exists
latest: digest: sha256:f64cb7c288dbf4ad9b12bd210c23c5aec1048dee040450ff2d9dbdf96e83a426 size: 1789
  1. 部署選單服務:
gcloud run deploy $MENU_SERVICE_NAME \
    --image=gcr.io/$PROJECT_NAME/menu-service:latest \
    --region $REGION \
    --allow-unauthenticated \
    --set-env-vars DB_USER=$DB_USER \
    --set-env-vars DB_PASS=$DB_PASSWORD \
    --set-env-vars DB_DATABASE=$DB_DATABASE \
    --set-env-vars DB_HOST=$DB_INSTANCE_IP \
    --vpc-connector $SERVERLESS_VPC_CONNECTOR \
    --project=$PROJECT_ID \
    --quiet

輸出範例

[...]
Done.
Service [menu-service] revision [menu-service-00002-xox] has been deployed and is serving 100 percent of traffic.
Service URL: https://menu-service-g2mfphytdq-uk.a.run.app

Google 建議您使用 Secret Manager 來儲存 SQL 憑證等機密資訊。您可以透過 Cloud Run 將密鑰做為環境變數傳遞或掛接為磁碟區

  1. 商店菜單服務網址:
MENU_SERVICE_URL=$(gcloud run services describe menu-service \
  --platform managed \
  --region $REGION \
  --format=json | jq \
  --raw-output ".status.url")
  1. 驗證菜單服務網址
echo $MENU_SERVICE_URL

輸出範例

https://menu-service-g2mfphytdq-uk.a.run.app

7. 測試服務

  1. 傳送 POST 要求以建立新的選單項目:
curl -X POST "${MENU_SERVICE_URL}/menu" \
  -H 'Content-Type: application/json' \
  -d '{
       "itemImageURL": "https://images.unsplash.com/photo-1631452180519-c014fe946bc7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1587&q=80",
       "itemName": "Curry Plate",
       "itemPrice": 12.5,
       "itemThumbnailURL": "https://images.unsplash.com/photo-1631452180519-c014fe946bc7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1587&q=80",
       "spiceLevel": 3,
       "status": "Ready",
       "tagLine": "Spicy touch for your taste buds!!"
   }'

輸出範例

{
    "id": 16,
    "createDateTime": "2022-04-28T18:14:04.17225",
    "itemImageURL": "https://images.unsplash.com/photo-1631452180519-c014fe946bc7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1587&q=80",
    "itemName": "Curry Plate",
    "itemPrice": 12.5,
    "itemThumbnailURL": "https://images.unsplash.com/photo-1631452180519-c014fe946bc7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1587&q=80",
    "spiceLevel": 3,
    "status": "Processing",
    "tagLine": "Spicy touch for your taste buds!!",
    "updateDateTime": "2022-04-28T18:14:04.172298"
}
  1. 傳送 PUT 要求,變更選單項目的狀態:
curl -X PUT "${MENU_SERVICE_URL}/menu/1" \
  -H 'Content-Type: application/json' \
  -d '{"status": "Ready"}'

輸出範例

{
    "id": 1,
    "createDateTime": "2022-04-28T17:21:02.369093",
    "itemImageURL": "https://images.unsplash.com/photo-1631452180519-c014fe946bc7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1587&q=80",
    "itemName": "Curry Plate",
    "itemPrice": 12.50,
    "itemThumbnailURL": "https://images.unsplash.com/photo-1631452180519-c014fe946bc7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1587&q=80",
    "spiceLevel": 0,
    "status": "Ready",
    "tagLine": "Spicy touch for your taste buds!!",
    "updateDateTime": "2022-04-28T17:21:02.657636"
}

8. 恭喜!

恭喜,您已完成程式碼研究室!

下一步:

探索其他 Cymbal Eats 程式碼研究室:

清除所用資源

如要避免系統向您的 Google Cloud 帳戶收取本教學課程所用資源的費用,請刪除含有相關資源的專案,或者保留專案但刪除個別資源。

刪除專案

如要避免付費,最簡單的方法就是刪除您針對教學課程建立的專案。