解决App Engine无法连接Cloud SQL(MySQL强制SSL)问题
2025-03-22 09:33:37
Google App Engine 无法直接连接强制 SSL 的 MySQL 实例?教你几招搞定!
碰上 Google App Engine 无法直接连接强制 SSL 的 MySQL 实例,是不是很头疼?别担心,这问题其实很常见。 你创建了一个启用了 SSL 的 MySQL 实例(版本 8.4),但 App Engine 应用连不上。 只有你在 Cloud Shell 里先用命令行连一次 MySQL,App Engine 才能连上。 一重启实例,又连不上了。 禁用 SSL 也没用,问题依旧。 接下来咱们就聊聊这是咋回事,以及该咋办。
一、 问题出在哪?
这问题通常是由几个原因导致的,咱们一个一个排查:
-
App Engine 连接方式: App Engine 连接 Cloud SQL (MySQL) 主要有两种方式:
- Cloud SQL Proxy: 这是推荐的方式。它通过一个安全的代理连接,简化了连接配置,并处理了身份验证。
- 直接通过 IP 地址连接: 需要你手动配置 MySQL 实例的网络授权,比较麻烦。
大多数时候,没法直接连上的原因是因为我们没有配置 Cloud SQL Proxy 或者配置有误.
-
授权问题: App Engine 应用的身份验证可能没有正确配置。Cloud SQL 依赖 Google Cloud IAM(Identity and Access Management)来管理访问权限。
-
MySQL 用户权限: 你的 MySQL 用户可能没有足够的权限来从 App Engine 服务账户访问数据库。
-
服务器CA证书问题: 在通过Cloud SQL Proxy 连接数据库,客户端需要校验服务器CA证书。App Engine 的运行环境如果证书配置存在问题,也会连接不上。
二、 搞定连接问题,看这几个方案!
1. 使用 Cloud SQL Proxy(推荐)
Cloud SQL Proxy 是首选! 它创建了一个安全的本地代理,你的 App Engine 应用可以通过这个代理连接到 Cloud SQL 实例,就像连接到本地 MySQL 服务器一样。
原理: Cloud SQL Proxy 处理了与 Cloud SQL 实例的加密连接和身份验证。 你的应用不需要处理 SSL 证书或复杂的网络配置。
操作步骤:
-
启用 Cloud SQL Admin API: 如果还没启用,先在 Google Cloud Console 里找到并启用它。
-
部署时添加 Cloud SQL Proxy: 在你的
app.yaml
文件中添加beta_settings
部分,并配置 Cloud SQL 连接:runtime: python39 # 根据你的实际运行环境修改 beta_settings: cloud_sql_instances: <YOUR_INSTANCE_CONNECTION_NAME>
YOUR_INSTANCE_CONNECTION_NAME
的格式为:project:region:instance
。 可以在 Cloud SQL 实例的概览页面找到。
-
连接字符串配置: 在你的应用程序代码中,使用标准的 MySQL 连接字符串连接到
127.0.0.1
(本地代理):import MySQLdb db = MySQLdb.connect( host="127.0.0.1", port=3306, user="your_mysql_user", passwd="your_mysql_password", db="your_database_name", ssl_mode = "VERIFY_IDENTITY", # 这很重要!确保开启了SSL并校验了身份。 ssl = { 'ca': '/etc/ssl/certs/ca-certificates.crt' # 指向系统信任的根证书文件,大部分情况下不用特别指定。 } ) # ... 执行 SQL 查询 ...
- 替换占位符为你自己的数据库用户、密码和数据库名。
- 确保你的 Python 程序安装了 PyMySQL 或 MySQLdb 等客户端. 可以用
pip install PyMySQL
命令安装
-
重新部署app engine 应用 .
进阶技巧
Cloud SQL Auth Proxy 可以进一步指定参数以满足不同环境需求. 可以在连接数据库的时候设定 ssl_mode
设定校验数据库服务器的规则:
-
DISABLED
:表示不通过安全连接方式来连接实例; -
ALLOW
:会优先尝试安全连接的方式连接实例; -
PREFER
:与ALLOW
模式很像,只是在连接失败后还会重试,但在默认情况下只使用此模式不一定是安全连接,仍然要依赖服务端的强制规定。 -
REQUIRE
:只有在安全连接的情况下才会成功连接实例。如果想要指定为这种模式则还要指定其它的配置,比如说 CA 证书; -
VERIFY_CA
:校验服务端的真实性, 要求配置sslca; -
VERIFY_IDENTITY
:最高等级校验规则, 在VERIFY_CA
基础上进一步要求配置sslcert
和sslkey
.
2. 通过 IP 地址连接(不推荐,但有时有用)
这种方法比较麻烦,也容易出错,但如果由于某些特殊原因你不能用 Cloud SQL Proxy,可以试试这个。
原理: 你需要直接配置 MySQL 实例的授权网络,允许 App Engine 服务的 IP 地址访问。
操作步骤:
- 查找 App Engine 的 IP 地址: 这个比较麻烦,App Engine 的 IP 地址不是固定的,你需要动态获取或者配置一个静态 IP 出口(但这会增加费用)。
- 获取数据库的证书:通过 Cloud SQL Proxy,首先你需要连接 Cloud SQL 实例并将服务器的 SSL 证书下载至您的机器或虚拟机. 随后可以通过mysql 客户端查看服务器的 ssl ca 证书
# 运行此命令的 Cloud Shell 或虚拟机中打开 shell。输入如下命令即可连接您的实例:
cloud_sql_proxy -instances=<YOUR_INSTANCE_CONNECTION_NAME>=tcp:3306 &
# 现在, 使用mysql客户端通过127.0.0.1(即 localhost)端口连接实例.
# 如果你在本地运行 Proxy,建议通过 Cloud SQL Auth Proxy(而非通过 IP 地址)在本地进行测试。
# 输入要连接的用户名。 例如:root;按 Enter 键。
# 根据提示,输入指定用户名的密码;然后按 Enter 键。
mysql -u <USERNAME> -p --host 127.0.0.1 --port 3306
#成功连接后, 使用命令来显示数据库服务器使用的证书详细信息:
mysql> SHOW STATUS LIKE 'Ssl_server_not_after';
mysql> SHOW STATUS LIKE 'Ssl_server_not_before';
#在mysql shell 中:\s 查看 SSL Cipher 信息:例如 SSL: Cipher in use is TLS_AES_256_GCM_SHA384
# 获取CA文件内容并写入一个新文件中(假设输出至一个server-ca.pem文件),
# 在linux环境下,你可以连接一个临时的mysql client 并运行以下mysql指令把CA文件直接输出至 server-ca.pem
mysql -u <USERNAME> -p --host 127.0.0.1 --port 3306 --ssl-mode=REQUIRED --execute="\s" | grep 'CA file' | awk -F: '{print $2}' | awk '{$1=$1;print}' > server-ca.pem
- 给用户授权通过主机连接
在MySQL 用户管理里,创建一个可以从任意主机通过SSL方式访问的新用户, 并且使用原生密码验证
CREATE USER 'appengine_user'@'%' IDENTIFIED WITH mysql_native_password BY 'your_password';
GRANT ALL PRIVILEGES ON your_database.* TO 'appengine_user'@'%';
FLUSH PRIVILEGES;
ALTER USER 'appengine_user'@'%' REQUIRE SSL;
这里注意必须指定`IDENTIFIED WITH mysql_native_password`, 这是因为 Google Cloud SQL 中MySQL 8 默认启用了`caching_sha2_password` 认证, App Engine 使用的连接客户端大概率并不支持此种加密方式.
-
数据库代码通过证书进行连接
import MySQLdb #替换 <INSTANCE_IP> 成数据库公网地址 db = MySQLdb.connect( host="<INSTANCE_IP>", port=3306, user="appengine_user", passwd="your_password", db="your_database_name", ssl_mode = "VERIFY_IDENTITY", # 开启SSL! ssl = { 'ca': './server-ca.pem' }# 填入下载的数据库证书! ) # ...
-
核查 IAM 权限(所有方案都需要)
不管你用哪种连接方式,都需要确保 App Engine 服务账户有正确的 IAM 权限。
原理: Google Cloud IAM 控制着谁可以访问哪些资源。你的 App Engine 服务账户需要 "Cloud SQL Client" 角色才能连接到 Cloud SQL 实例。
操作步骤:
- 找到你的 App Engine 服务账户: 在 Google Cloud Console 里找到 "IAM" 部分。 App Engine 的默认服务账户通常是
[PROJECT_ID]@appspot.gserviceaccount.com
。 - 添加 "Cloud SQL Client" 角色: 给你的服务账户添加这个角色。 如果这个账户已经有了 "Cloud SQL Admin" 角色,那就不用再添加了。
- 如果想精细化控制,还可以为服务账户添加数据库的特定用户访问权限
# 找到数据库的服务账号:
select * from mysql.general_log where argument like '%gserviceaccount.com%' limit 10;
# 把服务账号添加到数据库用户:
GRANT SELECT, INSERT, UPDATE, DELETE ON your_database.* TO 'your-appengine-service_account'@'cloudsqlproxy~%';
# 强制其通过SSL加密连接访问
ALTER USER 'your-appengine-service_account'@'cloudsqlproxy~%' REQUIRE SSL;
- 防火墙规则确认(适用使用公网ip连接方式) : 确保你的项目没有防火墙规则阻止了从 App Engine 到 Cloud SQL 的出站流量。如果采用的是专用IP进行数据库连接,你必须保证数据库设置了 Private Services Connect.
三, 小结
记住, 使用Cloud SQL Proxy 通常是最简单也最安全的,App Engine 和 Cloud SQL 都是 Google Cloud 的服务,它们之间的集成很顺畅。 上面这几招,希望至少有一招能解决你的问题。如果问题仍存在,请仔细查看每个操作步骤,核查是否有遗漏或配置错误. 重点检查授权与服务器 CA 证书这两项!