0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

CloudFormationでQuickSightにAthenaのデータセットを作成する

Posted at

はじめに

QuickSightがCloudFormationで操作できるので、AthenaのテーブルをQuickSightで使うには、という内容を試してみました。

参考

構成図

語がたくさん出てきてわからなくなったので、図示してみました。

image.png

構築

環境構築にあたって、2つの部分に分けました。

  • 共通部分
    • 1回構築すればよい部分
    • 個別部分N個に対し、1つでよい部分
      • バケット
        • データ格納
        • 出力先
      • Athenaワークグループ
      • Glueデータベース
  • 個別部分
    • 設定を変えて複数作成を想定する部分
      • Athenaテーブル
      • QuickSight DataSource
      • QuickSight DataSet

1.共通部分の構築

先の図のうち、以下の部分が最初に1回だけ構築する共通部分になります。

image.png

CloudFormationは以下。パラメータEnvを別にすることで、複数の環境が作成できるはずです。

common.yaml
AWSTemplateFormatVersion: '2010-09-09'

Parameters:
  Env:
    Type: String

Resources:
  RawDataBucket:
    Type: AWS::S3::Bucket
    Properties: 
      BucketName: !Sub raw-data-${AWS::AccountId}-${AWS::Region}-${Env}
      BucketEncryption: 
          ServerSideEncryptionConfiguration: 
            - 
              ServerSideEncryptionByDefault: 
                  SSEAlgorithm: 'AES256'
              BucketKeyEnabled: false
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true

  AthenaQueryResultBucket:
    Type: AWS::S3::Bucket
    Properties: 
      BucketName: !Sub query-result-${AWS::AccountId}-${AWS::Region}-${Env}
      BucketEncryption: 
          ServerSideEncryptionConfiguration: 
            - 
              ServerSideEncryptionByDefault: 
                  SSEAlgorithm: 'AES256'
              BucketKeyEnabled: false
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      LifecycleConfiguration: 
        Rules: 
          - 
            Id: 'auto-delete'
            Status: 'Enabled'
            ExpirationInDays: 7

  AthenaWorkGroup:
    Type: AWS::Athena::WorkGroup
    Properties:
      Name: !Sub athena-work-group-${Env}
      RecursiveDeleteOption: true
      WorkGroupConfiguration:
        ResultConfiguration:
          OutputLocation: !Sub s3://${AthenaQueryResultBucket}/data
          EncryptionConfiguration: 
            EncryptionOption: 'SSE_S3'
        EnforceWorkGroupConfiguration: true
        PublishCloudWatchMetricsEnabled: true

  GlueDatabase:
    Type: AWS::Glue::Database
    Properties: 
      CatalogId: !Ref AWS::AccountId  
      DatabaseInput:
        Name: !Sub glue-database-${Env}

Outputs:
  RawDataBucket:
    Value: !Ref RawDataBucket
    Export:
      Name: !Sub "${Env}-RawDataBucket-Name"
  AthenaQueryResultBucket:
    Value: !Ref RawDataBucket
    Export:
      Name: !Sub "${Env}-AthenaQueryResultBucket-Name"
  AthenaWorkGroup:
    Value: !Ref AthenaWorkGroup
    Export:
      Name: !Sub "${Env}-AthenaWorkGroup-Name"
  GlueDatabase:
    Value: !Ref GlueDatabase
    Export:
      Name: !Sub "${Env}-GlueDatabase-Name"
  • RawDataBucket
    • データ格納バケット
    • S3のSSEを設定
    • パブリックアクセスブロックはON
  • AthenaQueryResultBucket
    • Athenaの実行結果を格納するバケット
    • S3のSSEを設定
    • パブリックアクセスブロックはON
    • 7日でファイルを自動削除
  • AthenaWorkGroup
    • 環境専用のAthenaのワークグループ
    • 出力先はAthenaQueryResultBucket
  • GlueDatabase
    • 環境専用のAthenaテーブルを作成するデータベース

注意点ですが、Athenaワークグループ(AthenaWorkGroup)は、実行履歴があると削除時に以下のようなエラーになり、削除できませんでした。

"Invalid request provided: WorkGroup athena-work-group-xxxx is not empty (Service: Athena, Status Code: 400, Request ID: xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, Extended Request ID: null)"

そのため、以下の設定を入れています。

      RecursiveDeleteOption: true

参考のページは以下です。

2.QuickSightからのアクセス許可を設定

作成したバケットの両方に対して、QuickSightからアクセス許可を追加します。
またAthenaにアクセスできるようにもします。
QuickSightの管理画面で設定できます。

image.png

image.png

出力先バケットの場合は、「Athena Workgroupの書き込みアクセス許可」にもチェックを入れてください。

image.png

このあたりの部分もIaC化するのであれば、QuickSightで使用するロールに、自作のロールを使用することができそうです。以下の情報が参考になるかと思います。

3.データを格納

バケットに、Athenaテーブルで読ませたいデータを置きます。
今回は以下のファイルを置きました、社名を揃える用マスタというイメージです。

data\sampleData001.csv
source,destination
ANA,全日本空輸
全日空,全日本空輸
全日本空輸,全日本空輸
data\sampleData002.csv
source,destination
JR東,東日本旅客鉄道株式会社
JR東日本,東日本旅客鉄道株式会社
東日本旅客鉄道株式会社,東日本旅客鉄道株式会社

4.個別部分

Athenaテーブルを作成して、QuickSightに読み込ませる部分です。

each
AWSTemplateFormatVersion: '2010-09-09'

