Amazon Redshift Serverless ワークグループで指定した RPU によって配置可能なサブネットのサイズが変わる

Amazon Redshift Serverless はそれなりの数の ENI を生成します。RPU を MAX の 512 割り当てる場合、少なくとも /24 以上のサブネットが 3 つ必要そうです。

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


2022/11/15追記

公式ドキュメントに必要なサブネットサイズについて追記されていました。こちらの内容を正として最新の情報をご確認ください。

以降の記述は、公式の記述がなかった当時のアレコレの奮闘としてお楽しみください。


IP アドレスが足りなくて Redshift Serverless を作成できない!

コンバンハ、千葉(幸)です。

Amazon Redshift Serverless ワークグループを作成しようとした際に、以下のエラーが発生したことがありました。

Insufficient free IP addresses found in subnets: [subnet-xxxxxxxxx].

▲ 作ろうと思ったのに……の図

配置先として指定したサブネットに十分な IP アドレスがない、ということで怒られているようです。

Redshif Serverless には 3AZ にまたがる 3 つのサブネットを指定しなければならない *1という制約があることは知っていたのですが、サブネットサイズについてはドキュメント上で言及されているものは見つけられていませんでした。

エラーで指摘されたサブネットのサイズは/26だったので、「/25以上でないといけない」という制約でもあるのかな?などと当初考えていました。やがて試行を重ねるうちにワークグループ作成時に指定する「Redshift 処理ユニット (RPU)」の値によって結果が変わることに気がつきました。

分かってきた挙動をご紹介します。

まとめ

  • あくまでわたしが試した範囲では
    • Redshift Serverless ワークグループ作成時に作成される ENI は以下
      • Redshift 用:(RPU/8+1)
      • VPC エンドポイント用:1 個
    • 上記の ENI は(少なくとも初期段階では)すべて同一のサブネットに作成される
    • 作成後 10 分程度ワークグループを未使用のままにすると ENI は以下まで減少する
      • Redshift 用:1 個
      • VPC エンドポイント用:1 個
    • ワークグループの配置先として指定するサブネットのうちひとつでもサイズを満たさないものがあるとエラーが発生する

ワークグループ作成時の RPU ごとの IP 数と配置成否まとめ

  • 初期IP数(ワークグループ作成直後に生成される ENI の数)
  • サブネットサイズごとに、そのサブネットを配置先として指定した際のワークグループ作成の成否
    • :作成が成功した
    • -:作成が失敗した
RPU 初期IP数 /28 /27 /26 /25 /24
32 6 -
64 10 -
72 11 -
96 14 - -
128 18 - -
160 22 - -
192 26 - - -
256 34 - - -
384 50 - - -
512 66 - - - -
  • 各サブネットは他にリソースがない(利用可能な IP アドレスが MAX である)状態で検証しました
  • RPU は 32 ~ 512 の範囲で 8 刻みで指定できますが、さすがに全パターンは試せないので気になるところだけ刻みました

例えば RPU 512 のワークグループを作成しようとする場合、/24以上のサブネットが少なくとも 3 つ必要、ということになります。 *2

サブネットマスクごとのサブネットでの利用可能な IP アドレス数まとめ

基本的な部分のおさらいです。Amazon VPC のサブネットでは以下の仕様があります。 *3

  • 許可されているサブネットマスクは/28から/16まで
  • サブネットごとに、5つの IP アドレスが予約されており使用できない

それを踏まえてサブネットサイズごとの利用可能 IP アドレス数をまとめたものが以下です。

サブネットマスク アドレス数 利用可能数
/16 65536 65531
/17 32768 32763
/18 16384 16379
/19 8192 8187
/20 4096 4091
/21 2048 2043
/22 1024 1019
/23 512 507
/24 256 251
/25 128 123
/26 64 59
/27 32 27
/28 16 11

検証の方法

今回は以下のイメージで検証を行いました。

  • 3 つの AZ にまたがる/20の 3 つのサブネットを固定で用意
  • 4 つめのサブネットとして指定するサブネットを/28~/24で用意
  • RPU とサブネット(4つ)の組み合わせを変えながら、ワークグループの作成を試行

AWS CLI で Redshift Serverless ワークグループを作成する

Redshift Serverless は大きく以下のコンポーネントからなります。

  • 名前空間
    • データベース、ユーザー、IAM ロール、暗号化キーなどを定義
    • 独立して存在できる
    • 一つまでワークグループを関連づけられる
  • ワークグループ
    • ネットワーク設定、RPU などを定義
    • 独立して存在できず名前空間と関連づけが必須

