【问题标题】:Not able to connect app engine to cloud sql for mysql instance无法将应用引擎连接到 mysql 实例的云 sql
【发布时间】:2020-05-18 10:04:44
【问题描述】:

sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'localhost' ([Errno 2] No such file or directory)") (这个错误的背景在:http://sqlalche.me/e/e3q8)

我被这个错误困扰了很长时间,我正在尝试将我的应用程序引擎 python 代码连接到 mysql 实例的云 sql。这是我第一次使用谷歌云。下面是我写的代码 1.在app.yaml中

runtime:
    python37
vpc_access_connector:
    name: "projects/projectnameandcode/locations/location name/connectors/connector name"

2.requirements.txt

sqlalchemy
pymysql
  1. 在 main.py 中

    导入 pymysql

    db = sqlalchemy.create_engine(

    sqlalchemy.engine.url.URL(
        drivername="mysql+pymysql",
        username="username",
        password=password,
        database="databasename",
        query={"unix_socket": "/cloudsql/{}".format("instance name")},
    ),
    

    ) a= db.connect()

为什么我会遇到这个问题?我的 Iam 角色是所有者或管理员。

【问题讨论】:

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


    【解决方案1】:

    App Engine 标准环境不支持连接到云端 使用 TCP 的 SQL 实例。您的代码不应尝试访问 实例使用 IP 地址(例如 127.0.0.1 或 172.17.0.1),除非 您已配置无服务器 VPC 访问。

    根据您的问题,我了解到您正在使用vpc_access_connector。因此,我假设您配置了 Serverless VPC Access。

    main.py 中使用的代码用于使用 unix 域套接字而不是 TCP 连接到 Cloud SQL 实例。

    编辑:

    使用 TCP 和 UNIX 域套接字从应用程序引擎连接到云 SQL

    1.新建项目

    gcloud projects create con-ae-to-sql
    gcloud config set project con-ae-to-sql
    gcloud projects describe con-ae-to-sql
    

    2.为您的项目启用计费:https://cloud.google.com/billing/docs/how-to/modify-project

    3.运行以下 gcloud 命令以启用 App Engine 并创建关联的应用程序资源

    gcloud app create -region europe-west2
    gcloud app describe
    #Remember the location of you App Engine aplication, because we will create all our resources on the same region
    

    4.设置计算项目信息元数据:

     gcloud compute project-info describe --project con-ae-to-sql
     #Enable the Api, and you can check that default-region,google-compute-default-zone are not set. Set the metadata.
     gcloud compute project-info add-metadata --metadata google-compute-default-region=europe-west2,google-compute-default-zone=europe-west2-b
    

    5.启用服务网络API:

    gcloud services list --available
    gcloud services enable servicenetworking.googleapis.com
    

    6.创建2个云sql实例,(一个带有内部ip,一个带有公共ip)-https://cloud.google.com/sql/docs/mysql/create-instance

    6.具有外部ip的Cloud Sql实例:

    #Create the sql instance in the same region as App Engine Application
    gcloud --project=con-ae-to-sql beta sql instances create database-external --region=europe-west2
    #Set the password for the "root@%" MySQL user:
    gcloud sql users set-password root --host=% --instance database-external --password root 
    #Create a user
    gcloud sql users create user_name --host=% --instance=database-external  --password=user_password
    #Create a database
    gcloud sql databases create user_database --instance=database-external
    gcloud sql databases list --instance=database-external
    

    6.b 内部ip的云Sql实例:

    i.#Create a private connection to Google so that the VM instances in the default VPC network can use private services access to reach Google services that support it.
    
    gcloud compute addresses create google-managed-services-my-network     --global  --purpose=VPC_PEERING --prefix-length=16  --description="peering range for Google"  --network=default --project=con-ae-to-sql
    gcloud services vpc-peerings connect --service=servicenetworking.googleapis.com --ranges=google-managed-services-my-network  --network=default  --project=con-ae-to-sql
    #Check whether the operation was successful.
    gcloud services vpc-peerings operations describe     --name=operations/pssn.dacc3510-ebc6-40bd-a07b-8c79c1f4fa9a
    #Listing private connections
    gcloud services vpc-peerings list --network=default --project=con-ae-to-sql
     
    ii.Create the instance:
    
    gcloud --project=con-ae-to-sql beta sql instances create database-ipinternal --network=default --no-assign-ip  --region=europe-west2
    #Set the password for the "root@%" MySQL user:
    gcloud sql users set-password root --host=% --instance database-ipinternal --password root
    #Create a user
    gcloud sql users create user_name --host=% --instance=database-ipinternal  --password=user_password
    #Create a database
    gcloud sql databases create user_database --instance=database-ipinternal
    gcloud sql databases list --instance=database-ipinternal 
    
    
    gcloud sql instances list
    gcloud sql instances describe database-external
    gcloud sql instances describe database-ipinternal
    #Remember the instances connectionName
    

    好的,所以我们有两个 mysql 实例,我们将使用 Serverless Access 和 TCP 从 App Engine Standard 连接到 database-ipinternal,使用 unix domain socket 从 App Engine Standard 连接到 database-external,从 App Engine Flex 连接到 database-ipinternal使用 TCP,并使用 unix 域套接字从 App Engine Flex 到数据库外部。

    7.启用 Cloud SQL Admin API

    gcloud services list --available
    gcloud services enable sqladmin.googleapis.com
    

    8.目前 App Engine 标准环境不支持使用 TCP 连接到 Cloud SQL 实例。除非您已配置无服务器 VPC 访问,否则您的代码不应尝试使用 IP 地址(例如 127.0.0.1 或 172.17.0.1)访问实例。所以让我们配置无服务器 VPC 访问。

    8.a 确保为您的项目启用无服务器 VPC 访问 API:

    gcloud services enable vpcaccess.googleapis.com
    

    8.b 创建连接器:

    gcloud compute networks vpc-access connectors create serverless-connector --network default --region europe-west2 --range 10.10.0.0/28
    #Verify that your connector is in the READY state before using it
    gcloud compute networks vpc-access connectors describe serverless-connector --region europe-west2
    

    9.App Engine 使用服务帐号来授权您与 Cloud SQL 的连接。此服务帐户必须具有正确的 IAM 权限才能成功连接。除非另有配置,否则默认服务帐户的格式为 service-PROJECT_NUMBER@gae-api-prod.google.com.iam.gserviceaccount.com。确保您的服务的服务帐户具有以下 IAM 角色:Cloud SQL 客户端,并且为了在内部 IP 上从 App Engine Standard 连接到 Cloud Sql,我们还需要角色 Compute Network User。

    gcloud iam service-accounts list
    gcloud projects add-iam-policy-binding con-ae-to-sql --member serviceAccount:con-ae-to-sql@appspot.gserviceaccount.com --role roles/cloudsql.client
    gcloud projects add-iam-policy-binding con-ae-to-sql --member serviceAccount:con-ae-to-sql@appspot.gserviceaccount.com --role roles/compute.networkUser
    

    现在我配置了设置

    1.使用 Tcp 和 unix 域套接字从 App Engine Standard 连接到 Cloud Sql

    cd app-engine-standard/
    ls
    #app.yaml  main.py requirements.txt
    
    cat requirements.txt
    Flask==1.1.1
    sqlalchemy
    pymysql
    uwsgi==2.0.18
    
    cat app.yaml
    runtime: python37
    entrypoint: uwsgi --http-socket :8080 --wsgi-file main.py --callable app --master --processes 1 --threads 2
    vpc_access_connector:
        name: "projects/con-ae-to-sql/locations/europe-west2/connectors/serverless-connector" 
    
    
    
    cat main.py
    
    from flask import Flask
    import pymysql
    from sqlalchemy import create_engine
    
    # If `entrypoint` is not defined in app.yaml, App Engine will look for an app
    # called `app` in `main.py`.
    app = Flask(__name__)
    
    @app.route('/')
    def hello():
        engine_tcp = create_engine('mysql+pymysql://user_name:user_password@internal-ip-of-database-ipinternal:3306')
        existing_databases_tcp = engine_tcp.execute("SHOW DATABASES;")
        con_tcp = "Connecting from APP Engine Standard to Cloud SQL using TCP: databases => " + str([d[0] for d in existing_databases_tcp]).strip('[]') + "\n"
        engine_unix_socket = create_engine('mysql+pymysql://user_name:user_password@/user_database?unix_socket=/cloudsql/con-ae-to-sql:europe-west2:database-external')
        existing_databases_unix_socket = engine_unix_socket.execute("SHOW DATABASES;")
        con_unix_socket = "Connecting from APP Engine Standard to Cloud SQL using Unix Sockets: tables in sys database:  => " + str([d[0] for d in existing_databases_unix_socket]).strip('[]') + "\n"
        return con_tcp + con_unix_socket
    
    
    
    gcloud app deploy -q
    gcloud app browse
    #Go to https://con-ae-to-sql.appspot.com
    #Connecting from APP Engine Standard to Cloud SQL using TCP: databases => 'information_schema', 'user_database', 'mysql', 'performance_schema', 'sys' Connecting from APP Engine Standard to Cloud SQL using Unix Sockets: tables in sys database: => 'information_schema', 'user_database', 'mysql', 'performance_schema', 'sys'
    

    成功!

    2.使用 Tcp 和 unix 域套接字从 App Engine Flex 连接到 Cloud Sql

    cd app-engine-flex/
    ls
    #app.yaml  main.py requirements.txt
    
    cat requirements.txt
    Flask==1.1.1
    gunicorn==19.9.0
    sqlalchemy
    pymysql
    
    cat app.yaml
    runtime: python
    env: flex
    entrypoint: gunicorn -b :$PORT main:app
    runtime_config:
      python_version: 3
    #Using TCP and unix sockets domain
    beta_settings:
     cloud_sql_instances: con-ae-to-sql:europe-west2:database-ipinternal=tcp:3306,con-ae-to-sql:europe-west2:database-external
    manual_scaling:
      instances: 1
    resources:
      cpu: 1
      memory_gb: 0.5
      disk_size_gb: 10
    
    
    cat main.py
    
    from flask import Flask
    import pymysql
    from sqlalchemy import create_engine
    
    app = Flask(__name__)
    
    @app.route('/')
    def hello():
        engine_tcp = create_engine('mysql+pymysql://user_name:user_password@internal-ip-of-database-ipinternal:3306')
        existing_databases_tcp = engine_tcp.execute("SHOW DATABASES;")
        con_tcp = "Connecting from APP Engine Flex to Cloud SQL using TCP: databases => " + str([d[0] for d in existing_databases_tcp]).strip('[]') + "\n"
    
        engine_unix_socket = create_engine('mysql+pymysql://user_name:user_password@/user_database?unix_socket=/cloudsql/con-ae-to-sql:europe-west2:database-external')
        existing_databases_unix_socket = engine_unix_socket.execute("SHOW DATABASES;")
        con_unix_socket = "Connecting from APP Engine Flex to Cloud SQL using Unix Sockets: tables in sys database:  => " + str([d[0] for d in existing_databases_unix_socket]).strip('[]') + "\n"
        return con_tcp + con_unix_socket
    
    
    gcloud app deploy -q
    gcloud app browse
    #Go to https://con-ae-to-sql.appspot.com
    #Connecting from APP Engine Flex to Cloud SQL using TCP: databases => 'information_schema', 'marian', 'mysql', 'performance_schema', 'sys' Connecting from APP Engine Flex to Cloud SQL using Unix Sockets: tables in sys database: => 'information_schema', 'marian', 'mysql', 'performance_schema', 'sys'
    

    成功!

    【讨论】:

    • 我在添加 vpc_access_connector 之前遇到了同样的错误,你能指导我我做错了什么吗?谢谢
    【解决方案2】:

    快速查看Connecting to Cloud SQL from App Engine 文档,并确保您已正确执行所有步骤。具体来说,请确保以下几点:

    1. 实例有公网IP
    2. Cloud SQL Admin API 已启用
    3. 服务帐号拥有 Cloud SQL IAM 权限

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-18
      • 2018-09-02
      • 2020-11-06
      相关资源
      最近更新 更多