Jak połączyć się z Databricks to Azure SQL Server?
Problem:
Wykonanie połączenia między Databricks i bazą danych SQL Servera w chmurze Azure.
Co będzie potrzebne?
- Databricks 😉
- Azure SQL Server utworzony w Azure Portal
- Otwarte połączenia sieciowe - Databricks i SQL Server mają mieć możliwość komunikacji. Jeżeli masz problemy na tym poziomie, to niestety nie będzie przedmiotem tego wpisu.
- Service principal - żeby połączyć się z Databricks do SQL Servera w bezpieczny i prosty sposób
- Key Vault - do przechowywania sekretów
- Biblioteki Python - biblioteka do wykonania połączenia JDBC i do używania modułu Azure Identity
Wszystko gotowe? Zaczynamy!
Service principal
Zakładam, że wiesz jak stworzyć service principala w Azure Active Directory:
https://learn.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principals
Po stworzeniu service pricipala z zakładki szczegóły będziesz potrzebował: Application Id i Tenant id:
Z zakładki Certificates & Secrets będziesz też potrzebował Secret dla tego service principala, będziemy go za chwilę wstawiać do KeyVault'a.
Ważne!
Ten service principal musi mieć dostęp do bazy danych. W tym celu musisz stworzyć w bazie danych użytkownika dla service principala:
CREATE USER [ServicePrincipalName] FROM EXTERNAL PROVIDER
I dodać prawa, na przykład, tylko do odczytu:
ALTER ROLE db_datareader ADD MEMBER [trsalesbi-qa-euw-sp-01];
Albo gdy będziesz chciał dodać trochę więcej 😉
ALTER ROLE db_datawriter ADD MEMBER [trsalesbi-qa-euw-sp-01];
ALTER ROLE db_ddladmin ADD MEMBER [trsalesbi-qa-euw-sp-01];
Key Vault
Dobrą praktyką jest, żeby secrety w Databricks przechowywać w Key Vault.
Jak zrbić połączenie pomiędzy Azure Key Vault i Databricks opisane jest tutaj:
https://learn.microsoft.com/en-us/azure/databricks/security/secrets/secret-scopes
Co najważniejsze z tej dokumentacji to stworzenie połączenia między Azure KeyVault i Databricks.
https://
Jeżeli nie wiesz, czy masz już zdefiniowane połączenie między Azure Key Vault i Databricks możesz to sprawdzić używając Databricks CLI:
databricks secrets list-scopes
Możesz to też sprawdzić używając rest api
https://learn.microsoft.com/en-us/azure/databricks/dev-tools/api/latest/secrets#--list-secret-scopes
Endpoit powinien jest taki:
2.0/secrets/scopes/list
Po połączeniu Key Vaulta i Databricksa dodajesz tam service principal application id oraz secert:
Biblioteki Python
W konfiguracji clustra w zakładce Libraries dodaj biblioteki:
Potrzebujesz dwie biblioteki z pypi pobierz:
azure-identity
Natomiast z Maven'a będziesz potrzebował:
com.microsoft.azure:spark-mssql-connector_2.12_3.0:1.0.0-alpha
azure-identity
Za chwilę będziesz używał ich w notebooku.
Notebook
Zmęczony konfiguracją? Czas na trochę kodowania:
Zacznijmy od importu bibliotek:
import json
import requests
from azure.identity import ClientSecretCredential
W poniższym kodzie wstaw swój tenant id.
Następnie zmieniasz nazwę Databricks secret scope i podajesz klucze jakie definiowałęś w KeyVault.
tenant_id = 'your-tenant-id-from-azuread'
#key-vault-dbxsecrets - this is databricks secret scope, that points to Azure Active Directory Key Vault
client_id = dbutils.secrets.get(scope = 'key-vault-dbxsecrets', key = 'your-sp-appid')
client_secret = dbutils.secrets.get(scope = 'key-vault-dbxsecrets', key = 'your-sp-secret')
Po pobraniu sekretów pora jeszcze raz udać się do Azure portalu i tym razem skopiować nazwę serwera i bazy danych, mi najłatwiej było to pobrać wziąć z Database connection strings:
server_name = 'your-azure-sql-server-name'
db_name = 'your-azure-database-name'
db_scope = 'https://database.windows.net/.default'
azure_sql_url = f'jdbc:sqlserver://{server_name}.database.windows.net'
database = f'{db_name}'
Wreszcie pora na pobranie tokena
auth = ClientSecretCredential(authority = 'https://login.microsoftonline.com/',
tenant_id = tenant_id,
client_id = client_id,
client_secret = client_secret)
db_access_token = auth.get_token(db_scope)
db_access_token = db_access_token.token
Jeżeli wszystko poszło dobrze, to możesz teraz pobrać dane z tabeli:
spark.read.format('jdbc').option('url', azure_sql_url).option('dbtable', table_name).option('database', database).option('accessToken', db_access_token).load()
Cały notebook znajdziesz oczywiście na Githubie.
Niestety to nie jest krótki proces, jeżeli robisz to "manualnie". Jeżeli robisz to często zapewne da się to zautomatyzować przy użyciu CLI.
Daj znać z czym miałeś największy problem, i co zajęło Ci najwięcej czasu. Będzie mi też miło, jeżeli dasz mi znać, że udało Ci się połączyć 🙂