标准环境下的 GCP:MySQL 数据库连接被拒绝

Posted

技术标签:

【中文标题】标准环境下的 GCP:MySQL 数据库连接被拒绝【英文标题】:GCP at the standard environment: MySQL db connection refused 【发布时间】:2019-02-18 00:44:16 【问题描述】:

我的目标是让 Python 2.7 项目(mysql + MS Word 文件)在 GCP 工作。 我意识到我需要

    App Engine - 应用运行的位置(缩放等)。 Cloud SQL 作为 MySQL 数据库工作。 为此,我遵循了Cloud SQL for MySQL tut 和 Cloud SQL 实例是使用root 用户创建的。 App Engine 应用和 Cloud SQL 实例都在同一个项目中。 云存储

SQL第二代实例创建成功并设置了root用户。

我如何运行或部署

我使用 Cloud Shell 测试应用程序 - dev_appserver.py $PWD 并从 Cloud Shell 部署应用程序 - gcloud app deploy。 It works at appspot.com 直到我尝试在其中使用 MySQL 连接。

MySQL 连接

MySQL连接代码取自here:

import MySQLdb
import webapp2    

CLOUDSQL_CONNECTION_NAME = os.environ.get('CLOUDSQL_CONNECTION_NAME')
CLOUDSQL_USER = os.environ.get('CLOUDSQL_USER')
CLOUDSQL_PASSWORD = os.environ.get('CLOUDSQL_PASSWORD')    
DB_NAME='test-db'
def connect_to_cloudsql():
    # When deployed to App Engine, the `SERVER_SOFTWARE` environment variable
    # will be set to 'Google App Engine/version'.
    if os.getenv('SERVER_SOFTWARE', '').startswith('Google App Engine/'):
        # Connect using the unix socket located at
        # /cloudsql/cloudsql-connection-name.
        cloudsql_unix_socket = os.path.join(
            '/cloudsql', CLOUDSQL_CONNECTION_NAME)

        db = MySQLdb.connect(
            unix_socket=cloudsql_unix_socket,
            user=CLOUDSQL_USER,
            passwd=CLOUDSQL_PASSWORD)

    # If the unix socket is unavailable, then try to connect using TCP. This
    # will work if you're running a local MySQL server or using the Cloud SQL
    # proxy, for example:
    #
    #   $ cloud_sql_proxy -instances=your-connection-name=tcp:3306
    #
    else:
        db = MySQLdb.connect(
            host='127.0.0.1', user=CLOUDSQL_USER, passwd=CLOUDSQL_PASSWORD, db=DB_NAME)

    return db
db = connect_to_cloudsql()

变量在app.yaml中设置:

runtime: python27
api_version: 1
threadsafe: true
env_variables:
    CLOUDSQL_CONNECTION_NAME: coral-heuristic-215610:us-central1:db-basic-1
    CLOUDSQL_USER: root
    CLOUDSQL_PASSWORD: xxxxx

当应用程序通过dev_appserver.py $PWD 在测试模式下运行并且我选择使用 MySQL 连接时出现错误:

ERROR    2018-09-13 08:37:42,492 wsgi.py:263]
Traceback (most recent call last):
  ...
  File "/home/.../mysqldb.py", line 35, in connect_to_cloudsql
    host='127.0.0.1', user=CLOUDSQL_USER, passwd=CLOUDSQL_PASSWORD)
  File "/usr/lib/python2.7/dist-packages/MySQLdb/__init__.py", line 81, in Connect
    return Connection(*args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/MySQLdb/connections.py", line 204, in __init__
    super(Connection, self).__init__(*args, **kwargs2)
OperationalError: (2003, 'Can\'t connect to MySQL server on \'127.0.0.1\' (111 "Connection refused")')

云 SQL 代理

我已经下载并运行了适用于 Win-64 的云代理 (https://dl.google.com/cloudsql/cloud_sql_proxy_x64.exe),但问题仍然存在......似乎代理后台应用程序仅用于从我的本地计算机连接到 Cloud SQL。

您无需使用代理或配置 SSL 即可从 App Engine 标准或柔性环境连接到 Cloud SQL。 (source)

为什么连接被拒绝?

我应该使用第一代 Cloud sql 实例来简化与 App Engine 的连接吗?

更新 1

我在 Cloud Console 上编辑代码,目前 Cloud Console 运行良好。

更新 2

我已成功通过 Cloud Shell 连接到 sql 实例:

(coral-heuristic-215610)$ gcloud sql connect db-basic-1 --user=root

Whitelisting your IP for incoming connection for 5 minutes...done.
Connecting to database with SQL user [root].Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 48841
Server version: 5.7.14-google-log (Google)
MySQL [(none)]>

更新 3

comment on a similar issue 涉及 Cloud SQL 实例App Engine 应用 应该位于的区域,即在同一区域

在我的情况下,我已经检查过:

要连接的 Cloud SQL 实例:us-central1-a App Engine 应用:us-central

这些是一个地区的吗? - 结果是这些是一个地区的

更新 4

我本可以想办法打开数据库连接:

DB connection: <_mysql.connection open to '127.0.0.1' at 7f628c02bc00>

但这似乎只有在我打开另一个具有相同项目的 Cloud Shell 实例后才会发生 (coral-heuristic-215610)。在那个实例中,我已经开始连接到 SQL 实例并且它是成功的:

(coral-heuristic-215610)$ gcloud sql connect db-basic-1 --user=root

Whitelisting your IP for incoming connection for 5 minutes...done.
Connecting to database with SQL user [root].Enter password:

我猜第一个 cloud shell 实例开始连接 db 是因为 第二个实例已将我的 IP 列入白名单,不是吗?

【问题讨论】:

你能显示你实际调用数据库的代码吗? @LundinCast,我不调用 db cursor 因为没有建立连接。最后一件事现在在代码中:db = connect_to_cloudsql()。稍后我会添加cursor = db.cursor() cursor.execute(...) 关于您的第三次更新,这些都在同一个地区,是的。关于您在部署的应用程序中遇到的错误,当您转到 Dev Console > Logging 并选择您的应用程序引擎的服务时,您是否可以在日志中看到任何错误消息? @LundinCast ,在我发现的日志中:logMessage: "Traceback (most recent call last): ... File "/base/alloc/tmpfs/dynamic_runtimes/python27g/573c2cae20d3e94a/python27/python27_lib/versions/1/google/appengine/runtime/wsgi.py", line 302, in _LoadHandler raise err ImportError: <module 'mysqldb' from '/base/data/home/apps/s~coral-heuristic-215610/20180913t150025.412542355798183973/mysqldb.py'> has no attribute app" severity: "ERROR" @LundinCast,它是什么:module 'mysqldb' has no attribute app?注意,在 app.yaml 我使用 - url: /main script: main.app - url: /mysql script: mysqldb.app 【参考方案1】:

GAE 应用和 Google Cloud SQL 实例必须部署在同一区域if you’re using MySQL First Generation,否则,我验证它们可以在不同区域,只要您使用的是 MySQL 第二代。

我无法理解您尝试从哪里连接。我假设您想使用代理和Cloud SDK Credentials 从 Google Cloud Shell 进行连接。根据有关Cloud SQL Proxy的文档:

Cloud SQL 代理提供对 Cloud SQL Second 的安全访问 无需将 IP 地址列入白名单或 配置 SSL。

Cloud SQL 代理通过一个本地客户端(称为代理)来工作, 在本地环境中运行。您的应用程序与 具有数据库使用的标准数据库协议的代理。 代理使用安全隧道与其伙伴进行通信 服务器上运行的进程。

请记住,由于您没有部署应用程序,因此它没有使用您在 app.yaml 中建立的环境变量。因此,您必须在本地机器中自己导出并设置它们:

export CLOUDSQL_CONNECTION_NAME=your-connection-name
export CLOUDSQL_USER=root
export CLOUDSQL_PASSWORD=xxxxx

通过例如echo $CLOUDSQL_CONNECTION_NAME 来验证它们是否已设置。当您使用gcloud app deploy 部署您的应用程序时,这不是必需的,因为 GAE 会设置 app.yaml 中指定的任何环境变量。

代理必须在尝试按照these 步骤建立连接之前启动:

下载代理:

wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 -O cloud_sql_proxy

给它执行权限:

chmod +x cloud_sql_proxy

启动代理,将 <INSTANCE_CONNECTION_NAME> 替换为您的 Cloud SQL 实例连接名称:

./cloud_sql_proxy -instances=<INSTANCE_CONNECTION_NAME>=tcp:3306

你应该在最后看到类似这样的内容:

 2018/11/09 13:24:32 Rlimits for file descriptors set to &8500 1048576 
 2018/11/09 13:24:35 Listening on 127.0.0.1:3306 for my-project:cloud-sql-region:cloud-sql-name 
 2018/11/09 13:24:35 Ready for new connections

此时,您可以从 Google Cloud Shell instance 连接到本地运行的代理,这反过来会将您连接到 Cloud SQL 实例。

打开另一个Cloud Shell session(或选项卡)并使用python myapp.py 启动您的代码。您将连接到本地运行的代理。您也可以通过运行mysql -h 127.0.0.1 --user=root -p 来测试连接。

【讨论】:

【参考方案2】:

我通过在 app.yaml 中添加以下内容解决了连接被拒绝的问题:

beta_settings:
    cloud_sql_instances: "<CONNECTION_NAME>"

【讨论】:

以上是关于标准环境下的 GCP:MySQL 数据库连接被拒绝的主要内容,如果未能解决你的问题,请参考以下文章

创建 GCP 服务帐户密钥时权限被拒绝

权限被拒绝 - GCP 云资源管理器 setIamPolicy

调用 GCP App 引擎 REST API 时权限被拒绝

Mysql 数据库连接被拒绝

MySql连接被拒绝-Java [重复]

带有 MySQL 连接器的 C# - 访问被拒绝