こんにちは、クラウドインテグレーション事業部の平原です。
皆様は、ネクターというジュースを飲んだことがあるでしょうか?
私はたまにあの濃厚なピーチの味が恋しくなり飲んだりします!特に夏の季節は!!
といったところで今回は、Amazon Athenaとデータソース(RDSやOpenSearchなど)を連携するデータソースコネクターについて記事にします。
AWSサービスのAmazon Athenaをご利用し、濃厚なデータ分析を行っている方もいるかと思います。
Amazon Athenaをご利用の方の参考になればと思います。
はじめに
今回の記事は、データソースコネクターのAthenaMySQLConnector編です。
この記事とは別にOpenSearchと連携するAthenaElasticsearchConnector編も記事にしていますので、そちらも見て頂けると嬉しいです。
使用可能なデータソースコネクターは下記ページが参考になります。 docs.aws.amazon.com
また、参考程度となりますが、CloudFormationテンプレートの記載についても記述します。
データソースコネクターの作成
AWSマネージメントコンソールからデータソースコネクターを作成する方法を記載します。
AWSマネージメントコンソールのAthenaページに遷移する
左ペインのデータソースを選択し、「データソースの作成」をクリックする
"データソースを選択"で、"MySQL"をチェックし、「次へ」をクリックする
"データソースの詳細を入力"で、以下を入力し、「Lambda関数の作成」をクリックする
(AWS Lambdaアプリケーション画面が開く)
・データソース名: 任意の名前
・説明: 任意の説明(入力しなくても良い)AWS Lambdaアプリケーション AthenaMySQLConnectorの"設定とデプロイ"で、"アプリケーションの設定"に以下の様に入力し、「デプロイ」をクリックする
※ データソースコネクターのアプリケーションは、AWS CloudFormationを利用してデプロイされる
・アプリケーション名: AWS CloudFormationスタック名
・SecretNamePrefix: RDSの認証に使用しているAmazon Secrets Managerのシークレット名のプレフィックス
この値が、AWS Lambda関数のIAMロールのポリシーで使用される
例) シークレット名が"test-rds-secret"の場合、ここの値は"test"にする
・SpillBucket: Amazon S3バケット名
Amazon Athenaのクエリ実行が、AWS Lambda関数のTime Out時間を超える場合、一時的に使用されるバケット
・DefaultConnectionString: AWS Lambda関数からRDSに接続する際に使用されるURL
[書式] mysql://jdbc:mysql://<RDSのエンドポイント>/<RDSのDB名>?${<AWS Secrets Manager シークレット名>}
<RDSのエンドポイント>は、RDS Proxyのエンドポイントを指定することが可能
例) mysql://jdbc:mysql://test-mysqlproxy.proxy-xxxxxx123456.ap-northeast-1.rds.amazonaws.com/test_db?${test-rds-secret}
・DisableSpillEncryption: SpillBucketの暗号化を無効とするか否か
"false"の場合、暗号化が有効
・LambdaFunctionName: AWS Lambdaの関数名
・LambdaMemory: AWS Lambdaのメモリサイズ
・LambdaRoleARN: AWS Lambda関数に割り当てるIAMロールのARN
指定しない場合、このデプロイで作成されるIAMロールが割り当てられる
・LambdaTimeout: AWS Lambda関数のTime Out時間
・PermissionsBoundaryARN: AWS Lambda関数に割り当てるIAMロールに設定するPermissionsBoundaryポリシーのARN
・SecurityGroupIds: AWS Lambda関数にアタッチするセキュリティグループのID
・SpillPrefix: SpillBucketが利用される際の保存先プレフィックス
・SubnetIds: AWS Lambda関数が作成されるVPCサブネットのID
・このアプリがカスタム IAM ロールとリソースポリシーを作成することを承認します: チェックするCloudFormationスタック作成後、Amazon Athenaの"データソースの詳細を入力"画面に戻る
"接続の詳細"で、作成したAWS Lambda関数を選択し、「次へ」をクリックする
必要に応じて、更新ボタンをクリック"確認と作成"で、設定内容を確認し「データソースの作成」をクリックする
※ "SecurityGroupIds"や"SubnetIds"から分かるように、AWS Lambda関数はVPC Lambdaとなる
※ AWS Lambda関数は、権限はもちろんだが、ネットワーク的にAWS APIにアクセスできる設定にする必要あり
AWS Lambda関数をPublicサブネットに配置したが、Public IPアドレスが振られておらず"Network Failure"エラーとなり、ハマりました...
データソースコネクター設定後の確認
Amazon Athenaのデータソースコネクター画面にて、一覧から作成したデータソースコネクターをクリックする
"関連付けられたデータベース"で、意図したデータベースが表示されることを確認する
任意のデータベースをクリックし、"関連付けられたテーブル"に意図したテーブルが表示されることを確認する
Amazon Athenaの左ペインよりクエリエディタを選択し、遷移する
上部の"設定"タブにて、クエリ結果の出力先とするS3バケットを設定する
上部の"エディタ"タブにて、"データソース": 作成したデータソース / "データベース": 任意のデータベースを選択する
クエリのテキストに、クエリ文を記載し、「実行」をクリックする
CloudFormation記載例
参考程度ですが、CloudFormationでの記載例を記述します。
(このまま利用してもCloudFormationは成功しません)
AWSTemplateFormatVersion: "2010-09-09" Transform: AWS::Serverless-2016-10-31 Resources: # -------------------------------------------------------------- # Lambda Application: Connector # -------------------------------------------------------------- AthenaMySQLConnector: Type: AWS::Serverless::Application Properties: Location: ApplicationId: arn:aws:serverlessrepo:us-east-1:292517598671:applications/AthenaMySQLConnector # 利用リージョンに関わらず、ここは"us-east-1" SemanticVersion: 2023.25.1 ###### バージョンを指定 Parameters: # The default connection string is used when catalog is "lambda:${LambdaFunctionName}". Catalog specific Connection Strings can be added later. Format: ${DatabaseType}://${NativeJdbcConnectionString}. DefaultConnectionString: 'mysql://jdbc:mysql://<RDSのエンドポイント>/<RDSのDB名>?${!<AWS Secrets Manager シークレット名>}' # If set to 'false' data spilled to S3 is encrypted with AES GCM DisableSpillEncryption: 'false' # This is the name of the lambda function that will be created. This name must satisfy the pattern ^[a-z0-9-_]{1,64}$ LambdaFunctionName: 'test-athena-mysql-connector' # Lambda memory in MB (min 128 - 3008 max). LambdaMemory: '3008' # (Optional) A custom role to be used by the Connector lambda LambdaRoleARN: ' ' # Maximum Lambda invocation runtime in seconds. (min 1 - 900 max) LambdaTimeout: '900' # (Optional) An IAM policy ARN to use as the PermissionsBoundary for the created Lambda function's execution role PermissionsBoundaryARN: ' ' # Used to create resource-based authorization policy for "secretsmanager:GetSecretValue" action. E.g. All Athena MySQL Federation secret names can be prefixed with "AthenaMySQLFederation" and authorization policy will allow "arn:${AWS::Partition}:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:AthenaJdbcFederation*". Parameter value in this case should be "AthenaMySQLFederation". If you do not have a prefix, you can manually update the IAM policy to add allow any secret names. SecretNamePrefix: 'test' # One or more SecurityGroup IDs corresponding to the SecurityGroup that should be applied to the Lambda function. (e.g. sg1,sg2,sg3) SecurityGroupIds: 'sg-xxxxxx' # The name of the bucket where this function can spill data. SpillBucket: 'test-athena-mysql-connector-bucket' # The prefix within SpillBucket where this function can spill data. # SpillPrefix: 'athena-spill' # One or more Subnet IDs corresponding to the Subnet that the Lambda function can use to access you data source. (e.g. subnet1,subnet2) SubnetIds: 'subnet-aaaaaa, subnet-bbbbbb' # -------------------------------------------------------------- # Athena # -------------------------------------------------------------- AthenaMysqlDataCatalog: Type: AWS::Athena::DataCatalog Properties: Name: "test-athena-mysql-datasource" Description: Athena - Aurora Mysql DataSource Parameters: function: !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:test-athena-mysql-connector" Type: "LAMBDA"
※ 下記の部分は、"${}"がテンプレート内のパラメータと判定されない為に、"!"でエスケープしています
DefaultConnectionString: "mysql://jdbc:mysql://<RDSのエンドポイント>/<RDSのDB名>?${!<AWS Secrets Manager シークレット名>}"
さいごに
権限やネットワーク周りで引っかかることはあるかもしれませんが、データソースコネクターの作成自体はそれほど難しくないかなと思います。
ネクターを飲んで、データソースコネクターを利用しようと考えてる方の参考になれば幸いです!