Kinesis Data Streams が サポートした新機能「DryRun」を試してみた

Kinesis Data Streams が サポートした新機能「DryRun」を試してみた

Amazon Kinesis Data Streams の DryRun を、権限の異なる IAM ロール3つで試しました。CloudFormation で 1 シャードのストリームを作成し、権限とリクエストパラメータの検証、スロットリング時の応答、実行後にストリームが空のままかを確認しました。
2026.09.03

はじめに

2026-09-01 に、Amazon Kinesis Data Streams が DryRun をサポートしました。データの読み書きを一切行わず、リクエストが成功するかどうかだけを確認できるパラメータです。

https://aws.amazon.com/about-aws/whats-new/2026/09/amazon-kinesis-data-streams-api/

https://docs.aws.amazon.com/streams/latest/dev/kds-dryrun-validation.html

項目 以前 今回
権限検証の方法 意図的に失敗させるリクエスト(ペイロードを上限超えにする等)を送信する必要があった DryRun を指定するだけで検証できる
誤書き込みのリスク サービス制限が変更されると「失敗前提のリクエスト」が意図せず成功し、本番ストリームにレコードが書き込まれるリスクがあった ドライランは一切のデータ読み書きを行わないため誤書き込みのリスクがない
成功時のレスポンス DryRun パラメータ自体が存在しない DryRunOperationException(HTTP 400)が返り、成功するはずだったことを示す

本記事では、権限とリクエストパラメータの妥当性、スロットリング時の応答、実行後のストリームの状態を確認しました。

検証内容

開発者ガイドによると、DryRun が検証するのは IAM 権限、リクエストパラメータの妥当性、対象リソースの存在の3点です。対応する API は PutRecord、PutRecords、GetRecords、GetShardIterator、SubscribeToShard の5つです。

検証環境

DryRun フラグを指定できるかどうかは、AWS CLI のバージョンに依存します。検証に使った aws-cli/2.36.38 では、aws kinesis put-record のヘルプに [--dry-run | --no-dry-run] があります。リージョンは ap-northeast-1 です。

CloudFormation で、1 シャードのプロビジョンドモードのストリーム1本と、IAM ロール3つを作成しました。kds-dryrun-allow-role にはデータプレーンの操作を許可しました。kds-dryrun-deny-role に許可したのは DescribeStreamSummary と ListShards だけです。kds-dryrun-partial-role には読み取り系だけを許可しました。名前付き IAM ロールを作成するため、デプロイでは CAPABILITY_NAMED_IAM を指定します。

検証環境の CloudFormation テンプレート
AWSTemplateFormatVersion: '2010-09-09'
Description: Verification environment for Kinesis Data Streams DryRun parameter.

Parameters:
  TrustedPrincipalArn:
    Type: String
    AllowedPattern: '^arn:aws:iam::\d{12}:(role|user)/.+$'
  StreamName:
    Type: String
    Default: kds-dryrun-test
    AllowedPattern: '^[a-zA-Z0-9_.-]+$'

Resources:
  TestStream:
    Type: AWS::Kinesis::Stream
    Properties:
      Name: !Ref StreamName
      StreamModeDetails:
        StreamMode: PROVISIONED
      ShardCount: 1
      RetentionPeriodHours: 24

  AllowRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: kds-dryrun-allow-role
      MaxSessionDuration: 3600
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Ref TrustedPrincipalArn
            Action: sts:AssumeRole
      Policies:
        - PolicyName: kds-dataplane-allow
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - kinesis:PutRecord
                  - kinesis:PutRecords
                  - kinesis:GetRecords
                  - kinesis:GetShardIterator
                  - kinesis:DescribeStream
                  - kinesis:DescribeStreamSummary
                  - kinesis:ListShards
                Resource: !GetAtt TestStream.Arn

  DenyRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: kds-dryrun-deny-role
      MaxSessionDuration: 3600
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Ref TrustedPrincipalArn
            Action: sts:AssumeRole
      Policies:
        - PolicyName: kds-describe-only
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - kinesis:DescribeStreamSummary
                  - kinesis:ListShards
                Resource: !GetAtt TestStream.Arn

  PartialRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: kds-dryrun-partial-role
      MaxSessionDuration: 3600
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Ref TrustedPrincipalArn
            Action: sts:AssumeRole
      Policies:
        - PolicyName: kds-reader-only
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - kinesis:GetShardIterator
                  - kinesis:GetRecords
                  - kinesis:DescribeStreamSummary
                  - kinesis:ListShards
                Resource: !GetAtt TestStream.Arn

