[アップデート] API で非同期な SQL クエリが実行できる!Amazon Redshift で Data API が利用可能になりました

Redshift クラスターへの接続がめっちゃ簡単ですね。
2020.09.12

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

先日のアップデートで Amazon Redshift で Data API が利用可能になりました。

Data API サポートによるメリット

ドライバーが不要!

従来、Redshift クラスターに接続するには JDBC/ODBC といったドライバーを介して SQL クライアントツールで接続していたかと思います。

Data API はその名のとおり API によって SQL ステートメントを実行することが出来ますので、クライアント環境にドライバーのインストールは必要ありません。Amazon EventBridge によるイベントまたはスケジュールをトリガーとして Lambda や AppSync でクエリ、ロード、アンロードといった実装をシンプルに組むことができます。

IAM による接続権限の管理

Data API は IAM 認証または AWS Secrets Manager を利用します。データベース接続のためにユーザごとの認証情報を管理する必要はありません。他の AWS リソース同様に IAM の権限管理によって Redshift クラスターへの接続管理を行うことができます。

非同期処理!

Data API は非同期で動作します。イベントやスケジュールによってトリガーされた SQL ステートメント の結果をあとから取得することが可能です。クエリ結果は 24 時間保存されます。

非同期に処理されるということは、例えば Lambda で大きなデータのアンロードなどを Data API で実行しても API を受け付けたというレスポンスが即時返るだけです。Lambda のタイムアウトも気になりません。あとは Step Functions で定期的に ステートメントのステータスをウォッチし、完了ステータスに変わったら後続処理、といった利用も可能になりそうですね。

対応リージョン

Data API は AWS GovCloud および大阪ローカルリージョンを除く、すべてのリージョンで利用可能です。

Data API における考慮事項

Data API を利用される場合、以下の考慮事項にお気をつけください。

  • クエリの最大期間は 24 時間
  • クエリ結果の最大保持期間は 24 時間
  • クエリ結果の最大サイズは 100 MBです。100 MBを超えるレスポンスデータを返す場合、呼び出しは終了します。
  • クエリステートメントの最大サイズは 100 KB
  • クラスターが VPC 内にあること
  • Data APIは、次のノードタイプの単一ノードおよび複数ノードのクラスターに使用できます
    • dc2.large
    • dc2.8xlarge
    • ds2.xlarge
    • ds2.8xlarge
    • ra3.4xlarge
    • ra3.16xlarge

やってみる

検証環境

今回は以下の環境で検証しています。

  • 東京リージョン
  • クラスター: dc2.large 単一ノード

Secrets Manager に認証情報を登録

今回は Secrets Manager を使って Data API を実行しますので、まず認証情報を登録します。

Secrets Manager の管理コンソールを開き [新しいシークレットを保存する] をクリックします。シークレットの種類は [Redshiftクラスターの認証情報] を選択し、ユーザー名およびパスワードを入力します。シークレットがアクセスする Redshift クラスターを選択し、[次]へ。

シークレット名およびタグのキーに RedshiftDataFullAccess を指定し、[次]へ。

AWS 管理ポリシー AmazonRedshiftDataFullAccess を利用する場合は、タグキーに RedshiftDataFullAccess が付与されているシークレットのみ secretsmanager:GetSecretValue アクションが許可されています。別途ポリシーを作成し、タグベースの権限管理を利用しない場合は設定不要です。

AmazonRedshiftDataFullAccess ポリシー(一部抜粋)

{
     "Sid": "SecretsManagerPermissions",
     "Action": [
         "secretsmanager:GetSecretValue"
     ],
     "Effect": "Allow",
     "Resource": "*",
     "Condition": {
         "StringLike": {
             "secretsmanager:ResourceTag/RedshiftDataFullAccess": "*"
         }
     }
},

今回は特に指定しませんが、シークレット側でリソースポリシーを設定しアクセス管理することも可能です。

必要に応じてシークレットを自動ローテーションすることも可能ですが、今回は無効のまま [次] へ進み、[保存] します。

Data API で SQL を実行

今回は AWS CLI を使用します。AWS CLI は執筆時点の最新バージョンにアップデートしています。また、実行環境の IAM ロールには AmazonRedshiftDataFullAccess ポリシーのみをアタッチしています。

$ aws --version
aws-cli/2.0.48 Python/3.7.3 Linux/4.14.193-149.317.amzn2.x86_64 exe/x86_64.amzn.2

Data API for Redshift では「Data API を有効化する」といった操作は必要ないようです。クラスターを作成すると自動的に Data API 用のエンドポイントが利用可能でした。(Data API for Aurora Serverless では有効化/無効化を選択できます)

SQL ステートメントの実行

SQL ステートメントの実行は aws redshift-data execute-statement を使用します。--secret は先程作成したシークレットの ARN を指定し、--sql で実行したい SQL クエリを記述します。

また Data API は非同期であるためコマンドのレスポンスは API 実行に対するレスポンスであって、SQL クエリの実行結果ではないことに注目ください。

$ aws redshift-data execute-statement ¥
    --secret arn:aws:secretsmanager:ap-northeast-1:12345678901:secret:data-api-5LCD8Q ¥
    --cluster-identifier redshift-cluster-1 ¥
    --sql "select * from stl_query limit 1" ¥
    --database dev 