今回は名前空間defaultが存在する前提で、ワークグループのみを作成していきます。作成をマネジメントコンソールから繰り返すのは骨が折れますので、AWS CLI でトライします。

なお、aws redshift-serverlessコマンドは比較的新しく、AWS CLI のバージョンによっては対応していません。今回わたしは以下のバージョンで試しました。

% aws --version
aws-cli/2.7.24 Python/3.9.11 Darwin/21.5.0 exe/x86_64 prompt/off

CLI スケルトンを生成する

パラメータをオプションとして引き渡してもいいですが、別のファイルとして独立していた方が便利そうなので CLI スケルトンを生成します。

% aws redshift-serverless create-workgroup --generate-cli-skeleton
{
    "baseCapacity": 0,
    "configParameters": [
        {
            "parameterKey": "",
            "parameterValue": ""
        }
    ],
    "enhancedVpcRouting": true,
    "namespaceName": "",
    "publiclyAccessible": true,
    "securityGroupIds": [
        ""
    ],
    "subnetIds": [
        ""
    ],
    "tags": [
        {
            "key": "",
            "value": ""
        }
    ],
    "workgroupName": ""
}

上記の出力を参考に、指定が必須なワークグループ名と名前空間のほか、組み合わせを変更したい RPU とサブネットのみを定義してinput.jsonとして作成しました。

input.json

{
    "baseCapacity": 32,
    "namespaceName": "default",
    "subnetIds": [
        "subnet-0726628d2fcd30fd8",
        "subnet-0d43b308c45e508d8",
        "subnet-0dfdc2a8a75f41548",
        "subnet-08bb0ba2d1d066d6f"
    ],
    "workgroupName": "test-wg"
}

ハイライト部の値を適宜変更しながら、ワークグループの生成を試みます。

作成が成功した場合の例

上記のファイルを指定して AWS CLI を実行する例は以下です。正常に実行されると以下のような結果が得られます。

% aws redshift-serverless create-workgroup\
    --cli-input-json file://input.json
{
    "workgroup": {
        "baseCapacity": 128,
        "configParameters": [
            {
                "parameterKey": "datestyle",
                "parameterValue": "ISO, MDY"
            },
            {
                "parameterKey": "enable_user_activity_logging",
                "parameterValue": "true"
            },
            {
                "parameterKey": "query_group",
                "parameterValue": "default"
            },
            {
                "parameterKey": "search_path",
                "parameterValue": "$user, public"
            },
            {
                "parameterKey": "max_query_execution_time",
                "parameterValue": "14400"
            }
        ],
        "creationDate": "2022-08-18T16:51:57.095000+00:00",
        "endpoint": {
            "address": "test-wg.012345678910.ap-northeast-1.redshift-serverless.amazonaws.com",
            "port": 5439
        },
        "enhancedVpcRouting": false,
        "namespaceName": "default",
        "publiclyAccessible": false,
        "securityGroupIds": [
            "sg-0b4aa795db56df73f"
        ],
        "status": "CREATING",
        "subnetIds": [
            "subnet-0726628d2fcd30fd8",
            "subnet-08bb0ba2d1d066d6f",
            "subnet-0d43b308c45e508d8",
            "subnet-0dfdc2a8a75f41548"
        ],
        "workgroupArn": "arn:aws:redshift-serverless:ap-northeast-1:012345678910:workgroup/a9e15e2b-c746-4c4a-a6e1-c6adcc4791bc",
        "workgroupId": "a9e15e2b-c746-4c4a-a6e1-c6adcc4791bc",
        "workgroupName": "test-wg"
    }
}

IP アドレス不足によりエラーが発生した場合の例

RPU とサブネットサイズの組み合わせによっては、以下のようにエラーが発生します。

% aws redshift-serverless create-workgroup --cli-input-json file://input.json

An error occurred (ValidationException) when calling the CreateWorkgroup operation: Insufficient free IP addresses found in subnets: [subnet-0ca11020f54905e7f].

Insufficient free IP addresses found in subnets: [subnet-xxxxxx].

冒頭で見たマネジメントコンソールでのエラーメッセージと同一です。

Redshift Serverless ワークグループによって生成された ENI を確認する

正常にワークグループの作成が行われた場合は、以下のコマンドで生成された ENI の確認を行いました。