Outputs:
  StreamArn:
    Value: !GetAtt TestStream.Arn
  AllowRoleArn:
    Value: !GetAtt AllowRole.Arn
  DenyRoleArn:
    Value: !GetAtt DenyRole.Arn
  PartialRoleArn:
    Value: !GetAtt PartialRole.Arn
aws cloudformation deploy \
    --template-file template.yaml \
    --stack-name kds-dryrun-verify \
    --capabilities CAPABILITY_NAMED_IAM \
    --parameter-overrides TrustedPrincipalArn=arn:aws:iam::123456789012:role/example-role \
    --region ap-northeast-1

コマンド実行直前は 2026-09-03T01:30:57Z、スタック作成完了で CLI が復帰したのは 01:32:04Z で、所要時間は 67 秒でした。5 秒間隔のポーリングで StreamStatus が ACTIVE を返した最初の確認は 01:32:13Z で、コマンド実行直前から 76 秒後でした。

今回の検証では、スタック作成完了から 32 秒後の 01:32:36Z に AssumeRole して実行した DryRun が成功し、IAM ロールの伝播を待たずに実行できました。

権限別の検証は、それぞれのロールを引き受けて実行しました。一時的な認証情報は環境変数として渡し、ファイルには書いていません。テンプレートの信頼ポリシーは指定した1つのプリンシパルだけを許可しているため、別のロールへ切り替える前に環境変数を解除します。

unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN

CREDS=$(aws sts assume-role \
    --role-arn arn:aws:iam::123456789012:role/kds-dryrun-allow-role \
    --role-session-name dryrun-test \
    --query Credentials --output json)

export AWS_ACCESS_KEY_ID=$(jq -r .AccessKeyId <<<"$CREDS")
export AWS_SECRET_ACCESS_KEY=$(jq -r .SecretAccessKey <<<"$CREDS")
export AWS_SESSION_TOKEN=$(jq -r .SessionToken <<<"$CREDS")

検証が終わったらスタックを削除します。削除するまでシャード時間が課金されます。

aws cloudformation delete-stack --stack-name kds-dryrun-verify --region ap-northeast-1
aws cloudformation wait stack-delete-complete --stack-name kds-dryrun-verify --region ap-northeast-1

削除は 01:50:13Z に開始し、完了の待機を含めて 01:50:44Z に終わりました(31 秒)。

権限の検証

3つのロールで PutRecord に DryRun を付けて実行し、読み取り系だけを許可したロールでは GetShardIterator も試しました。まず、データプレーンの操作を許可したロールでの PutRecord です。

$ aws kinesis put-record \
    --stream-name kds-dryrun-test \
    --data aGVsbG8= --cli-binary-format base64 \
    --partition-key fixed-key \
    --dry-run --region ap-northeast-1

aws: [ERROR]: An error occurred (DryRunOperationException) when calling the PutRecord operation: DryRunOperation validation succeeded while calling PutRecord operation.: Request would have succeeded, but DryRun flag is set.

検証が通ったときも CLI はエラーとして出力し、終了コードは 254 でした。

次に、同じコマンドを、DescribeStreamSummary と ListShards だけを許可したロールでも実行しました。

aws: [ERROR]: An error occurred (AccessDeniedException) when calling the PutRecord operation: User: arn:aws:sts::123456789012:assumed-role/kds-dryrun-deny-role/dryrun-test is not authorized to perform: kinesis:PutRecord on resource: arn:aws:kinesis:ap-northeast-1:123456789012:stream/kds-dryrun-test because no identity-based policy allows the kinesis:PutRecord action

