DatabricksのUnity Catalogを利用してS3のデータを外部テーブルとして読み込んでみた

DatabricksのUnity Catalogを利用してS3のデータを外部テーブルとして読み込んでみた

Clock Icon2025.03.28

データ事業本部のueharaです。

今回は、DatabricksのUnity Catalogを利用してS3のデータを外部テーブルとして読み込んでみたいと思います。

はじめに

データレイクとして、既にS3にてHive形式でParquetファイルを格納しているというケースは多いと思います。

今回は、DatabricksのUnity Catalogを利用して、S3にあるParquetファイルを読み込んでみたいと思います。

事前準備・設定

IAMロールの作成

Databricksから対象のAWSアカウントにあるS3にアクセスするためのIAMロールを作成します。

AWSマネージドコンソールからIAMサービスにアクセスし『ロールの作成』を選択します。

次に『カスタム信頼ポリシー』を選択して、以下の内容を記載します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": ["arn:aws:iam::414351767826:role/unity-catalog-prod-UCMasterRole-14S5ZJVKOTYTL"]
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "0000"
        }
      }
    }
  ]
}

このポリシーでは、Unity Catalogがバケット内のデータにアクセスするロールを引き受けることができるように、クロスアカウントの信頼関係が記載されています。

いまいまはプレースホルダーとして外部IDを 0000 に設定していますが、こちらは後の手順で環境に合わせ更新します。

アクセス許可ポリシーの構成はスキップし、ロール名を記載してIAMロールを保存します(ポリシーは次のステップで追加します)

次に、作成したIAMロールに対しインラインポリシーを設定します。

0328_databricks_01

作成するポリシーは以下の通りです。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject",
        "s3:ListBucket",
        "s3:GetBucketLocation",
        "s3:ListBucketMultipartUploads",
        "s3:ListMultipartUploadParts",
        "s3:AbortMultipartUpload"
      ],
      "Resource": ["arn:aws:s3:::<BUCKET>/*", "arn:aws:s3:::<BUCKET>"],
      "Effect": "Allow"
    },
    {
      "Action": ["sts:AssumeRole"],
      "Resource": ["arn:aws:iam::<AWS-ACCOUNT-ID>:role/<AWS-IAM-ROLE-NAME>"],
      "Effect": "Allow"
    }
  ]
}

プレースホルダにしている部分は以下を設定して下さい。

項目 設定値
<BUCKET> 利用するS3バケットの名前
<AWS-ACCOUNT-ID> 利用しているAWSアカウントのアカウントID
<AWS-IAM-ROLE-NAME> 上記で作成したIAMロールの名前

なお、今回使用するS3バケットの暗号化にはSSE-S3を利用している想定のため、KMSに関する記載は省略していますが、S3バケットの暗号化にKMSを利用している場合は当該KMSに対する "kms:Decrypt", "kms:Encrypt", "kms:GenerateDataKey*" 権限も付与して下さい。

次に、同じロールに対し以下のポリシーも作成してアタッチします。(※こちらのポリシーの追加は必須ではないのですが、Databricksでファイルイベントを構成する場合に必要となる権限であり、設定が推奨されているため一応この場で作成してアタッチしておきます)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ManagedFileEventsSetupStatement",
      "Effect": "Allow",
      "Action": [
        "s3:GetBucketNotification",
        "s3:PutBucketNotification",
        "sns:ListSubscriptionsByTopic",
        "sns:GetTopicAttributes",
        "sns:SetTopicAttributes",
        "sns:CreateTopic",
        "sns:TagResource",
        "sns:Publish",
        "sns:Subscribe",
        "sqs:CreateQueue",
        "sqs:DeleteMessage",
        "sqs:ReceiveMessage",
        "sqs:SendMessage",
        "sqs:GetQueueUrl",
        "sqs:GetQueueAttributes",
        "sqs:SetQueueAttributes",
        "sqs:TagQueue",
        "sqs:ChangeMessageVisibility",
        "sqs:PurgeQueue"
      ],
      "Resource": ["arn:aws:s3:::<BUCKET>", "arn:aws:sqs:*:*:csms-*", "arn:aws:sns:*:*:csms-*"]
    },
    {
      "Sid": "ManagedFileEventsListStatement",
      "Effect": "Allow",
      "Action": ["sqs:ListQueues", "sqs:ListQueueTags", "sns:ListTopics"],
      "Resource": ["arn:aws:sqs:*:*:csms-*", "arn:aws:sns:*:*:csms-*"]
    },
    {
      "Sid": "ManagedFileEventsTeardownStatement",
      "Effect": "Allow",
      "Action": ["sns:Unsubscribe", "sns:DeleteTopic", "sqs:DeleteQueue"],
      "Resource": ["arn:aws:sqs:*:*:csms-*", "arn:aws:sns:*:*:csms-*"]
    }
  ]
}

