我有一个实例组,已设置自动扩展和负载平衡。我还使用 Google Cloud SQL 作为 MySQL 服务器。
每当实例组扩展并添加另一个实例时,该实例都会获得一个新的 IP 地址。问题是这个实例不再有权访问 Google SQL 实例(因为 SQL 实例需要预先配置授权网络)。我该怎么办?
我目前通过将以下 IP 添加到 SQL 管理器中的授权 IP 来接受大多数 IP 到我的 SQL 服务器:
100.0.0.0/6 104.0.0.0/5 112.0.0.0/4
答案1
正如 @justbeez 提到的,我相信最好的方法是使用第二代实例,并且云端 SQL 代理。如果这不可能,可以设置第一代实例仅允许 SSL 连接并将任何来源列入白名单,如所述这里。
更复杂的方法是创建一个实例模板因此启动脚本在启动时运行并通过以下方式授权实例 IP 地址云端。可以用同样的方式删除 IP关闭时间。
可以从元数据服务器获取 GCE VM 的 IP 地址
curl "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip" -H "Metadata-Flavor: Google"
答案2
如果您使用的是第二代 Cloud SQL 实例,则可能需要考虑使用 Cloud SQL Proxy 连接方法: https://cloud.google.com/sql/docs/mysql-connect-proxy
简而言之,您可以在实例本地安装 Cloud SQL 代理,并通过服务帐户进行身份验证。然后,您可以像使用 UNIX 或 TCP 套接字连接一样连接到它。
这需要一些设置,但不需要任何 IP 白名单。配置完成后,您只需将该版本添加到您正在使用的任何自动扩展模板中。
注意:如果您碰巧使用 Docker 容器,它们有一个包装在 Docker 映像中的 Cloud SQL Proxy 版本,您可以将其作为服务添加到您的 pod 中: https://cloud.google.com/sql/docs/mysql-connect-docker
(我能想到的唯一其他选择是使用 API 来编辑白名单以响应自动缩放事件。)
答案3
好吧,我发帖不多,但这个问题浪费了我很多时间和精力。我希望这些信息能帮助面临同样问题的人:
使用 Cloud SQL Proxy 似乎是 GCP 推动每个人克服这一障碍的方法。但是,请记住,一旦您走上这条路,您就会与 GCP 紧密相连。您的应用程序必须直接了解 GCP 特定的组件才能与数据库通信——这仅在应用程序在 GCP 中运行时才有必要,在其他地方则无须这样做。
由于这种不良后果,我选择遵循@Carlos 的“更复杂”的方法。这种方法的优点是它隔离了与 SQL 实例通信所需的逻辑,并将其与 GCP 特定的配置(而不是应用程序本身)相关联。
以下代码是我编写的启动脚本,用于允许自动启动实例模板获得对 SQL 实例的授权。它在 GCP 的 Container-Optimized OS 中运行,该 OS 未安装 gcloud。
#!/bin/bash
PROJECT=<your project>
DB=<your db name>
METADATA=http://metadata.google.internal/computeMetadata/v1
# Get the external IP of this instance
EXTERNAL_IP=$(curl -s "$METADATA/instance/network-interfaces/0/access-configs/0/external-ip" -H "Metadata-Flavor: Google")
# Get access to call the SQL API
curl -s --header "Authorization: Bearer $ACCESS_TOKEN" -X GET https://www.googleapis.com/sql/v1beta4/projects/$PROJECT/instances/$DB?fields=settings/ipConfiguration/authorizedNetworks/value | grep value | awk -F\" '{print $4}' && \
SVC_ACCT=$METADATA/instance/service-accounts/default && \
ACCESS_TOKEN=$(curl -H 'Metadata-Flavor: Google' $SVC_ACCT/token | cut -d'"' -f 4)
# Get the IPs that are authorized to the database
EXISTING_IPS=$(curl -s --header "Authorization: Bearer $ACCESS_TOKEN" -X GET https://www.googleapis.com/sql/v1beta4/projects/$PROJECT/instances/$DB?fields=settings/ipConfiguration/authorizedNetworks/value | grep -B1 -A1 value | tr -d '\n')
# If the $EXTERNAL_IP is already authorized, then there's nothing to do
[ -n "$(echo $EXISTING_IPS | grep $EXTERNAL_IP)" ] && exit 0
# If the $EXISTING_IPS is not empty, prepend a comma
[ -n "$EXISTING_IPS" ] && EXISTING_IPS=", $EXISTING_IPS"
# Patch the database settings with the new authorized IPs
curl -s --header "Authorization: Bearer ${ACCESS_TOKEN}" \
--header 'Content-Type: application/json' \
--data "{\"settings\":{\"ipConfiguration\":{\"authorizedNetworks\":[{\"value\":\"$EXTERNAL_IP\"}$EXISTING_IPS]}}}" \
-X PATCH \
https://www.googleapis.com/sql/v1beta4/projects/$PROJECT/instances/$DB
# Dump the database settings for visual verification
curl -s --header "Authorization: Bearer $ACCESS_TOKEN" -X GET https://www.googleapis.com/sql/v1beta4/projects/$PROJECT/instances/$DB?fields=settings
更新:此解决方案可在我的公共 GitHub 仓库。