Parameters:
  Env:
    Type: String
  TableName:
    Type: String
    Description: Table name must not contain uppercase characters.
  QuickSightAdminUser:
    Type: String
    Description: user must not be asterisk(*).

Resources:
  # Athena Table
  GlueTable:
    Type: AWS::Glue::Table
    Properties:
      CatalogId: !Ref AWS::AccountId
      DatabaseName:
        Fn::ImportValue:
          !Sub "${Env}-GlueDatabase-Name"
      TableInput:
        Name: !Ref TableName
        TableType: EXTERNAL_TABLE
        Parameters:
          skip.header.line.count: 1
          has_encrypted_data: false
          serialization.encoding: utf-8
          EXTERNAL: true
        StorageDescriptor:
          OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
          Columns:
            - Name: source
              Type: string
            - Name: destination
              Type: string
          InputFormat: org.apache.hadoop.mapred.TextInputFormat
          Location:
            Fn::Join:
              - ''
              - - 's3://'
                - Fn::ImportValue: !Sub "${Env}-RawDataBucket-Name"
                - '/data' 
          SerdeInfo:
            Parameters:
              field.delim: ","
              serialization.format: ","
            SerializationLibrary: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe

  # QuickSight DataSource
  AthenaDataSource:
    Type: AWS::QuickSight::DataSource
    Properties: 
      AwsAccountId: !Ref AWS::AccountId
      Name: !Sub "${Env}-Athena"
      DataSourceId: !Sub "${Env}-Athena-Id"
      Type: ATHENA
      DataSourceParameters:
        AthenaParameters:
          WorkGroup:
            Fn::ImportValue:
              !Sub "${Env}-AthenaWorkGroup-Name"
      Permissions:
        - Actions:
            - quicksight:UpdateDataSourcePermissions
            - quicksight:DescribeDataSource
            - quicksight:DescribeDataSourcePermissions
            - quicksight:PassDataSource
            - quicksight:UpdateDataSource
            - quicksight:DeleteDataSource
          Principal: !Sub arn:aws:quicksight:${AWS::Region}:${AWS::AccountId}:user/default/${QuickSightAdminUser}

  # QuickSight DataSet
  RepDataSet:
    Type: AWS::QuickSight::DataSet
    Properties:
      AwsAccountId: !Ref AWS::AccountId
      Name: !Sub "Select-${GlueTable}"
      DataSetId: !Sub "Select-${GlueTable}-Id"
      ImportMode: SPICE
      PhysicalTableMap:
        rep-physical:
          RelationalTable:
            DataSourceArn: !GetAtt AthenaDataSource.Arn
            # Set Database Name
            Schema: 
              Fn::ImportValue:
                !Sub "${Env}-GlueDatabase-Name"
            # Set Table Name
            Name: !Ref GlueTable
            InputColumns:
              - Name: source
                Type: STRING
              - Name: destination
                Type: STRING
      Permissions:
        - Actions:
            - quicksight:UpdateDataSetPermissions
            - quicksight:DescribeDataSet
            - quicksight:DescribeDataSetPermissions
            - quicksight:PassDataSet
            - quicksight:DescribeIngestion
            - quicksight:ListIngestions
            - quicksight:UpdateDataSet
            - quicksight:DeleteDataSet
            - quicksight:CreateIngestion
            - quicksight:CancelIngestion
          Principal: !Sub arn:aws:quicksight:${AWS::Region}:${AWS::AccountId}:user/default/${QuickSightAdminUser}
  • QuickSightAdminUser
    • DataSourceやDataSetを操作するQuickSightのユーザを指定します
    • "*"だと、エラーになってしまいました。
  • GlueTable
    • Athenaのテーブル定義
    • Locationは、共通部分の出力を参照しています。
    • 注意
      • ColumnsのTypeは小文字
        • 大文字でも作成はされますが、DataSetを作成する箇所で問題になりました。
  • AthenaDataSource
    • AthenaのDataSourceの定義
    • 共通部分で出力したワークグループを参照
  • RepDataSet
    • AthenaのDataSetの定義
    • 無加工であればPhysicalTableMapだけで定義可能
    • RelationalTable.Schemaには、(共通部分で出力した)データベースをセット
    • 注意
      • RelationalTable.InputColumnsのTypeは大文字
        • 小文字だとエラーになります
        • (上で注意した)AthenaのColumnsのTypeを大文字にすると、以下のようなエラーになります。
An error has been thrown from the AWS Athena client. HIVE_METASTORE_ERROR: Error: type expected at the position 0 of 'STRING' but 'STRING' is found.

作成に成功すると、QuickSight上でデータセットが作成され、置いたCSVが確認できます。

image.png

失敗談:削除時のやらかしについて

削除する際に、バケットを削除したあとにQuickSightのアクセス許可を外そうとすると、以下のようなちぐはぐな状態になっていました。

  • QuickSightの管理画面ではアクセス許可の情報が表示されない
  • IAMポリシーではアクセス許可が設定されている

このポリシーをQuickSight管理画面からではなく、直接修正するとQuickSightでは「外部で変更されたため、QuickSightからは編集できません」となり、以降QuickSightからはその部分の設定ができませんでした。
該当のポリシーを削除すれば、再度QuickSightから編集できます。ただし、削除前にどこのバケットに許可していたのかを控えておき、再度設定画面からチェックを入れる羽目になりました。

なので削除時は、操作の手順を正確に逆から行ってください。

おわりに

今回はAthenaを作って、それをQuickSightから読み込ませることを(おおよそ)IaC化しました。
今までQuickSightはGUIでしかできないと思っていましたが、IaC化で標準化が簡単に出来るようになれば、利用シーンが増えるのではないでしょうか。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?