毎回しらべていてしんどいので。
参考資料 ここが一番わかりやすい https://codelabs.developers.google.com/connecting-to-private-cloudsql-from-cloud-run
用語の整理
"Private service access" を設定する一貫で、 "private service connection" をつくる。Google の docs だと "private connection" といってることもあるけど、こっちは「パブリックでない接続」という意味の一般用語ぽい。
つくるもの
注: ここでは default
の VPC を使うよ。要件的に微妙な場合は別途 google_compute_network
と google_compute_subnetwork
を作ってね。
注: CLI のコマンドは Code Labs からコピペ、 terraform はわたしが書いたコード
つくるものはこういうイメージ↓
services
これらのサービスが有効になっている必要がある
gcloud services enable \ sqladmin.googleapis.com \ run.googleapis.com \ vpcaccess.googleapis.com \ servicenetworking.googleapis.com
VPC peering 用の IP address
gcloud compute addresses create google-managed-services-default \ --global \ --purpose=VPC_PEERING \ --prefix-length=20 \ --network=projects/$PROJECT_ID/global/networks/default
resource "google_compute_global_address" "google_managed_services_default" { name = "google-managed-services-default" purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 20 network = data.google_compute_network.default.id }
private connection
gcloud services vpc-peerings connect - connect to a service via VPC peering for a project network
ref: https://cloud.google.com/sdk/gcloud/reference/services/vpc-peerings/connect
gcloud services vpc-peerings connect \ --service=servicenetworking.googleapis.com \ --ranges=google-managed-services-default \ --network=default \ --project=$PROJECT_ID
# CLI だと名前を指定していないけど、ここでは設定している resource "google_service_networking_connection" "private_service_access_connector_default" { network = data.google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.google_managed_services_default.name] }
Cloud SQL instance, db, user
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} # db gcloud sql databases create $DB_DATABASE --instance=$DB_INSTANCE_NAME # user gcloud sql users create ${DB_USER} \ --password=$DB_PASSWORD \ --instance=$DB_INSTANCE_NAME
resource "google_sql_database_instance" "main" { name = "main" region = var.region database_version = "POSTGRES_16" settings { tier = "db-f1-micro" edition = "ENTERPRISE" availability_type = "ZONAL" ip_configuration { ipv4_enabled = false private_network = var.network_default_id enable_private_path_for_google_cloud_services = true } backup_configuration { enabled = true point_in_time_recovery_enabled = true } } # terraform だと private service connection が先に存在する必要がある depends_on = [var.private_service_access_connector_default_id] } resource "google_sql_database" "main_db" { name = var.db_database_name instance = google_sql_database_instance.main.name } resource "google_sql_user" "main_user" { name = var.db_username instance = google_sql_database_instance.main.name password = var.db_password }
Serverless VPC Access connector
紛らわしいのが、 private service connection とは別に Cloud Run にもコネクターが必要になる。というのも、 Cloud Run はサーバレスなやつなので、 VPC の概念がない。
gcloud compute networks vpc-access connectors - manage Serverless VPC Access Service connectors
https://cloud.google.com/sdk/gcloud/reference/compute/networks/vpc-access/connectors
gcloud compute networks vpc-access connectors create ${SERVERLESS_VPC_CONNECTOR} \ --region=${REGION} \ --range=10.8.0.0/28
resource "google_vpc_access_connector" "serverless_default" { name = "serverless-conn-default" network = data.google_compute_network.default.id ip_cidr_range = "10.8.0.0/28" region = var.region }
Cloud Run
直前でつくった serverless VPC access service connector を割り当てて Cloud Run を deploy する
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
(自分は gcloud コマンドでデプロイするので Terraform は省略)
tips
IP アドレスの数の考慮
IP アドレスの数が足りなくなったら、
- CIDR block を expand するか、
- 新しい IP address range を allocate
のどちらかができる。ただし、 allocation の数には quota があるので、 expand したほうがよさそう。
Select a CIDR block that is large enough to meet your current and future needs. If you later find that the range isn't sufficient in size, expand the range if possible. Although you can assign multiple allocations to a single service producer, Google enforces a quota on the number of IP address ranges that you can allocate but not the size (netmask) of each range.
https://cloud.google.com/vpc/docs/configure-private-services-access#considerations
allocation (= IP address range) の名前
自分で private service connection を作るとき (i.e. terraform とか CLI とか) google-managed-services-[your network name]
という形式にしておくとよい。この名前は Google が自動で作る名前なのにで、新しい接続をコンソールからつくるときとかに、Google 側に「もう接続があるよ」とつたえられて新しいリソースが作られるのを防ぐ。IP アドレスって結構高いからやった方が良いと思う。
If you create the allocation yourself instead of having Google do it (such as through Cloud SQL), you can use the same naming convention to signal to other users or Google services that an allocation for Google already exists. When a Google service allocates a range on your behalf, the service uses the following format to name the allocation: google-managed-services-[your network name]. If this allocation exists, Google services use the existing one instead of creating another one.
https://cloud.google.com/vpc/docs/configure-private-services-access#considerations
Cloud SQL の private IP address を変えるとき
... は、なんか考慮が必要っぽい。詳しくはここ: https://cloud.google.com/sql/docs/mysql/configure-private-services-access#change-private-ip
Private service access で複数のリソースがある場合
たとえば、同じ VPC に複数の Cloud SQL があってそれらに Private service access を設定する必要があるとき、 Private service access は1つでよい...というのが明示的に書いてある。
If a single service producer offers multiple services, you only need one private connection for all of the producer's services.
https://cloud.google.com/vpc/docs/configure-private-services-access#creating-connection
もしどの Cloud SQL がどの connection を使うかを指定したいときは、VPC network を複数立ててね、とも書いてある。
If a single service producer offers multiple services and you want to control which allocated ranges are used for different service resources, you can use multiple VPC networks each with their own private connections.
google-managed-services-[network name]
となっているもの上記の説明で納得できる。
解説的な
そもそもなんで private service access を設定する必要があるかというと、Cloud SQL を VPC 内に置くためには、「自分の VPC」と、「Google 側の VPC」をつなげる必要がある。結局「自分の VPC」も Google 側のリソースだからわざわざ分ける必要は何? って思ったけど、Cloud SQL がマネージドサービスなのとか責任範囲とかが関わってくるっぽい。
ちなみに、説明としてはこうあったので
The private connection enables VM instances in your VPC network and the services that you access to communicate exclusively by using internal IP addresses.
自分のプロジェクトだと VM 使わないからいらないか〜と思って、private connection を作らずに private IP つきの Cloud SQL を作ったらふつうにエラーになった。