拒否されたときの終了コードも 254 でした。成功・失敗を終了コードでは判定できず、例外の種類で見分ける必要があります。

同じロールで DescribeStreamSummary を実行しました。

{
    "StreamDescriptionSummary": {
        "StreamName": "kds-dryrun-test",
        "StreamARN": "arn:aws:kinesis:ap-northeast-1:123456789012:stream/kds-dryrun-test",
        "StreamStatus": "ACTIVE",
        "StreamModeDetails": {
            "StreamMode": "PROVISIONED"
        },
        "RetentionPeriodHours": 24,
        "EncryptionType": "NONE",
        "OpenShardCount": 1,
        "ConsumerCount": 0,
        "MaxRecordSizeInKiB": 1024
    }
}

DescribeStreamSummary が通っているため、先の拒否はロール自体が利用できないのではなく、PutRecord の権限不足によるものです。

読み取り系だけを許可したロールで GetShardIterator に DryRun を付けると、DryRunOperationException が返り、検証に成功しました。

aws kinesis get-shard-iterator \
    --stream-name kds-dryrun-test \
    --shard-id shardId-000000000000 \
    --shard-iterator-type TRIM_HORIZON \
    --dry-run --region ap-northeast-1

同じロールの PutRecord では AccessDeniedException が返りました。同一のストリームに対する結果なので、判定はストリーム単位ではなく API アクション単位です。

なお、開発者ガイドには DryRun で検証されない権限の記載があります。カスタマーマネージド KMS キーで暗号化したストリームの kms:GenerateDataKey と kms:Decrypt です。

パラメータの検証

リクエストパラメータの妥当性がどう扱われるかを、レコードサイズの上限で確認しました。ペイロードは 1 MiB ちょうどと 1 MiB + 1 バイトの2つを用意しました。

head -c 1048576 /dev/zero | tr '\0' 'a' > payload-1mib.bin
head -c 1048577 /dev/zero | tr '\0' 'a' > payload-over1mib.bin

1,048,577 バイトのペイロードで DryRun を実行すると、次のエラーが返りました。

aws kinesis put-record \
    --stream-name kds-dryrun-test \
    --data fileb://payload-over1mib.bin \
    --partition-key fixed-key \
    --dry-run --region ap-northeast-1
{"__type":"ValidationException","message":"1 validation error detected: Value at 'data' failed to satisfy constraint: Member must have length less than or equal to 1048576"}

1,048,576 バイトでは DryRunOperationException が返り、検証は成功しました。エラーメッセージが示す制約値は 1048576 で、同じストリームの MaxRecordSizeInKiB は 1024 でした。--debug で採取したレスポンスヘッダに x-amzn-RequestId が含まれており、サービス側の判定であることを確認しました。

API リファレンスの PutRecord には、Data の Length Constraints が記載されています。値は Minimum length of 0. Maximum length of 10485760. です。冒頭には最大レコードサイズ 10 MiB とあります(2026-09-03 参照)。今回のストリームで返った値は 1048576 でした。

スロットリング

開発者ガイドには、DryRun に専用のスロットル上限があると記載されています。

Requests with DryRun enabled are subject to a dedicated throttle limit of 1 transaction per second (TPS) per stream, separate from the stream's normal per-shard throughput limits. This limit is shared across all supported dry-run APIs (PutRecord, PutRecords, GetRecords, GetShardIterator, and SubscribeToShard) on the same stream. If you exceed this limit, the API returns a ThrottlingException.

実際の挙動を確認するため、5 バイトのレコードを 60 リクエスト、並列 12 で投入しました。DryRun の有無だけを変えて1回ずつ実行し、AWS_MAX_ATTEMPTS=1 で CLI の自動リトライを無効にしました。

export AWS_MAX_ATTEMPTS=1

seq 1 60 | xargs -P 12 -I{} aws kinesis put-record \
    --stream-name kds-dryrun-test \
    --data aGVsbG8= --cli-binary-format base64 \
    --partition-key fixed-key \
    --dry-run --region ap-northeast-1