ClusterIdentifier: redshift-cluster-1
CreatedAt: '2020-09-11T17:01:41.171000+00:00'
Database: dev
Id: b9ffc607-9cce-4283-839b-c64ae21e2931
SecretArn: arn:aws:secretsmanager:ap-northeast-1:12345678901:secret:data-api-5LCD8Q

SQL ステートメントの一覧

実行した SQL ステートメントに関する一覧は aws redshift-data list-statements で表示できます。実行結果はこの Id を使って取得します。

$ aws redshift-data list-statements --status ALL
Statements:
- CreatedAt: '2020-09-11T16:50:23.351000+00:00'
  Id: f00188ec-e89d-491c-80d5-2444503a6cb2
  QueryString: select * from stl_query limit 1
  SecretArn: arn:aws:secretsmanager:ap-northeast-1:12345678901:secret:data-api-5LCD8Q
  Status: FINISHED
  UpdatedAt: '2020-09-11T16:50:25.030000+00:00'
- CreatedAt: '2020-09-11T17:01:41.171000+00:00'
  Id: b9ffc607-9cce-4283-839b-c64ae21e2931
  QueryString: select * from stl_query limit 1
  SecretArn: arn:aws:secretsmanager:ap-northeast-1:12345678901:secret:data-api-5LCD8Q
  Status: FINISHED
  UpdatedAt: '2020-09-11T17:01:42.052000+00:00'

SQL ステートメントの結果取得

SQL ステートメントの実行結果を取得するには aws redshift-data get-statement-result に SQL ステートメントの ID を指定します。

$ aws redshift-data get-statement-result --id b9ffc607-9cce-4283-839b-c64ae21e2931
ColumnMetadata:
- isCaseSensitive: false
  isCurrency: false
  isSigned: true
  label: userid
  length: 0
  name: userid
  nullable: 0
  precision: 10
  scale: 0
  schemaName: pg_catalog
  tableName: stll_query
  typeName: int4
(後略)

CloudTrail に記録されること、されないこと

Data API へのリクエストは CloudTrail に記録されます。誰が Data API を使って、いつ、どのステートメントを実行したか知ることが出来ます。ただし --sql の内容は ***OMITTED*** という形式でマスキングされるため CloudTrail で SQL クエリを知ることは出来ないようです。

{
    "eventVersion": "1.05",
    "userIdentity": {
        "type": "AssumedRole",
        "principalId": "AROXXXXXXXXXXXXXXXXXX:i-00f8d3102bd7cabb9",
        "arn": "arn:aws:sts::012345678901:assumed-role/dataapi/i-00f8d3102bd7cabb9",
        "accountId": "012345678901",
        "accessKeyId": "ASIXXXXXXXXXXXXXXXXXX",
        "sessionContext": {
            "sessionIssuer": {
                "type": "Role",
                "principalId": "AROXXXXXXXXXXXXXXXXXX",
                "arn": "arn:aws:iam::012345678901:role/dataapi",
                "accountId": "012345678901",
                "userName": "dataapi"
            },
            "webIdFederationData": {},
            "attributes": {
                "mfaAuthenticated": "false",
                "creationDate": "2020-09-11T16:37:39Z"
            },
            "ec2RoleDelivery": "2.0"
        }
    },
    "eventTime": "2020-09-11T16:50:24Z",
    "eventSource": "redshift-data.amazonaws.com",
    "eventName": "ExecuteStatement",
    "awsRegion": "ap-northeast-1",
    "sourceIPAddress": "AWS Internal",
    "userAgent": "aws-cli/2.0.48 Python/3.7.3 Linux/4.14.193-149.317.amzn2.x86_64 exe/x86_64.amzn.2 command/redshift-data.execute-statement",
    "requestParameters": {
        "clusterIdentifier": "redshift-cluster-1",
        "database": "dev",
        "secretArn": "arn:aws:secretsmanager:ap-northeast-1:012345678901:secret:data-api-5LCD8Q",
        "sql": "***OMITTED***"
    },
    "responseElements": {
        "clusterIdentifier": "redshift-cluster-1",
        "createdAt": "Sep 11, 2020 4:50:23 PM",
        "database": "dev",
        "id": "f00188ec-e89d-491c-80d5-2444503a6cb2",
        "secretArn": "arn:aws:secretsmanager:ap-northeast-1:012345678901:secret:data-api-5LCD8Q"
    },
    "requestID": "78e7fe0b-68c6-4f51-ac8a-89b09adb3f31",
    "eventID": "77926415-834c-44ea-82f5-5d3882b75bd3",
    "readOnly": false,
    "eventType": "AwsApiCall",
    "recipientAccountId": "012345678901"
}

簡単ではありますが、検証は以上です!

さいごに

ついに Redshift にも Data API が来ましたね。ドライバーのインストールが不要で、認証情報の管理もシンプルなので非常に簡単に Redshift クラスターの SQL クライアント環境が準備できます。

Data API といえば Aurora Serverless が一足先に対応しています。Data API for Aurora Serverless は同期的に処理されるのに対して、Data API for Redshift は非同期的に処理される点はお気をつけください!

以上!大阪オフィスの丸毛(@marumo1981)でした!