EBSボリューム作成時のべき等性を担保できるようになりました

2021.08.05

中山(順)@リカバリー中 です

先日、EBSボリュームを作成する際にべき等性を担保できるように、作成リクエスト時にClient tokenを指定できるようになりました。

Amazon Elastic Block Store now supports idempotent volume creation

実際にAWS CLIを使って動作を確認してみたいと思います。

べき等性 is 何?

結論としては、「ある操作を 1 回行っても複数回行っても結果が同じである」という性質です。

そもそも、べき等性とは、どういうことを言うのでしょうか ? これは「ある操作を 1 回行っても複数回行っても結果が同じである」ことをいう概念です。

サーバーレスが気になる開発者に捧ぐ「べき等性」ことはじめ 第一回 べき等性 (冪等性/idempotency) ってなんだ!?

APIに対してリクエストを行ったとき、リクエスト元に応答が返って来なかったけどAPI側(サーバ側)ではリクエストを正常に受信できていたというケースが考えられると思います。 EC2インスタンスの作成を例に考えてみたいのですが、クライアント側でリクエストの応答が正常に無かったというだけで単純にリトライしてしまうと、EC2インスタンスが2つ作成されてしまう可能性があります。 これはいけません。

ということで、何らかの方法でべき等性を担保する必要があります。

このあたりの話は、AWSさん公式コンテンツであるBuilders libraryでも詳細に解説されています。 ここのコンテンツはすごくおすすめです。

Making retries safe with idempotent APIs

ちなみに、EC2 Instanceでは以前よりClient tokenを利用したべき等性の担保が可能でした。 今回のアップデートでは、EBSボリュームでも同様にべき等性を担保できるようになりました。

Ensuring idempotency

やってみた

AWS CLIで確認してみます。 リファレンスはこちらです。

create-volume

バージョンですが、ブログ執筆時の最新バージョンを利用しています。

aws --version
aws-cli/2.2.26 Python/3.8.8 Linux/4.14.225-168.357.amzn2.x86_64 exec-env/CloudShell exe/x86_64.amzn.2 prompt/off

Client tokenなし

まずはClient token無しで作成します。 こんな感じで普通に作成できました。

aws ec2 create-volume \
    --volume-type gp3 \
    --size 10 \
    --availability-zone ap-northeast-1a
{
    "AvailabilityZone": "ap-northeast-1a",
    "CreateTime": "2021-08-05T05:36:01+00:00",
    "Encrypted": false,
    "Size": 10,
    "SnapshotId": "",
    "State": "creating",
    "VolumeId": "vol-0c3204c0ccc23a029",
    "Iops": 3000,
    "Tags": [],
    "VolumeType": "gp3",
    "MultiAttachEnabled": false,
    "Throughput": 125
}

もう一度同じコマンドを実行してみます。 当たり前ですが、普通に作成できました。 もちろん、Volume IDは別のものです。

aws ec2 create-volume \
    --volume-type gp3 \
    --size 10 \
    --availability-zone ap-northeast-1a
{
    "AvailabilityZone": "ap-northeast-1a",
    "CreateTime": "2021-08-05T05:38:19+00:00",
    "Encrypted": false,
    "Size": 10,
    "SnapshotId": "",
    "State": "creating",
    "VolumeId": "vol-0dce2897a7092d8be",
    "Iops": 3000,
    "Tags": [],
    "VolumeType": "gp3",
    "MultiAttachEnabled": false,
    "Throughput": 125
}

Client tokenあり

それでは、Client tokenを付与してみます。 なお、Client tokenは大文字小文字を区別する64文字以内のASCII文字として指定する必要があります。

で、普通に作成できました。

