【Databricks】ワークスペースを作成してみた

# 背景・目的
こちらの「[Databricksの特徴とアカウント開設の手順を整理した](https://qiita.com/zumax/items/4fe990550bbdc28c1c4b)」では、Databricksの特徴を簡単に整理しましたが、今回はDatabricksのWorkspace（ワークスペース）について整理します。
また、アカウントコンソールでワークスペースの作成も試してみます。

# まとめ
ワークスペースは、下記の特徴があります。
- Databricksのデプロイ単位
- アカウント内に複数のワークスペースを作成可能
- Unity Catalogにより、複数のワークスペースを一元的に管理される
- Databricksのアセットにアクセスするための環境
    - オブジェクトをフォルダで整理可能
    - データオブジェクトとコンピューティングリソースへのアクセスを提供する


## イメージ図
DatabricksのWorkspaceとAWSのリソースは、下記の関係（構成）になるかと思われます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/f7e44e22-863b-55cb-66d7-be915a0cedb1.png)

# 概要
## ワークスペースとは
こちらのDatabricksのドキュメント「[Databricksの概念＞アカウントとワークスペース](https://docs.databricks.com/ja/getting-started/concepts.html#accounts-and-workspaces)」には、下記の記載があります。

> Databricks において、ワークスペースはクラウド内の Databricks デプロイメントであり、チームが Databricks アセットにアクセスするための環境として機能します。組織は、ニーズに応じて、複数のワークスペースを使用するか、ワークスペースを 1 つだけ使用するかを選択できます。
> Databricks アカウントは、複数のワークスペースを含めることができる単一のエンティティです。Unity Catalog が有効なアカウントであれば、アカウント内のすべてのワークスペースにわたって、ユーザーとデータへのアクセスを一元的に管理できます。請求とサポートもアカウントレベルで処理されます。

> ワークスペース は、すべての Databricks 資産にアクセスするための環境です。ワークスペースは、オブジェクト (ノートブック、ライブラリ、ダッシュボード、エクスペリメント) を folders に整理し、データ オブジェクトとコンピューティング リソースへのアクセスを提供します。

整理すると、下記の特徴があるようです。
- Databricksのデプロイ単位
- アカウント内に複数のワークスペースを作成可能
- Unity Catalogにより、複数のワークスペースを一元的に管理される
- Databricksのアセットにアクセスするための環境
    - オブジェクトをフォルダで整理可能
    - データオブジェクトとコンピューティングリソースへのアクセスを提供する

# 実践
[アカウントコンソールを使用したワークスペースの作成](https://docs.databricks.com/ja/administration-guide/workspace/create-workspace.html)を元に試してみます。

## 事前準備
### ワークスペースデプロイ用の IAMロールを作成する
[ワークスペースデプロイ用の IAMロールを作成する](https://docs.databricks.com/ja/administration-guide/account-settings-e2/credentials.html)を元に試します。

クロスアカウント IAMロール for Databricks ワークスペースのデプロイを作成して設定します。 このロールは、コンピュートおよび VPC リソースを作成および管理するために、Databricks に AWS アカウントへの制限付きアクセスを付与します。


#### ステップ 1: クロスアカウント IAM ロールを作成する
1. 事前にDatabricksのアカウントIDを確認しておきます。
1. AWSにサインインし、IAMのナビゲーションで「ロール」を選択します。
1. 「ロールを作成」をクリックします。
1. 下記を番号の順に入力し、「次へ」をクリックします。
    - 信頼されたエンティティタイプの①「AWSアカウント」を選択
    - ②「別のAWSアカウント」を選択
    - ③アカウントIDには、「414351767826」を入力。※Databricksの固定アカウント
    - ④外部IDを要求をチェック
    - ⑤外部IDに、DatabricksのアカウントIDを入力

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/ff60bacc-1f81-4dd0-0468-baf0a649742d.png)

1. アクセス許可は何も選択せずにそのまま「次へ」をクリックします。
1. ロール名を入力し、「ロールを作成」をクリックします。

#### ステップ 2: アクセスポリシーを作成する

1. IAM コンソールの [ロール] セクションで、ステップ 1 で作成した IAMロールをクリックします。
1. 「許可」タブで、「インラインポリシーを作成」をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/a3afa01c-0494-16c2-98a8-2da35af951d8.png)
1. JSONエディタを選択し、下記のポリシーを貼り付け、「次へ」をクリックします。
    ```
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "Stmt1403287045000",
          "Effect": "Allow",
          "Action": [
            "ec2:AllocateAddress",
            "ec2:AssignPrivateIpAddresses",
            "ec2:AssociateDhcpOptions",
            "ec2:AssociateIamInstanceProfile",
            "ec2:AssociateRouteTable",
            "ec2:AttachInternetGateway",
            "ec2:AttachVolume",
            "ec2:AuthorizeSecurityGroupEgress",
            "ec2:AuthorizeSecurityGroupIngress",
            "ec2:CancelSpotInstanceRequests",
            "ec2:CreateDhcpOptions",
            "ec2:CreateFleet",
            "ec2:CreateInternetGateway",
            "ec2:CreateLaunchTemplate",
            "ec2:CreateLaunchTemplateVersion",
            "ec2:CreateNatGateway",
            "ec2:CreateRoute",
            "ec2:CreateRouteTable",
            "ec2:CreateSecurityGroup",
            "ec2:CreateSubnet",
            "ec2:CreateTags",
            "ec2:CreateVolume",
            "ec2:CreateVpc",
            "ec2:CreateVpcEndpoint",
            "ec2:DeleteDhcpOptions",
            "ec2:DeleteFleets",
            "ec2:DeleteInternetGateway",
            "ec2:DeleteLaunchTemplate",
            "ec2:DeleteLaunchTemplateVersions",
            "ec2:DeleteNatGateway",
            "ec2:DeleteRoute",
            "ec2:DeleteRouteTable",
            "ec2:DeleteSecurityGroup",
            "ec2:DeleteSubnet",
            "ec2:DeleteTags",
            "ec2:DeleteVolume",
            "ec2:DeleteVpc",
            "ec2:DeleteVpcEndpoints",
            "ec2:DescribeAvailabilityZones",
            "ec2:DescribeFleetHistory",
            "ec2:DescribeFleetInstances",
            "ec2:DescribeFleets",
            "ec2:DescribeIamInstanceProfileAssociations",
            "ec2:DescribeInstanceStatus",
            "ec2:DescribeInstances",
            "ec2:DescribeInternetGateways",
            "ec2:DescribeLaunchTemplates",
            "ec2:DescribeLaunchTemplateVersions",
            "ec2:DescribeNatGateways",
            "ec2:DescribePrefixLists",
            "ec2:DescribeReservedInstancesOfferings",
            "ec2:DescribeRouteTables",
            "ec2:DescribeSecurityGroups",
            "ec2:DescribeSpotInstanceRequests",
            "ec2:DescribeSpotPriceHistory",
            "ec2:DescribeSubnets",
            "ec2:DescribeVolumes",
            "ec2:DescribeVpcs",
            "ec2:DetachInternetGateway",
            "ec2:DisassociateIamInstanceProfile",
            "ec2:DisassociateRouteTable",
            "ec2:GetLaunchTemplateData",
            "ec2:GetSpotPlacementScores",
            "ec2:ModifyFleet",
            "ec2:ModifyLaunchTemplate",
            "ec2:ModifyVpcAttribute",
            "ec2:ReleaseAddress",
            "ec2:ReplaceIamInstanceProfileAssociation",
            "ec2:RequestSpotInstances",
            "ec2:RevokeSecurityGroupEgress",
            "ec2:RevokeSecurityGroupIngress",
            "ec2:RunInstances",
            "ec2:TerminateInstances"
          ],
          "Resource": [
            "*"
          ]
        },
        {
          "Effect": "Allow",
          "Action": [
            "iam:CreateServiceLinkedRole",
            "iam:PutRolePolicy"
          ],
          "Resource": "arn:aws:iam::*:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot",
          "Condition": {
            "StringLike": {
              "iam:AWSServiceName": "spot.amazonaws.com"
            }
          }
        }
      ]
    }
    ```

1. ポリシーの名前を設定し、「ポリシーの作成」をクリックします。

#### ステップ 3: Databricksで資格情報の構成を作成する
上記で、IAMロールを作成後、そのロールのIDを使用するCredentialを作成しDatabricksに通知できる。

1. Databricksのアカウントコンソールにサインインします。
1. ナビゲーションペインで「クラウドリソース」を選択します。
1. クラウドリソースの画面で「資格情報の設定を追加」をクリックします。
1. 下記を入力し、「追加」をクリックします。
    - ①資格情報の設定名
    - ②ロールARN
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/ef4d4216-3f15-fb86-4583-0af89d5d6f2e.png)