実行 結果 経過
DryRun なし 60 件すべて成功 01:42:21.595Z 〜 01:42:26.990Z
DryRun あり 32 件が DryRunOperationException、28 件が ProvisionedThroughputExceededException 01:43:56.992Z 〜 01:44:02.241Z

同じ条件でも、DryRun を付けた側だけがスロットリングされました。開発者ガイドに記載された ThrottlingException は今回の検証では一度も観測せず、代わりに ProvisionedThroughputExceededException が返りました。

5 バイトのレコードで DryRun を 60 回逐次実行した場合も、スロットリングが発生しました(01:47:21.429Z 〜 01:47:46.045Z)。この試行では 50 件が DryRunOperationException、10 件が ProvisionedThroughputExceededException でした。初めてスロットリングされたのは 15 回目でした。

ProvisionedThroughputExceededException は、DryRun を付けない実書き込みでも返ります。1 MiB のレコードを 24 リクエスト、並列 8 で投入しました。16 件が成功し、8 件が ProvisionedThroughputExceededException でした(01:40:29.428Z 〜 01:40:31.873Z)。スクリプトがリクエストごとに記録した完了時刻は、01:40:30 台が 14 件、01:40:31 台が 2 件でした。例外名だけでは、DryRun 由来かどうかを判断できません。

並列投入に使ったスクリプト
#!/usr/bin/env bash
STREAM=kds-dryrun-test
REGION=ap-northeast-1
PAYLOAD=payload-1mib.bin
COUNT="${1:-24}"
PARALLEL="${2:-8}"
export AWS_MAX_ATTEMPTS=1  # CLI 側の自動リトライを無効にして生の応答を観測する

seq 1 "$COUNT" | xargs -P "$PARALLEL" -I{} \
    aws kinesis put-record \
        --stream-name "$STREAM" \
        --data "fileb://$PAYLOAD" \
        --partition-key "key-{}" \
        --region "$REGION"

上記の実行は、リクエスト数 24、並列数 8 を引数に指定したものです。

1 MiB のレコードを 1 秒間隔で 20 回投入した場合は、20 件すべて成功し、スロットリングは発生しませんでした(01:49:26.356Z 〜 01:49:57.876Z)。この試行は、前の試行から 60 秒空けてから開始しています。

副作用の確認

ここまでの検証で DryRun を計 176 回実行した後、実書き込みを行う前の 01:40:05Z に TRIM_HORIZON から get-records を3回連続で実行しました。

{
  "RecordCount": 0,
  "MillisBehindLatest": 0,
  "Records": []
}

3 回とも同じ結果で、ストリームにレコードは1件もありませんでした。スロットリング節の実行は、いずれもこの確認より後に行いました。

料金

DryRun の利用に追加料金はありません。DryRun を有効にしたリクエストも、無効にした同等のリクエストと同じように課金されます。PutRecord と PutRecords は、プロビジョンドモードでは入力ペイロードサイズに基づいて課金され、ストリームとシャード時間の料金は通常どおり適用されます(開発者ガイド)。

プロビジョンドモードの課金単位は、シャード時間と 25 KB 単位の PUT ペイロードユニットです。料金ページの US East の計算例では、1 シャードあたり $0.015/時間、PUT ペイロードユニットは 100 万ユニットあたり $0.014 です。権限確認を繰り返し実行する場合も、実書き込みと同じ課金が発生します。

まとめ

Kinesis Data Streams の DryRun により、プロビジョンドモードのストリームでレコードを書かないまま検証できるようになりました。IAM 権限とリクエストパラメータが通るかどうかを、API アクション単位で確認できます。確認のためのテストデータがストリームに残りません。

Kinesis Data Streams には、書き込んだレコードを個別に削除する操作がありません。保持期間が過ぎるまで残るため、権限確認のために投入したテストデータはストリームのノイズになることがあります。IAM ポリシーを最小権限へ絞り込み、その結果を確かめたい場面で、今回サポートされた DryRun を試してみてください。

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事