无法从 Kubernetes Engine 连接到 CloudSQL(无法连接到 'localhost' 上的 MySQL 服务器)
Unable to connect to CloudSQL from Kubernetes Engine (Can't connect to MySQL server on 'localhost')
我尝试按照以下步骤操作:
https://cloud.google.com/sql/docs/mysql/connect-kubernetes-engine.
我在同一个 pod 中有应用程序容器和云sql 代理容器运行。
创建集群后,代理容器的日志似乎是正确的:
$kubectl logs users-app-HASH1-HASH2 cloudsql-proxy
2018/08/03 18:58:45 using credential file for authentication; email=it-test@tutorial-bookshelf-xxxxxx.iam.gserviceaccount.com
2018/08/03 18:58:45 Listening on 127.0.0.1:3306 for tutorial-bookshelf-xxxxxx:asia-south1:it-sample-01
2018/08/03 18:58:45 Ready for new connections
但是来自应用程序容器的日志抛出无法连接本地主机错误:
$kubectl logs users-app-HASH1-HASH2 app-container
...
19:27:38 users_app.1 | return Connection(*args, **kwargs)
19:27:38 users_app.1 | File "/usr/local/lib/python3.7/site-packages/pymysql/connections.py", line 327, in __init__
19:27:38 users_app.1 | self.connect()
19:27:38 users_app.1 | File "/usr/local/lib/python3.7/site-packages/pymysql/connections.py", line 629, in connect
19:27:38 users_app.1 | raise exc
19:27:38 users_app.1 | sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'localhost' ([Errno 2] No such file or directory)") (Background on this error at: http://sqlalche.me/e/e3q8)
SQLALCHEMY_DATABASE_URI
是 'mysql+pymysql://{user}:{password}@/{database}?unix_socket=/cloudsql/{cloudsql_connection_name}'
并填充了正确的值(我使用 kubectl secrets 设置的凭据)。
我确定我在这里做了一些愚蠢的事情,所以我希望对 GCP 有更多经验的人可以看看并提供解决此问题的指导。
更新:
我刚刚转到 GCP kubernetes 引擎页面并在应用程序容器上打开了一个 shell 并尝试连接到云 sql 实例。这似乎奏效了。
$gcloud container cluster ......... -it /bin/sh
#python
>>> import pymysql
>>> connection = pymysql.connect(host='127.0.0.1', user='user', password='password', db='db')
>>> with connection.cursor() as cursor:
... cursor.execute("show databases;")
... tables = cursor.fetchall()
...
5
但是以下(当我尝试通过 sqlalchemy 连接时)失败了:
>>> connection = pymysql.connect(host='127.0.0.1', user='u', password='p', db='d', unix_socket='/cloudsql/CONNECTION_NAME')
...
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on '127.0.0.1' ([Errno 2] No such file or directory)")
>>> from sqlalchemy import create_engine
>>> engine = create_engine('mysql://user:password@localhost/db')
>>> engine.connect()
Traceback (most recent call last):
...
sqlalchemy.exc.OperationalError: (_mysql_exceptions.OperationalError) (2002, 'Can\'t connect to local MySQL server through socket \'/run/mysqld/mysqld.sock\' (2 "No such file or directory")') (Background on this error at: http://sqlalche.me/e/e3q8)
>>> engine = create_engine('mysql+pymysql://user:password@/db?unix_socket=/cloudsql/tutorial-bookshelf-xxxx:asia-south1:test-01')
>>> engine.connect()
Traceback (most recent call last):
...
raise exc
sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'localhost' ([Errno 2] No such file or directory)") (Background on this error at: http://sqlalche.me/e/e3q8)
好的..发布一个答案,但我不是很满意,所以我会等待更多。
我能够通过将 SQLALCHEMY_DATABASE_URI 更改为 'mysql+pymysql://user:password@/db'
来连接到云 SQL 实例(这意味着我摆脱了 unix 套接字连接字符串)
所以 :
>>> engine = create_engine('mysql+pymysql://user:password@/db')
>>> engine.connect()
<sqlalchemy.engine.base.Connection object at 0x7f2236bdc438>
对我有用。我不确定为什么我必须摆脱 unix 套接字连接字符串,因为我确实为我的项目启用了 Cloud SQL API。
通过代理连接到云SQL 可以通过 unix 套接字或 TCP 连接来完成,但您不应尝试同时使用两者。
我没有看到关于您如何配置代理的任何规范,但如果您希望使用 unix 套接字,那么您的代理实例标志应该如下所示:-instances=<INSTANCE_CONNECTION_NAME>
。这将导致代理在 /cloudsql 目录中创建一个 unix 套接字,将流量转发到您的 Cloud SQL 实例。在这种情况下,您将在 url.
中设置 unix_socket=/cloudsql/<INSTANCE_CONNECTION_NAME>
如果您尝试通过 TCP 套接字连接,请使用这样的实例标志:-instances=<INSTANCE_CONNECTION_NAME>=tcp:3306
。这将告诉代理侦听端口 3306 并将流量转发到您的 Cloud SQL 实例。在这种情况下,您将使用 host='127.0.0.1' 和 port=3306.
如果您正在寻找有关在 GKE 上使用 CloudSQL 的实践介绍,我建议您查看此项目中提到的代码实验室:https://github.com/GoogleCloudPlatform/gmemegen
我最近通过 cloudsql-proxy 安装了 cloudSQL postgres。我有几个问题要问你。
- 您用于 cloudsql-proxy 的凭据,它们是否具有云 SQL 客户端角色。
你的cloudsql-proxy容器命令是不是这样的,
/cloud_sql_proxy",
"--dir=/cloudsql", "-instances==tcp:3306",
"-credential_file=/secrets/cloudsql/credentials.json"
如果您能分享您的 kubernetes deployment.yml 可能会有帮助,它同时具有应用程序和代理容器。
我尝试按照以下步骤操作: https://cloud.google.com/sql/docs/mysql/connect-kubernetes-engine.
我在同一个 pod 中有应用程序容器和云sql 代理容器运行。
创建集群后,代理容器的日志似乎是正确的:
$kubectl logs users-app-HASH1-HASH2 cloudsql-proxy
2018/08/03 18:58:45 using credential file for authentication; email=it-test@tutorial-bookshelf-xxxxxx.iam.gserviceaccount.com
2018/08/03 18:58:45 Listening on 127.0.0.1:3306 for tutorial-bookshelf-xxxxxx:asia-south1:it-sample-01
2018/08/03 18:58:45 Ready for new connections
但是来自应用程序容器的日志抛出无法连接本地主机错误:
$kubectl logs users-app-HASH1-HASH2 app-container
...
19:27:38 users_app.1 | return Connection(*args, **kwargs)
19:27:38 users_app.1 | File "/usr/local/lib/python3.7/site-packages/pymysql/connections.py", line 327, in __init__
19:27:38 users_app.1 | self.connect()
19:27:38 users_app.1 | File "/usr/local/lib/python3.7/site-packages/pymysql/connections.py", line 629, in connect
19:27:38 users_app.1 | raise exc
19:27:38 users_app.1 | sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'localhost' ([Errno 2] No such file or directory)") (Background on this error at: http://sqlalche.me/e/e3q8)
SQLALCHEMY_DATABASE_URI
是 'mysql+pymysql://{user}:{password}@/{database}?unix_socket=/cloudsql/{cloudsql_connection_name}'
并填充了正确的值(我使用 kubectl secrets 设置的凭据)。
我确定我在这里做了一些愚蠢的事情,所以我希望对 GCP 有更多经验的人可以看看并提供解决此问题的指导。
更新: 我刚刚转到 GCP kubernetes 引擎页面并在应用程序容器上打开了一个 shell 并尝试连接到云 sql 实例。这似乎奏效了。
$gcloud container cluster ......... -it /bin/sh
#python
>>> import pymysql
>>> connection = pymysql.connect(host='127.0.0.1', user='user', password='password', db='db')
>>> with connection.cursor() as cursor:
... cursor.execute("show databases;")
... tables = cursor.fetchall()
...
5
但是以下(当我尝试通过 sqlalchemy 连接时)失败了:
>>> connection = pymysql.connect(host='127.0.0.1', user='u', password='p', db='d', unix_socket='/cloudsql/CONNECTION_NAME')
...
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on '127.0.0.1' ([Errno 2] No such file or directory)")
>>> from sqlalchemy import create_engine
>>> engine = create_engine('mysql://user:password@localhost/db')
>>> engine.connect()
Traceback (most recent call last):
...
sqlalchemy.exc.OperationalError: (_mysql_exceptions.OperationalError) (2002, 'Can\'t connect to local MySQL server through socket \'/run/mysqld/mysqld.sock\' (2 "No such file or directory")') (Background on this error at: http://sqlalche.me/e/e3q8)
>>> engine = create_engine('mysql+pymysql://user:password@/db?unix_socket=/cloudsql/tutorial-bookshelf-xxxx:asia-south1:test-01')
>>> engine.connect()
Traceback (most recent call last):
...
raise exc
sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'localhost' ([Errno 2] No such file or directory)") (Background on this error at: http://sqlalche.me/e/e3q8)
好的..发布一个答案,但我不是很满意,所以我会等待更多。
我能够通过将 SQLALCHEMY_DATABASE_URI 更改为 'mysql+pymysql://user:password@/db'
来连接到云 SQL 实例(这意味着我摆脱了 unix 套接字连接字符串)
所以 :
>>> engine = create_engine('mysql+pymysql://user:password@/db')
>>> engine.connect()
<sqlalchemy.engine.base.Connection object at 0x7f2236bdc438>
对我有用。我不确定为什么我必须摆脱 unix 套接字连接字符串,因为我确实为我的项目启用了 Cloud SQL API。
通过代理连接到云SQL 可以通过 unix 套接字或 TCP 连接来完成,但您不应尝试同时使用两者。
我没有看到关于您如何配置代理的任何规范,但如果您希望使用 unix 套接字,那么您的代理实例标志应该如下所示:-instances=<INSTANCE_CONNECTION_NAME>
。这将导致代理在 /cloudsql 目录中创建一个 unix 套接字,将流量转发到您的 Cloud SQL 实例。在这种情况下,您将在 url.
unix_socket=/cloudsql/<INSTANCE_CONNECTION_NAME>
如果您尝试通过 TCP 套接字连接,请使用这样的实例标志:-instances=<INSTANCE_CONNECTION_NAME>=tcp:3306
。这将告诉代理侦听端口 3306 并将流量转发到您的 Cloud SQL 实例。在这种情况下,您将使用 host='127.0.0.1' 和 port=3306.
如果您正在寻找有关在 GKE 上使用 CloudSQL 的实践介绍,我建议您查看此项目中提到的代码实验室:https://github.com/GoogleCloudPlatform/gmemegen
我最近通过 cloudsql-proxy 安装了 cloudSQL postgres。我有几个问题要问你。
- 您用于 cloudsql-proxy 的凭据,它们是否具有云 SQL 客户端角色。
你的cloudsql-proxy容器命令是不是这样的,
/cloud_sql_proxy", "--dir=/cloudsql", "-instances==tcp:3306", "-credential_file=/secrets/cloudsql/credentials.json"
如果您能分享您的 kubernetes deployment.yml 可能会有帮助,它同时具有应用程序和代理容器。