今回は配置先のサブネット・VPC を都度 空にしてからワークグループを作成したため、フィルタリング条件として VPC ID を指定することで「ワークグループによって生成された ENI」の確認ができました。

% aws ec2 describe-network-interfaces\
 --filters Name=vpc-id,Values=vpc-0903631bbdee7fca5\
 --query 'NetworkInterfaces[].{
     PrivateIpAddress:PrivateIpAddress,
     AvailabilityZone:AvailabilityZone,
     SubnetId:SubnetId,
     Description:Description,
     RequesterId:RequesterId,
     RequesterManaged:RequesterManaged
 }'\
 --output table
--------------------------------------------------------------------------------------------------------------------------------------------------------------
|                                                                  DescribeNetworkInterfaces                                                                 |
+------------------+-------------------------------------------------+-------------------+------------------+-------------------+----------------------------+
| AvailabilityZone |                   Description                   | PrivateIpAddress  |   RequesterId    | RequesterManaged  |         SubnetId           |
+------------------+-------------------------------------------------+-------------------+------------------+-------------------+----------------------------+
|  ap-northeast-1a |  RedshiftNetworkInterface                       |  172.31.47.130    |  amazon-redshift |  True             |  subnet-0726628d2fcd30fd8  |
|  ap-northeast-1a |  RedshiftNetworkInterface                       |  172.31.42.151    |  amazon-redshift |  True             |  subnet-0726628d2fcd30fd8  |
|  ap-northeast-1a |  RedshiftNetworkInterface                       |  172.31.46.167    |  amazon-redshift |  True             |  subnet-0726628d2fcd30fd8  |
|  ap-northeast-1a |  VPC Endpoint Interface vpce-0c4f2339b89312d0f  |  172.31.41.91     |  727180483921    |  True             |  subnet-0726628d2fcd30fd8  |
|  ap-northeast-1a |  RedshiftNetworkInterface                       |  172.31.36.187    |  amazon-redshift |  True             |  subnet-0726628d2fcd30fd8  |
|  ap-northeast-1a |  RedshiftNetworkInterface                       |  172.31.41.179    |  amazon-redshift |  True             |  subnet-0726628d2fcd30fd8  |
|  ap-northeast-1a |  RedshiftNetworkInterface                       |  172.31.37.142    |  amazon-redshift |  True             |  subnet-0726628d2fcd30fd8  |
|  ap-northeast-1a |  RedshiftNetworkInterface                       |  172.31.36.155    |  amazon-redshift |  True             |  subnet-0726628d2fcd30fd8  |
|  ap-northeast-1a |  RedshiftNetworkInterface                       |  172.31.41.103    |  amazon-redshift |  True             |  subnet-0726628d2fcd30fd8  |
|  ap-northeast-1a |  RedshiftNetworkInterface                       |  172.31.43.143    |  amazon-redshift |  True             |  subnet-0726628d2fcd30fd8  |
|  ap-northeast-1a |  RedshiftNetworkInterface                       |  172.31.46.110    |  amazon-redshift |  True             |  subnet-0726628d2fcd30fd8  |
|  ap-northeast-1a |  RedshiftNetworkInterface                       |  172.31.40.35     |  amazon-redshift |  True             |  subnet-0726628d2fcd30fd8  |
|  ap-northeast-1a |  RedshiftNetworkInterface                       |  172.31.32.79     |  amazon-redshift |  True             |  subnet-0726628d2fcd30fd8  |
|  ap-northeast-1a |  RedshiftNetworkInterface                       |  172.31.43.20     |  amazon-redshift |  True             |  subnet-0726628d2fcd30fd8  |
|  ap-northeast-1a |  RedshiftNetworkInterface                       |  172.31.47.29     |  amazon-redshift |  True             |  subnet-0726628d2fcd30fd8  |
|  ap-northeast-1a |  RedshiftNetworkInterface                       |  172.31.47.252    |  amazon-redshift |  True             |  subnet-0726628d2fcd30fd8  |
|  ap-northeast-1a |  RedshiftNetworkInterface                       |  172.31.32.184    |  amazon-redshift |  True             |  subnet-0726628d2fcd30fd8  |
|  ap-northeast-1a |  RedshiftNetworkInterface                       |  172.31.40.255    |  amazon-redshift |  True             |  subnet-0726628d2fcd30fd8  |
+------------------+-------------------------------------------------+-------------------+------------------+-------------------+----------------------------+

上記は RPU 128 でワークグループを作成した際の例で、以下の内訳になっていました。

  • RedshiftNetworkInterface:17 個
  • VPC Endpoint Interface:1 個