<BUCKET> は先程のポリシーと同じ値を設定してください。

これでIAMロールの準備は完了です。

DatabricksでCredentialの作成

Databricksにログインした後、左側のタブにある『Catalog』を選択します。

0328_databricks_02

次に、歯車マークから『Credentials』を選択します。

0328_databricks_03

遷移したページから『Create Credential』を選択し、Storage Credentialを選択してCredential TypeはAWS IAM Roleを選択します。

Credential nameと先に作成したIAMロールのARNを設定してCreateを押します。

0328_databricks_04

作成が完了すると、以下のようにIAMロールの信頼ポリシーを更新するようメッセージが表示されますので、External ID(外部ID)と信頼ポリシーを控えておいて下さい。

0328_databricks_05

IAMロールの更新

DatabricksでCredentialを作成した際に表示された信頼ポリシーで、最初に作成したIAMロールの信頼ポリシーを更新します。

{
 "Version": "2012-10-17",
 "Statement": [
  {
   "Effect": "Allow",
   "Principal": {
    "AWS": [
     "arn:aws:iam::414351767826:role/unity-catalog-prod-UCMasterRole-14S5ZJVKOTYTL",
     "arn:aws:iam::<AWS-ACCOUNT-ID>:role/<AWS-IAM-ROLE-NAME>"
    ]
   },
   "Action": "sts:AssumeRole",
   "Condition": {
    "StringEquals": {
     "sts:ExternalId": "<EXTERNAL-ID>"
    }
   }
  }
 ]
}

外部ロケーションの作成

Databricksのホーム画面に戻り、再度『Catalog』を選択し、歯車マークから今度は『External Locations』を選択します。

0328_databricks_06

開いた画面で『Create external location』を押下します。

Storage Credentialを既に作成しているため、設定は『Manual』を選択します。

0328_databricks_07

External location nameには任意の名前を設定し、対象のS3バケットのURLと作成したStorage credentialを選択し、『Create』を押します。

0328_databricks_08

作成した外部ロケーションで『Test connection』を行い、以下のように表示されれば接続は成功です。

0328_databricks_09

動作検証

S3にデータファイルを配置

ターゲットのS3に sample-data というパスを切り、その中で適当にHive形式でパーティションを切ります。

0328_databricks_10

切ったパーティション内に、以下のようなデータ構造のparquetファイルを格納します。

data.parquet
{"id":1,"name":"Alice","score":90}
{"id":2,"name":"Bob","score":55}

テーブルの作成・確認

Databricksの左タブの『SQL Editor』を選択してクエリエディタを開いた後、以下のクエリを実行します。(以下はLOCATIONとして私のS3バケットのURLを指定しているため、ご自身の環境に合わせ変更して下さい)

CREATE EXTERNAL TABLE sample_data (
  id BIGINT,
  name STRING,
  score BIGINT
)
USING PARQUET
PARTITIONED BY (yyyymmdd STRING)
LOCATION 's3://uehara-databricks-test/sample-data/';

作成が成功すると、以下のようにCatalog配下に作成したテーブルが見れるようになっています。

0328_databricks_11

テーブルのプロパティを確認すると以下のようになっていました。

0328_databricks_12

テーブルをSELECTして確認してみたところ、しっかりデータが表示できました。

0328_databricks_13

最後に

今回は、DatabricksのUnity Catalogを利用してS3のデータを外部テーブルとして読み込んでみました。

参考になりましたら幸いです。

参考文献

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.