Skip to main content

故障排查:开启了Databricks的Table Access Controler之后,Python脚本无法访问外部的数据库了

分类:  故障排查 标签:  #Databricks #大数据 发布于: 2023-08-07 22:14:07

最近遇到一个案例:起初我们是想在Databricks里通过pyodbc访问访问外部的数据,这个简单,写一个脚本,然后把这个脚本放置到集群的初始化脚本里,安装必要的库就行了。脚本如下:

#!/bin/sh
curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list > /etc/apt/sources.list.d/mssql-release.list
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install msodbcsql17
pip install pyodbc

写完保存该脚本之后,上传到DBFS里,如下图:


上传成功后,在创建集群的时候或者编辑集群按照如下的方式配置初始化脚本:


启动集群之后,创建一个Notebook, 运行如下的Python脚本:

import pyodbc

conn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};'
                      'SERVER={ServerName};'
                      'DATABASE={dbname};UID={username};'
                      'PWD={Password}')

cursor = conn.cursor()
cursor.execute("SELECT @@version;")
row = cursor.fetchone()
while row:
    print(row[0])
    row = cursor.fetchone()
    
conn.close()    

运行该notebook可以很完美的得到结果。

继续测试,从Databricks菜单里启用Table Access Control


Admin Console:


重启集群,再次运行该notebook,发现问题来了:


刚才还好好的notebook现在报错了:

OperationalError: ('HYT00', '[HYT00] [unixODBC][Microsoft][ODBC Driver 17 for SQL Server]Login timeout expired (0) (SQLDriverConnect)')

开始排查,首先想到的肯定是因为开启了Table access control, 为了验证这个问题,关闭Table access Control, 测试成功,打开,失败。

所以问题就是出在Table Access control上,根据错误的提示,首先想到是不是网络不通了。

Notebook里新建一个cell, 运行:

%sh
nc -zv {you Database address} 1433

发现还是真是连不通了,赶紧翻文档,找到文档说明:
https://learn.microsoft.com/en-us/azure/databricks/security/access-control/table-acls/table-acl


果然找到了问题所在,所以需要在集群里添加一个配置:

spark.databricks.pyspark.iptable.outbound.whitelisted.ports 1433

如下图:


重启集群,然后再次使用如下的脚本测试连通性:

%sh
nc -zv {you Database address} 1433

这次发现果然端口通了。

再次运行notebook, 还是报错,同样的错误:

OperationalError: ('HYT00', '[HYT00] [unixODBC][Microsoft][ODBC Driver 17 for SQL Server]Login timeout expired (0) (SQLDriverConnect)')

头疼!明明端口是通的,为什么又报错了?想起了另外一件事:会不会是外部的Azure SQL DB的问题。记起来了Azure SQL DB有提供三种连接方式:

  • default
  • proxy
  • redirect

打开Azure SQL DB ServerNetworking,可以看到:


如果选择模式redirect,SQL DB的连接实际上只有第一次连接走1433,后面的存取直接和instance通讯了,用了其他的端口。所以我们需要选择Proxy模式,永远都使用1433的默认端口。

重新设定了Azure SQL DB的连接方式,终于连接成功了!