PySpark通过Dataproc + SSL连接到Cloud SQL

时间:2017-09-21 07:27:37

标签: python ssl jdbc google-cloud-sql google-cloud-dataproc

我有一个在数据库中存储数据的Cloud SQL实例,我已经检查了此Cloud SQL实例的选项以阻止所有未加密的连接。当我选择此选项时,我将获得三个SSL证书 - 服务器证书,客户端公钥和客户端私钥(三个单独的.pem文件)(link to relevant CloudSQL+SSL documentation)。这些证书文件用于建立与Cloud SQL实例的加密连接。

我可以使用--ssl-ca--ssl-cert--ssl-key选项从命令行使用MySQL成功连接到Cloud SQL,以指定服务器证书,客户端公钥,和客户端私钥分别:

mysql -uroot -p -h <host-ip-address> \
--ssl-ca=server-ca.pem \
--ssl-cert=client-cert.pem \
--ssl-key=client-key.pem

我现在正在尝试运行连接到此Cloud SQL实例的PySpark作业,以提取数据以对其进行分析。 PySpark作业与Google Cloud培训团队提供的this example基本相同。在所述脚本的line 39上,存在与Cloud SQL实例建立的JDBC连接:

jdbcDriver = 'com.mysql.jdbc.Driver'
jdbcUrl = 'jdbc:mysql://%s:3306/%s?user=%s&password=%s' % (CLOUDSQL_INSTANCE_IP, CLOUDSQL_DB_NAME, CLOUDSQL_USER, CLOUDSQL_PWD)

但这不会形成加密连接,也不会提供三个证书文件。如果我有与Cloud SQL实例禁用的未加密连接,我会看到以下错误消息:

17/09/21 06:23:21 INFO org.spark_project.jetty.util.log: Logging initialized @5353ms
17/09/21 06:23:21 INFO org.spark_project.jetty.server.Server: jetty-9.3.z-SNAPSHOT
17/09/21 06:23:21 INFO org.spark_project.jetty.server.Server: Started @5426ms
17/09/21 06:23:21 INFO org.spark_project.jetty.server.AbstractConnector: Started ServerConnector@74af54ac{HTTP/1.1,[http/1.1]}{0.0.0.0:4040}

[...snip...]

py4j.protocol.Py4JJavaError: An error occurred while calling o51.load.
: java.sql.SQLException: Access denied for user 'root'@'<cloud-sql-instance-ip>' (using password: YES)

如果我有与Cloud SQL实例启用的未加密连接,则作业运行正常。 (这表明问题不在于Cloud SQL API权限 - 我正在运行PySpark作业的群集肯定有权访问Cloud SQL实例。)

我发现涉及SSL add a &useSSL=true or &encrypt=true but do not point to external certificates的JDBC连接字符串;或者,他们在某种特定于Java的过程中使用keystore。如何从上面链接的Python脚本修改JDBC连接字符串,以便将JDBC(通过PySpark)指向服务器证书和客户端公钥/私钥的位置(server-ca.pem,client-cert.pem)和磁盘上的client-key.pem)?

1 个答案:

答案 0 :(得分:0)

Dataproc群集上有handy initialization action for configuring the CloudSQL Proxy个。默认情况下,它假定您打算将CloudSQL用于Hive Metastore,但如果您下载并自定义设置ENABLE_CLOUD_SQL_METASTORE=0然后将其重新上传到您自己的存储桶中以用作自定义初始化操作,那么您应该自动在所有节点上安装CloudSQL代理。然后你只需将你的mysql连接字符串设置为指向localhost而不是真正的CloudSQL IP。

指定元数据标记时,如果您在元数据中禁用了additional-cloud-sql-instances 而不是 hive-metastore-instance

--metadata "additional-cloud-sql-instances=<PROJECT_ID>:<REGION>:<ANOTHER_INSTANCE_NAME>=tcp<PORT_#>`

在这种情况下,您可以选择使用脚本默认用于Metastore的相同端口分配,即端口3306