azure databricks中使用Unity Catalog 02--功能体验

发布时间 2023-03-28 01:45:11作者: John.Xiong

目录

  • 先决条件

  • 在Azure Databricks环境中设置Unity Catalog元存储

    • 步骤1:为元存储创建blob存储

    • 步骤2:创建Azure Databricks访问连接器

    • 步骤3:在Azure Databricks帐户控制台中创建元存储

    • 步骤4a:创建catalog和托管表

    • 步骤4b:创建一个外部表

  • Unity Catalog中的访问控制

  • Unity Catalog中的数据血缘

  • 使用“动态”视图进行行级安全性和列级筛选

先决条件

以下是我们需要考虑在Azure Databricks中使用Unity Catalog的一些先决条件。

  1. Azure Databricks帐户应在高级计划中。

  2. 第一个Azure Databricks帐户管理员在首次登录Azure Databrick帐户控制台时必须是Azure Active Directory全局管理员(https://accounts.azuredatabricks.net/login/ ). 首次登录后,AAD管理员将成为Azure Databricks全局管理员。AAD管理员可以将Azure Databricks全局管理员权限分配给其他用户,这些用户可以在没有AAD全局管理员参与的情况下进一步执行全局管理员角色。

  3. 如果我们有跨多个地区(美国东部/西部)的多个Azure Databricks工作区,则需要为每个地区提供单独的元存储。我们不能在多个地区共享元存储。例如,如果我们有两个Azure Databricks工作区,一个在EastUS,另一个在WestUS,我们需要为每个区域创建两个元存储。

在Azure Databricks环境中设置Unity Catalog元存储

步骤1:为元存储创建blob存储

正常创建一个azure storage blob,但是有一点要注意:层次结构命名空间,必须启用。

image-20230327230344350

创建一个container,并记录下其dfs的访问地址abfss://<container-name>@<storage-account-name>.dfs.core.windows.net/<metastore-name>,例如:abfss://unitycatalogmetastore01@labseaunitycatalog.dfs.core.windows.net/unitycatalogdemo01

步骤2:创建Azure Databricks访问连接器

  1. 从Azure门户,让我们创建一个资源Azure Databricks访问连接器。部署后连接器资源URI将是Azure Databricks的托管标识。从Azure Databricks到其他资源的身份验证将使用此托管身份进行。记录下资源ID

    image-20230327231009120

    image-20230327230856731

  2. 在我们在前面部分中创建的元存储blob,将访问连接器授予“存储 Blob 数据参与者”访问权限。

    image-20230327231414942

步骤3:在Azure Databricks帐户控制台中创建元存储

需要注意的是,AAD Global管理员必须首次登录帐户控制台。一旦AAD Global管理员登录,他们将添加任何用户或组作为帐户管理员,这样以后帐户控制台就可以由添加的用户进行管理。添加的用户将成为Azure Databricks帐户管理员。

  1. 创建高级Azure Databricks工作区。

  2. 登录帐户控制台(https://accounts.azuredatabricks.net/)使用任何AAD全局管理帐户。

  3. 转到用户管理并添加一个不同的帐户作为帐户管理员。(可选)

  4. 创建metastore。谨记一个区域一个metastore。

    image-20230327232104030

  5. 将元存储与Azure Databricks工作区连接起来。工作区和mestore在同一个区域的才能关联起来。如果同一区域中有多个工作区,我们可以将所有工作区都附加到单个元存储中。通过共享元存储,我们可以在工作空间中共享对象。

    image-20230327232355898

  6. 登录到Azure Databricks工作区时,我们将能够看到一个默认的catalog “main”,该catalog是在我们将Unity catalog元存储与Azure Databrick工作区连接时创建的。

    image-20230327232535711

步骤4a:创建catalog和托管表

%sql
create catalog if not exists myfirstcatalog;

create database if not exists myfirstcatalog.mytestDB;

%python
#read the sample data into dataframe
df_flight_data = spark.read.csv("/databricks-datasets/flights/departuredelays.csv", header=True)
df_flight_data.createOrReplaceTempView("temp_tbl")


%sql
create table if not exists myfirstcatalog.mytestDB.myFirstManagedTable
AS
Select * from temp_tbl

image-20230327232942863

image-20230327233653574

步骤4b:创建一个外部表

在一些外部位置(如Azure Blob Storage或ADLS g2帐户)中以hive或delta格式存在数据。我们想将该表附加到我们的Unity目录元存储中。 需要注意的是,Unity Catalog元存储可能无法直接访问外部位置。要建立这种访问,我们需要通过提供实际路径来创建存储凭据和外部位置。Unity Catalog将使用访问连接器管理的身份(access connector for Azure Databricks)来访问外部位置。我们需要提供对外部存储位置的访问连接器授予“存储 Blob 数据参与者”访问权限

创建存储凭据

我们正在使用访问连接器(托管标识)来创建存储凭据。我们还可以提供服务主体的方式(不太推荐)。

可将 Unity Catalog 配置为使用 Azure 托管标识以 Unity Catalog 用户身份访问存储容器。 托管标识为应用程序提供一个标识,可以在连接到支持 Azure Active Directory (Azure AD) 身份验证的资源时使用。

  • 可使用 Unity Catalog 中的托管标识来支持两个主要用例:

    • 作为连接到元存储的根存储帐户(存储托管表的位置)的标识。

    • 作为连接到其他外部存储帐户的标识(用于基于文件的访问或外部表)。

与使用服务主体配置 Unity Catalog 相比,使用托管标识配置 Unity Catalog 具有以下优势:

  • 你可连接到受存储防火墙保护的 Azure Data Lake Storage Gen2 帐户。

  • 托管标识不需要维护凭据或轮换机密。

image-20230327233557160

创建外部位置

在创建外部表之前,我们需要将物理数据位置与之前创建的存储凭据进行映射。

image-20230327233746680

测试创建外部表

 %python

#read the sample data into dataframe
df_flight_data = spark.read.csv("/databricks-datasets/flights/departuredelays.csv", header=True)

#create the delta table to the mount point that we have created earlier
dbutils.fs.rm("abfss://labdpdw@labseadpdw01.dfs.core.windows.net/mytestDB/MyFirstExternalTable", recurse=True)
df_flight_data.write.format("delta").mode("overwrite").save("abfss://labdpdw@labseadpdw01.dfs.core.windows.net/mytestDB/MyFirstExternalTable")
 %sql
create table if not exists myfirstcatalog.mytestDB.MyFirstExternalTable
USING DELTA
LOCATION 'abfss://labdpdw@labseadpdw01.dfs.core.windows.net/mytestDB/MyFirstExternalTable'

Unity Catalog中的访问控制

以下是Unity Catalog中的安全对象。访问级别是从父级对象继承到子级对象的。例如,如果我们提供对目录的读取访问,它将被继承到层次结构中的最后一个子级(即架构/托管表/视图…等)。我们可以通过使用SQL命令、Unity catalog CLI或在Data Explorer中管理元存储对象的权限。 重要提示:在Unity Catalog Metastore中提供的权限不会被继承。权限可以由metastore管理员授予。

image-20230327234757266

example:授予一个测试用户访问特定的表,使用databricks SQL方式操作。

步骤1:让我们创建一个Azure Databricks组,该组将包含所有对该表具有只读权限的用户(myfirstcatalog.mytestDB.MyFirstExternalTable)。为此,我们需要导航到Databricks帐户控制台组部分。然后我们需要将用户添加到组中。

image-20230327235305664

image-20230327235356944

授予cluster权限

image-20230327235543132

步骤2:在Azure Databricks中运行GRANT命令。这应该由元存储管理员运行。

 %sql
grant USE_CATALOG on catalog myfirstcatalog to group_data_reader;
grant USE_SCHEMA on schema myfirstcatalog.mytestDB to group_data_reader;
grant select on table myfirstcatalog.mytestDB.MyFirstExternalTable to group_data_reader;

运行后,使用group_data_reader组中的账户登录databricks,就可以看到表了。

image-20230328000538989

Unity Catalog中的数据血缘

可以捕获在Azure Databricks集群上执行的任何语言的查询之间的运行时数据血缘。血缘是从表级别和列级别捕获的。血缘数据包括与查询相关的笔记本、工作流和仪表板。 血缘图与上一节中讨论的Unity Catalog共享相同的权限模型。用户无权访问的表不会显示在血缘图中。

example:创建notebook,执行如下代码,创建table和引用数据之间的关系表

 %sql
create catalog lineage_data;
CREATE SCHEMA lineage_data.lineagedemo;
 %sql
CREATE TABLE IF NOT EXISTS
  lineage_data.lineagedemo.menu (
    recipe_id INT,
    app string,
    main string,
    dessert string
   );

INSERT INTO lineage_data.lineagedemo.menu
     (recipe_id, app, main, dessert)
VALUES
     (1,"Ceviche", "Tacos", "Flan"),
     (2,"Tomato Soup", "Souffle", "Creme Brulee"),
     (3,"Chips","Grilled Cheese","Cheesecake");

CREATE TABLE
  lineage_data.lineagedemo.dinner
AS SELECT
  recipe_id, concat(app," + ", main," + ",dessert)
AS
  full_menu
FROM
  lineage_data.lineagedemo.menu
%python
from pyspark.sql.functions import rand, round
df = spark.range(3).withColumn("price", round(10*rand(seed=42),2)).withColumnRenamed("id","recipe_id")

df.write.mode("overwrite").saveAsTable("lineage_data.lineagedemo.price")

dinner = spark.read.table("lineage_data.lineagedemo.dinner")
price = spark.read.table("lineage_data.lineagedemo.price")

dinner_price = dinner.join(price, on="recipe_id")
dinner_price.write.mode("overwrite").saveAsTable("lineage_data.lineagedemo.dinner_price")

image-20230328001136579

点击see linage graph,可以显示table之间的关系以及字段之间的引用关系

image-20230328001213943

%sql
-- 复杂的col引用:一个col来自多个col的数据
create table lineage_data.lineagedemo.tbl_col_refNCol
as
select recipe_id, app, main, dessert, case when recipe_id = 1 then app when recipe_id = 2 then main else dessert end as col3 from lineage_data.lineagedemo.menu

image-20230328001750308

%sql
-- 复杂的col引用:一个col来自多个table col的数据
create table lineage_data.lineagedemo.tbl_col_refNCol_byjoin
as
select a1.recipe_id, a1.full_menu, case when a1.full_menu like '%Sou%' then a2.price else 0.0 end as price from lineage_data.lineagedemo.dinner as a1
left join lineage_data.lineagedemo.price as a2
on (
a1.recipe_id = a2.recipe_id
)

image-20230328002403444

%sql
-- 复杂的col引用:一个col来自多个table col的数据,并使用聚合函数
create table lineage_data.lineagedemo.tbl_col_refNCol_byjoin_agg
as
select a1.recipe_id, a1.full_menu, sum(case when a1.full_menu like '%Sou%' then a2.price else 0.0 end) as sum_price from lineage_data.lineagedemo.dinner as a1
left join lineage_data.lineagedemo.price as a2
on (
a1.recipe_id = a2.recipe_id
)
group by a1.recipe_id, a1.full_menu

image-20230328002645257

测试无权访问的表将会被mask起来

%sql
grant USE_CATALOG on catalog lineage_data to group_data_reader;
grant USE_SCHEMA on schema lineage_data.lineagedemo to group_data_reader;
grant select on table lineage_data.lineagedemo.tbl_col_refncol_byjoin_agg to group_data_reader;

image-20230328002902309

使用“动态”视图进行行级安全性和列级筛选

在Unity Catalog中,我们可以使用动态视图来配置行和列中的细粒度访问控制。此外,我们可以根据权限屏蔽数据。 如果当前用户是特定帐户级别组的成员,则新的内置函数is_account_group_member(account group)将返回TRUE。建议在针对Unity目录数据的动态视图中使用。

Unity Catalog 引入了以下功能,这些功能允许你动态限制哪些用户可以访问视图中的行、列:

current_user():返回当前用户的电子邮件地址。 is_account_group_member():如果当前用户是特定帐户级别组的成员,则返回 TRUE。 建议在针对 Unity Catalog 数据的动态视图中使用。 is_member():如果当前用户是特定工作区级别组的成员,则返回 TRUE。 提供此函数是为了与现有 Hive 元存储兼容。 请避免将它与针对 Unity Catalog 数据的视图一起使用,因为它不评估帐户级别的组成员身份。

列级别权限

example:普通用户看到部分关键列是打码的,管理员是可以看到正常数据的。

%sql
create view if not exists myfirstcatalog.mytestDB.vw_col_mask_demo1
as
select date,

case when is_account_group_member("group_data_admin") then delay else '***' end as delay,

distance, origin, destination from myfirstcatalog.mytestDB.MyFirstExternalTable;

# 授权
grant select on table myfirstcatalog.mytestDB.vw_col_mask_demo1 to group_data_reader;

image-20230328004315520

行级别权限

现在我们将扩展前面的例子。我们有几个特定于的组,例如,ABE_admin只能看到origin=‘ABE’的数据,类似地,ATL_admin组应该只能看到origin=‘TL’的数据。如果任何用户不属于任何组,他们将无法查看数据。group_data_admin组的用户将能够看到所有数据。

%sql
create view if not exists myfirstcatalog.mytestDB.vw_row_level_demo1
as
select date,

case when is_account_group_member("group_data_admin") then delay else '***' end as delay,

distance, origin, destination from myfirstcatalog.mytestDB.MyFirstExternalTable
where case
when is_account_group_member("group_data_admin") then true
when is_account_group_member("ABE_group") then origin = 'ABE'
when is_account_group_member("ATL_group") then origin = 'ATL'
else false
end

创建ABE_group组,添加一个普通用户进去,并添加到workspace中。

image-20230328005223358

image-20230328005245560

%sql
grant select on table myfirstcatalog.mytestDB.vw_row_level_demo1 to ABE_group;

image-20230328005405578