PySpark 通过 Dataproc + SSL 连接到云 SQL

PySpark via Dataproc + SSL Connection to Cloud SQL

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

我能够使用 --ssl-ca--ssl-cert--ssl-key 选项从命令行使用 MySQL 成功连接到云 SQL分别指定服务器证书、客户端public密钥、客户端私钥:

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 作业与所述脚本的 this example provided by Google Cloud training team. On line 39 基本相同,有一个 JDBC 连接到云 SQL 实例:

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 实例 disabled 有未加密的连接,我会看到以下错误消息:

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)

而如果我有未加密的连接到云 SQL 实例 已启用 ,工作 运行 就可以了。 (这表明问题不在于 Cloud SQL API 权限 - 我 运行 从中执行 PySpark 作业的集群绝对有权访问 Cloud SQL 实例.)

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

Dataproc 集群上有一个 handy initialization action for configuring the CloudSQL Proxy。默认情况下,它假定您打算将 CloudSQL 用于 Hive 元存储,但是如果您下载它并对其进行自定义设置 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