aws ec2 create-volume \
    --volume-type gp3 \
    --size 10 \
    --availability-zone ap-northeast-1a \
    --client-token 550e8400-e29b-41d4-a716-446655440000
{
    "AvailabilityZone": "ap-northeast-1a",
    "CreateTime": "2021-08-05T05:42:52+00:00",
    "Encrypted": false,
    "Size": 10,
    "SnapshotId": "",
    "State": "creating",
    "VolumeId": "vol-0cec5626dcb45dcbf",
    "Iops": 3000,
    "Tags": [],
    "VolumeType": "gp3",
    "MultiAttachEnabled": false,
    "Throughput": 125
}

続けて、同じClinet tokenで作成してみます。

すると、応答は普通に返ってきたのですが、Volume IDが同じです。

aws ec2 create-volume \
    --volume-type gp3 \
    --size 10 \
    --availability-zone ap-northeast-1a \
    --client-token 550e8400-e29b-41d4-a716-446655440000
{
    "AvailabilityZone": "ap-northeast-1a",
    "CreateTime": "2021-08-05T05:42:52+00:00",
    "Encrypted": false,
    "Size": 10,
    "SnapshotId": "",
    "State": "creating",
    "VolumeId": "vol-0cec5626dcb45dcbf",
    "Iops": 3000,
    "Tags": [],
    "VolumeType": "gp3",
    "MultiAttachEnabled": false,
    "Throughput": 125
}

ボリュームの一覧を確認しますと、コマンドを4回実行したはずですがボリュームは3つしか作成されていないことが確認できました。

aws ec2 describe-volumes
{
    "Volumes": [
        {
            "Attachments": [],
            "AvailabilityZone": "ap-northeast-1a",
            "CreateTime": "2021-08-05T05:36:01.964000+00:00",
            "Encrypted": false,
            "Size": 10,
            "SnapshotId": "",
            "State": "available",
            "VolumeId": "vol-0c3204c0ccc23a029",
            "Iops": 3000,
            "VolumeType": "gp3",
            "MultiAttachEnabled": false,
            "Throughput": 125
        },
        {
            "Attachments": [],
            "AvailabilityZone": "ap-northeast-1a",
            "CreateTime": "2021-08-05T05:38:19.200000+00:00",
            "Encrypted": false,
            "Size": 10,
            "SnapshotId": "",
            "State": "available",
            "VolumeId": "vol-0dce2897a7092d8be",
            "Iops": 3000,
            "VolumeType": "gp3",
            "MultiAttachEnabled": false,
            "Throughput": 125
        },
        {
            "Attachments": [],
            "AvailabilityZone": "ap-northeast-1a",
            "CreateTime": "2021-08-05T05:42:52.612000+00:00",
            "Encrypted": false,
            "Size": 10,
            "SnapshotId": "",
            "State": "available",
            "VolumeId": "vol-0cec5626dcb45dcbf",
            "Iops": 3000,
            "VolumeType": "gp3",
            "MultiAttachEnabled": false,
            "Throughput": 125
        }
    ]
}

それでは、Client tokenを別のものに変えてみます。 すると、別の新しいボリュームが作成されました。

aws ec2 create-volume \
    --volume-type gp3 \
    --size 10 \
    --availability-zone ap-northeast-1a \
    --client-token 550e8400-e29b-41d4-a716-446655449999
{
    "AvailabilityZone": "ap-northeast-1a",
    "CreateTime": "2021-08-05T05:50:36+00:00",
    "Encrypted": false,
    "Size": 10,
    "SnapshotId": "",
    "State": "creating",
    "VolumeId": "vol-099f508ecbe5adddd",
    "Iops": 3000,
    "Tags": [],
    "VolumeType": "gp3",
    "MultiAttachEnabled": false,
    "Throughput": 125
}

まとめ

非常に地味ですが、大事な機能を確認してみました。 ネットワークは常に正常稼働しているわけではありませんので、利用者がAWS環境を正しい状態を保つためにはこういった機能が必要になってきます。 こういった機能は他でも応用が利く話ですので、時間のある方は同様の機能をサポートしている他のAPIを試してべき等性を感じてみてはいかがでしょうか?