### ワークスペースデプロイ用の S3 バケットを作成する
こちらは、「[ワークスペースデプロイ用の S3 バケットを作成する](https://docs.databricks.com/ja/administration-guide/account-settings-e2/storage.html)」を参考に、作成します。

ここでは、Databricks ワークスペース展開のルート ストレージを作成および構成します。

:::note info
ルートストレージ作成のベストプラクティス

- ワークスペースのデプロイに使用するバケットは、ワークスペースのルートストレージと呼ばれます。 ルートストレージを使用して本番環境顧客データを保存しないこと。
- 本番データ用に追加の S3 バケットまたはその他のデータソースを作成し、オプションでそれらの DBFS マウントポイントを作成する。
- S3 バケットは、Databricks ワークスペースのデプロイと同じ AWS リージョンに存在する必要があります。
- Databricks では、Databricks 専用の S3 バケットを使用し、他のリソースやサービスと共有しないことをお勧めします。
:::

#### ステップ 1: ストレージ設定を作成し、バケットポリシーを生成する

1. Databricsのアカウントコンソールにサインインし、ナビゲーションペインの「クラウドリソース」をクリックします。
1. ①「ストレージ設定」、②「ストレージ設定を追加」をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/a2043d60-2201-179d-d0d8-3d2e649fbe7f.png)