ワークグループ作成直後は上記の結果でしたが、10分程度放置した後に再度確認すると以下のように変化していました。

% aws ec2 describe-network-interfaces\
 --filters Name=vpc-id,Values=vpc-0903631bbdee7fca5\
 --query 'NetworkInterfaces[].{
     PrivateIpAddress:PrivateIpAddress,
     AvailabilityZone:AvailabilityZone,
     SubnetId:SubnetId,
     Description:Description,
     RequesterId:RequesterId,
     RequesterManaged:RequesterManaged
 }'\
 --output table
--------------------------------------------------------------------------------------------------------------------------------------------------------------
|                                                                  DescribeNetworkInterfaces                                                                 |
+------------------+-------------------------------------------------+-------------------+------------------+-------------------+----------------------------+
| AvailabilityZone |                   Description                   | PrivateIpAddress  |   RequesterId    | RequesterManaged  |         SubnetId           |
+------------------+-------------------------------------------------+-------------------+------------------+-------------------+----------------------------+
|  ap-northeast-1a |  VPC Endpoint Interface vpce-0c4f2339b89312d0f  |  172.31.41.91     |  727180483921    |  True             |  subnet-0726628d2fcd30fd8  |
|  ap-northeast-1a |  RedshiftNetworkInterface                       |  172.31.37.142    |  amazon-redshift |  True             |  subnet-0726628d2fcd30fd8  |
+------------------+-------------------------------------------------+-------------------+------------------+-------------------+----------------------------+
  • RedshiftNetworkInterface:1 個
  • VPC Endpoint Interface:1 個

いくつか試行を重ねた結果、以下の傾向が見て取れました。

  • RedshiftNetworkInterface はワークグループ作成直後に(RPU/8+1) 個作成され、未使用だと 1 個まで減少する
  • RedshiftNetworkInterface、VPC Endpoint Interface はワークグループ作成時にはすべて同一のサブネットに生成される

検証の結果をまとめてみる

ここまでの手順を繰り返して得られた結果のまとめが、冒頭で載せた以下です。

  • 初期IP数(ワークグループ作成直後に生成される ENI の数)
  • サブネットサイズごとに、そのサブネットを配置先として指定した際のワークグループ作成の成否
    • :作成が成功した
    • -:作成が失敗した
RPU 初期IP数 /28 /27 /26 /25 /24
32 6 -
64 10 -
72 11 -
96 14 - -
128 18 - -
160 22 - -
192 26 - - -
256 34 - - -
384 50 - - -
512 66 - - - -

必要となる空き IP アドレスの数について法則を見出せないかといろいろ考えてみたのですが、ピンとくるものがありませんでした。思いついた方は教えていただけると幸いです。

Redshift_Serverless_summary

空き IP アドレスの数を調整して境界線を探る

上記のまとめにより大まかな結果は得られたのですが、サブネットの利用可能 IP アドレスが MAX の場合でしか試せていません。

例えば RPU 128 の場合に判明しているのは以下です。

  • 空き IP アドレスが 27(/27)では足りない
  • 空き IP アドレスが 59(/26)あれば事足りる

27~59 のどこかに境界線があるはずだ、ということで探ってみることにしました。

検証のアプローチは以下です。

  • /26のサブネットを作成し、手動で ENI を 32 個作成する(空き IP アドレスが 27 になる)
  • 1個ずつ ENI を削除しながらワークグループの作成を試み、どの段階で作成が成功するかを確認する

作業するサブネットの確認

今回 4 つめの配置先サブネットとして使用するサブネットは、以下の通り/26で利用可能 IP アドレスが MAX の状態です。

% aws ec2 describe-subnets\
    --subnet-ids subnet-0f0ee4597ab063b80\
    --query 'Subnets[].{
        CidrBlock:CidrBlock,
        AvailableIpAddressCount:AvailableIpAddressCount
        }'\
    --output table
------------------------------------------------
|                DescribeSubnets               |
+--------------------------+-------------------+
|  AvailableIpAddressCount |     CidrBlock     |
+--------------------------+-------------------+
|  59                      |  172.31.100.0/26  |
+--------------------------+-------------------+

ENI を 32 個作成する

以下コマンドにより、対象のサブネットに ENI を 32 個作成します。

% for i in {1..32} ; do
    aws ec2 create-network-interface --subnet-id subnet-0f0ee4597ab063b80 --query NetworkInterface.PrivateIpAddress ;
    done

