我有一个云实例存储数据库中的数据,我已经检查了此云SQL实例的选项以阻止所有未加密的连接。当我选择此选项时,我将获得三个SSL证书 - 服务器证书,客户端键和客户端私钥(三个单独的.pem文件)(链接到相关的Cloudsql SSL文档)。这些证书文件用于建立与云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
我现在正在尝试运行一个连接到此云SQL实例的Pyspark作业,以提取数据以分析它。Pyspark的工作与Google Cloud Training团队提供的示例基本相同。在所述脚本的第39行中,有一个与云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实例 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连接字符串涉及SSL添加&useSSL=true
或&encrypt=true
,但请勿指向外部证书;或者,他们在某种特定于Java的过程中使用密钥库。如何将JDBC连接字符串从链接到上面的python脚本修改,以便指向JDBC(通过PySpark)指向服务器证书的位置和客户端公共/私人键(server-ca.pem,client-cert.pem)和client-key.pem)在磁盘上?
有一个方便的初始化操作,用于在DataProc群集上配置CloudSQL代理。默认情况下,它假定您打算将CloudSQL用于Hive Metastore,但是如果您下载并自定义设置ENABLE_CLOUD_SQL_METASTORE=0
,然后将其重新上传到自己的存储桶中以用作自定义初始化操作,则应自动获得CloudSQL Proxy安装在所有节点上。然后,您只需将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
。