S3 Tablesを利用するAWSアーキテクチャ構築：Athena


# はじめに
本記事は、以下記事の続きです。

https://qiita.com/tamabe/private/d590444037e6d29f836e

今回は、S3テーブルにAthenaから接続し、SQLクエリを実行してデータが返ってくるまでを確認します。
以下AWS公式記事の手順を参考にしています。

https://docs.aws.amazon.com/athena/latest/ug/gdc-register-s3-table-bucket-cat.html


# 構成図
最終的な構成図は以下です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618752/9b886697-7590-1ed3-7dda-f318ef900e41.png)


本記事では **AthenaからS3 Tablesバケットをクエリする** 部分を実装します。



# 実装手順
以下ステップで実装していきます。
ステップ3～5では、権限管理でLake Formationも出てきます。
本記事では **4. Athenaからクエリ実行** のステップを行っていきます。

1. [S3テーブルバケットを作成](https://qiita.com/tamabe/items/8c459d2434f20191ac3e)
1. [EMRからスキーマ作成](https://qiita.com/tamabe/items/533d1b812de4adf4ec89)
2. [Firehoseからデータ送信](https://qiita.com/tamabe/items/d590444037e6d29f836e)
2. [Athenaからクエリ実行](https://qiita.com/tamabe/items/1c35ced1fee7bad9dc6e)
2. [QuickSightからデータセット接続](https://qiita.com/tamabe/items/1c7e299c13e92a3a61d8)




# Athenaからクエリ実行手順
以下ステップで行います。

1. [Athena用IAMロール ポリシー設定](#athena用iamロール-ポリシー設定)
2. [Lake Formationから権限設定](#lake-formationから権限設定)
2. [Athenaからクエリ実行](#athenaからクエリ実行)



# Athena用IAMロール ポリシー設定
まず、Athena用のカスタムポリシー[^16][^14][^15]を作成します。
コンソール操作：
「IAMコンソール」 → 「ポリシー」 → 「ポリシーの作成」 → 「ポリシーエディタ: JSON」

以下JSONを貼り付け → 次へ → 任意のポリシー名設定 → ポリシーの作成
※特に **"Sid": "DataCatalogPermissions"の"Resource"記述** 部分にクセがあります・！
```json:Athena用ポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DataCatalogPermissions",
            "Effect": "Allow",
            "Action": [
				"glue:GetCatalog",
                "glue:GetDatabase",
				"glue:GetDatabases",
				"glue:GetTables",
				"glue:GetTable"
            ],
            "Resource": [
                "arn:aws:glue:ap-northeast-1:<アカウントID>:catalog",
                "arn:aws:glue:ap-northeast-1:<アカウントID>:catalog/s3tablescatalog",
                "arn:aws:glue:ap-northeast-1:<アカウントID>:catalog/s3tablescatalog/*",
				"arn:aws:glue:ap-northeast-1:<アカウントID>:database/s3tablescatalog/<S3テーブルバケット名>/<S3テーブル名前空間>",
				"arn:aws:glue:ap-northeast-1:<アカウントID>:table/s3tablescatalog/<S3テーブルバケット名>/<S3テーブル名前空間>/<S3テーブルバケット内のテーブル名>"   
            ]
        },
        {
            "Sid": "BaseAthenaPermissions",
            "Effect": "Allow",
            "Action": [
                "athena:*"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Sid": "ListObjectsInBucket",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::<クエリ結果保存用S3バケット>"
            ]
        },
        {
            "Sid": "BaseS3BucketPermissions",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetBucketLocation",
                "s3:ListAllMyBuckets"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Sid": "BaseQueryResultsPermissions",
            "Effect": "Allow",
            "Action": [
                "s3:GetBucketLocation",
                "s3:GetObject",
                "s3:ListBucket",
                "s3:ListBucketMultipartUploads",
                "s3:ListMultipartUploadParts",
                "s3:AbortMultipartUpload",
                "s3:CreateBucket",
                "s3:PutObject",
                "s3:PutBucketPublicAccessBlock"
            ],
            "Resource": [
                "arn:aws:s3:::<クエリ結果保存用S3バケット>*"
            ]
        }
    ]
}
```


次に、Athena用のサービスロールを作成します。
コンソール操作：
「IAMコンソール」 → 「ロール」 → 「ロールを作成」

今回、「カスタム信頼ポリシー」 → 以下JSONを貼り付けて「次へ」
※**Athenaコンソールからクエリ実行する自身のIAMユーザーを"Principal"に追加**します。

```json:Athena用ロールに対するカスタム信頼ポリシー
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<アカウントID>:user/<ユーザー名>"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```


「許可ポリシー」に、先ほど作成したAthena用ポリシーを選択して「次へ」

任意のロール名を設定 → 「ロールを作成」





# Lake Formationから権限設定
Athena は、**S3テーブル名前空間** 経由で接続します。
Lake Formationから、Athena用ロールに権限を付与します。
※**S3テーブルバケット内テーブルへのSuper(ALL)権限**を付与します。

コンソールから操作：
Lake Formationコンソール → Databasesタブ

以下の通り、
Choose catalogで、「<アカウントID>:s3tablescatalog/<S3テーブルバケット名>」を選択し、
アクセス先となる「S3テーブル名前空間」を選択します。
この状態で、Actions → Grant

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618752/c46ffd86-78d4-228a-01df-86e966c39f19.png)


以下の通り、Athena用ロールに、S3テーブルバケットの指定テーブルへのSuper(ALL)権限を付与します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618752/dc3feab4-5b95-228e-25a4-7f54b6233d05.png)




# Athenaからクエリ実行

Athena用ロールへの権限設定ができたので、Athenaコンソールからクエリを実行します。

## スイッチロール
ここで、先程作成したAthena用ロールにスイッチロールしてみます。

コンソールから操作：
右上のIAMユーザー名クリック → ロールの切り替え
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618752/6bfaf0f1-5ef4-b3e8-c274-f820882a913b.png)

Athena用ロール情報を入力して「ロールの切り替え」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618752/c4de0f0b-8b6b-7cb8-a074-331607d96047.png)


## SQLクエリ実行
コンソールから操作：
Athenaコンソール → クエリエディタ

以下SQLを貼り付けて、「実行する」

```sql:
SELECT * FROM "s3tablescatalog/<S3テーブルバケット名>"."<S3テーブル名前空間>"."<S3テーブルバケット内のテーブル名>" limit 10;
```


## クエリ結果
実行後しばらくすると以下出力を確認できました！
※[前回記事](https://qiita.com/tamabe/private/d590444037e6d29f836e) でS3テーブルバケット内に格納したデータが出力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618752/d8403e44-4db3-0f5c-69e7-05f302f01f39.png)




# 最後に
ここまでで、S3テーブルバケットにクエリ実行するところまで確認しました。
次回記事では、このS3テーブルバケットに、QuickSightで接続するまでの設定を確認します。

https://qiita.com/tamabe/items/1c7e299c13e92a3a61d8



# 参考URL
この記事で参考にしたURLです。
[^16]:AWS記事：Amazon Athena の AWS 管理ポリシー
https://docs.aws.amazon.com/ja_jp/athena/latest/ug/managed-policies.html

[^15]:AWS記事：AWS Glue Data Catalog のデータベースとテーブルへのアクセスを構成する
https://docs.aws.amazon.com/ja_jp/athena/latest/ug/fine-grained-access-to-glue-resources.html

[^14]:AWS記事：Athena から Amazon S3 へのアクセスを制御する
https://docs.aws.amazon.com/ja_jp/athena/latest/ug/s3-permissions.html

[^13]:AWS記事：Route incoming records to a single Iceberg table
https://docs.aws.amazon.com/firehose/latest/dev/apache-iceberg-format-input-record.html

[^12]:AWS記事：Grant Lake Formation permissions on your table resources
https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-integrating-aws.html#grant-permissions-tables

[^1]:AWS記事：Amazon S3 table bucket, table, and namespace naming rules
https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-buckets-naming.html

[^2]:AWS CLI Command Reference：s3tables
https://docs.aws.amazon.com/cli/latest/reference/s3tables/

[^3]:AWS記事：Accessing Amazon S3 tables with Amazon EMR
https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-integrating-emr.html

[^4]:AWS記事：Querying Amazon S3 tables with Apache Spark
https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-integrating-open-source-spark.html

[^5]:AWS記事：Streaming data to tables with Amazon Data Firehose
https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-integrating-firehose.html

[^6]:AWS記事：Register S3 table bucket catalogs in Athena
https://docs.aws.amazon.com/athena/latest/ug/gdc-register-s3-table-bucket-cat.html

[^7]:AWS記事：Visualizing table data with Amazon QuickSight
https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-integrating-quicksight.html

[^8]:AWS記事：Using Amazon S3 Tables with AWS analytics services #Grant Lake Formation permissions on your table resources
https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-integrating-aws.html#grant-permissions-tables

[^9]:AWS記事：Using Amazon S3 Tables with AWS analytics services
https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-integrating-aws.html

[^10]:AWS記事：Use an Iceberg cluster with Spark
https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-iceberg-use-spark-cluster.html#emr-iceberg-create-cluster

[^11]:AWS記事：Connect to the Amazon EMR cluster primary node using SSH
https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-connect-master-node-ssh.html