ENI を削除しながらワークグループの作成を試みる

以下のコマンドによりループ処理を行います。

% COUNT=1
% aws ec2 describe-network-interfaces\
    --filters Name=subnet-id,Values=subnet-0f0ee4597ab063b80\
    --query "NetworkInterfaces[*].[NetworkInterfaceId]"\
    --output text\
 | while read interface; do
    aws ec2 delete-network-interface --network-interface-id $interface
    echo "利用可能なIPアドレス数は$((27+$((COUNT++))))"
    sleep 30
    aws redshift-serverless create-workgroup --cli-input-json file://input.json;
   done

大まかに以下の内容です。

  • aws ec2 describe-network-interfaces により ENI のリストを取得する
  • リストを一つずつ読み込み、以下をループ
    • ENI を削除する(aws delete-network-interface
    • 空き IP アドレス数を表示
    • 30秒待機(不要な気もしますが、念の為)
    • ワークグループの作成を試みる

なお、ワークグループ作成時に指定しているinput.jsonの内訳は以下です。

input.json

{
    "baseCapacity": 128,
    "namespaceName": "default",
    "subnetIds": [
        "subnet-0726628d2fcd30fd8",
        "subnet-0d43b308c45e508d8",
        "subnet-0dfdc2a8a75f41548",
        "subnet-0f0ee4597ab063b80"
    ],
    "workgroupName": "test-wg"
}

上記のコマンドを実行した結果、空き IP アドレス数が 43 の時にワークグループの作成が成功しました。

利用可能なIPアドレス数は28

An error occurred (ValidationException) when calling the CreateWorkgroup operation: Insufficient free IP addresses found in subnets: [subnet-0f0ee4597ab063b80].
利用可能なIPアドレス数は29

An error occurred (ValidationException) when calling the CreateWorkgroup operation: Insufficient free IP addresses found in subnets: [subnet-0f0ee4597ab063b80].

...略...

利用可能なIPアドレス数は41

An error occurred (ValidationException) when calling the CreateWorkgroup operation: Insufficient free IP addresses found in subnets: [subnet-0f0ee4597ab063b80].
利用可能なIPアドレス数は42

An error occurred (ValidationException) when calling the CreateWorkgroup operation: Insufficient free IP addresses found in subnets: [subnet-0f0ee4597ab063b80].
利用可能なIPアドレス数は43
{
    "workgroup": {
        "baseCapacity": 128,
        "configParameters": [
            {
                "parameterKey": "datestyle",
                "parameterValue": "ISO, MDY"
...略...
利用可能なIPアドレス数は44

An error occurred (ConflictException) when calling the CreateWorkgroup operation: The workgroup with name test-wg already exists.

先ほどの表に当てはめてみると……たまたま 43 という数字はありましたが、関連性はわかっていません。

Redshift_Serverless_rpu128

もう少し材料が揃えば見えてくるものがあるかもしれませんが、ひとまず満足してここで検証を切り上げました。

終わりに

Redshift Serverless のワークグループ作成時に指定する RPU によって生成される ENI の数が変わる、それに関連して配置可能なサブネットのサイズも変動する、ということを確認しました。

現時点では Redshift Serverless での ENI の挙動やサブネットサイズについて公式ドキュメントで言及されている箇所は見つけられませんでした。 *4

例えば ALB では以下のように記述があるので、似たような形で記述が増えると嬉しいな、と思っています。

ロードバランサーが正しくスケールできるように、ロードバランサーのアベイラビリティーゾーンサブネットごとに CIDR ブロックを最低でも /27 ビットマスク (例: 10.0.0.0/27) にし、少なくとも各サブネットにつき 8 個の空き IP アドレスを用意してください。

今回は試してみたベースでの情報ですが、Redshift Serverless の導入を検討されている方の参考になれば幸いです。(既存の環境に導入する際は新規 VPC の作成も視野に入れていろいろ考える余地がありそうです。)

以上、 チバユキ (@batchicchi) がお送りしました。

参考

脚注

  1. Considerations when using Amazon Redshift Serverless - Amazon Redshift
  2. あくまで今回の試行結果に準じれば、です。正確な仕様かは現時点では分かりませんし、今後変更になる可能性もあります。
  3. VPC のサブネット - Amazon Virtual Private Cloud
  4. 初期に生成された数から減る挙動は確認できましたが、それより増える可能性もあるのか?という部分も気になっています。