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

时间:2018-09-13 09:46:25

标签: python google-app-engine google-cloud-platform google-cloud-sql google-app-engine-python

我的目标是在GCP上运行一个可用的Python 2.7项目(MySQL + MS Word文件)。 我意识到我需要

  1. App Engine-应用将在其中运行(缩放等)。
  2. 用作MySQL数据库的Cloud SQL。 为此,我遵循了Cloud SQL for MySQL tut
    • Cloud SQL实例是由root用户创建的。
    • App Engine应用程序和Cloud SQL实例都在同一个项目中。
  3. 云存储

成功创建了第二代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")')

Cloud SQL代理

我已经下载并运行Win-64的Cloud Proxy(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应用:我们中心

这些是一个地区吗?-原来是一个地区的这些景点

更新4

我本来可以打开数据库连接的:

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

但是,这似乎只有在我用同一项目( coral-heuristic-215610 )打开了另一个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:

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

2 个答案:

答案 0 :(得分:1)

我通过将以下内容添加到app.yaml中来解决了连接拒绝问题:

beta_settings:
    cloud_sql_instances: "<CONNECTION_NAME>"

答案 1 :(得分:0)

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

我无法理解您要从哪里连接。我假设您想使用代理和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测试连接。