1. 下記を入力し、「ポリシーを生成」をクリックします。
    - ストレージ設定名
    - バケット名
    <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/b0e6e68f-fa42-55d0-1bfc-aff5a29dc802.png" width=500>

1. S3バケットポリシーが表示されるのでコピーします。
    ```
    {
     "Version": "2012-10-17",
     "Statement": [
      {
       "Sid": "Grant Databricks Access",
       "Effect": "Allow",
       "Principal": {
        "AWS": "arn:aws:iam::414351767826:root"
       },
       "Action": [
        "s3:GetObject",
        "s3:GetObjectVersion",
        "s3:PutObject",
        "s3:DeleteObject",
        "s3:ListBucket",
        "s3:GetBucketLocation"
       ],
       "Resource": [
        "arn:aws:s3:::XXXXX/*",
        "arn:aws:s3:::XXXXX"
       ],
       "Condition": {
        "StringEquals": {
         "aws:PrincipalTag/DatabricksAccountId": [
          "XXXXXXXXXXXXX"
         ]
        }
       }
      }
     ]
    }
    ```

1. 「追加」ボタンをクリックします。


#### ステップ 2: 
1. AWSにサインインします。
1. 上記のステップ1でストレージ設定を作成した際に使用した名前でS3バケットを作成します。
1. バケットポリシーを編集し、上記のステップ1でコピーしたポリシーを貼り付けて「変更の保存」をクリックします。


## アカウントコンソールを使用したワークスペースの作成
### カスタム AWS 設定でワークスペースを作成する
[アカウントコンソールを使用したワークスペースの作成](https://docs.databricks.com/ja/administration-guide/workspace/create-workspace.html)を元に試してみます。

1. ナビゲーションペインで「ワークスペース」をクリックします。
    <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/f9a7525d-55f6-4aec-9dae-607a256d58d5.png" width=200>

1. 「カスタムAWS構成」を選択します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/e492cf2c-22bc-938f-ff05-e1b3865e4ca5.png)

1. 下記を設定し、「保存」をクリックします。
    - ワークスペース名：任意の名前
    - リージョン：上記で作成したメタストアのS3バケットと同一リージョン
    - 資格情報の設定：作成した資格情報の設定
    - ストレージ設定：作成したストレージ設定
    - Unity Catalog： 今回は有効化しません。別途試します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/5c8629dc-798c-51a6-88cd-bb8f24e670ca.png)

### ワークスペースの状態を表示する
1. 作成後、ステータスはしばらくの間、Provisioningになります。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/61cdcc2c-4f4f-3323-7bbd-ed479f805725.png)

1. 作成が完了すると「Running」になり、デプロイが完了します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/19e4da56-74c3-ac36-230b-07624f13bc99.png)

### ワークスペースにログインする
1. 作成したワークスペースで「開く」をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/69c2c74c-0c03-e2e5-1d21-683af4848321.png)

1. 別ウィンドウが起動され、作成されたWorkspaceにサインインできたことがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/2f305d80-3fc3-5963-8704-54cb7bd24a8b.png)

# 考察
今回は、ワークスペースを作成してみました。このハンズオンを通してDatabricksアカウントを介してクライアントのVPC（EC2インスタンスを作成する）や、S3バケットへアクセスしていることがわかりました。
今後は、Unity Catalogやワークスペース上でオブジェクトを作成していきたいと思います。

また、作成したワークスペースは異なるドメインになるようです。Databricksのコンソール内でワークスペースを切り替えることができないようです。。（Azureならできるようです。）
そのため、AWS Identy Centerを設定して個別にワークスペースを登録してログインすることも試してみたいです。

# 参考
https://qiita.com/zumax/items/4fe990550bbdc28c1c4b

https://docs.databricks.com/ja/administration-guide/workspace/create-workspace.html

https://docs.databricks.com/ja/administration-guide/account-settings-e2/credentials.html

https://docs.databricks.com/ja/administration-guide/account-settings-e2/storage.html