michimani.net

AWS CLI v2.2.0 の変更点について調べてみた

2021-04-28

普段はパッチバージョンが更新されていくことが多い AWS CLI ですが、今朝のアップデートでは v2 のマイナーバージョンが上がって 2.1.39 から 2.2.0 になりました。 CHANGELOG をもとに、どこが変わったのか見てみます。

目次

v2.2.0 の変更点

AWS CLI では、マイナーバージョンが更新されるときは CHANGELOG に feature: として内容が記載されます。
今回の 2.2.0 では下記の記述がありました。

feature:s3: Add experimental support for performing S3 transfers using the AWS Common Runtime (CRT). It provides a C-based S3 transfer client that can improve transfer throughput for s3 commands.

aws-cli/CHANGELOG.rst at 2.2.0 · aws/aws-cli

直訳すると

AWS Common Runtime(CRT)を使用してS3転送を実行する実験的なサポートを追加しました。これは、CベースのS3転送クライアントを提供し、s3コマンドの転送スループットを向上させることができます。

…なるほど。

変更点の詳細

CHANGELOG およびコミットをもとに、変更点の詳細を確認してみます。

ヘルプで確認できるレベルの変更点

s3 コマンドについて、ヘルプで確認できるレベルの変更点は確認できませんでした。 (利用可能なサブコマンド、ヘルプの内容は同じ)

ソースコードレベルの変更

ソースコードに関しては、下記のコミットにて差分を確認できます。

Merge pull request #6105 from kyleknap/crt-s3 · aws/aws-cli@2e05300

CHANGELOG で記載のあった転送に関する変更が加えられており、 transfer_client として crt を指定できるようになっているようです。

s3 コマンドのサブコマンドのうち、 S3 転送を利用するサブコマンドは下記のとおりです。(= S3TransferCommand)

これは awscli/customizations/s3/subcommands.py#L708 あたりで確認できます。

aws-cli/subcommands.py at v2 · aws/aws-cli

S3TransferCommand では、 config ファイル (= ~/.aws/config) から取得した S3 に関する設定の中から、 preferred_transfer_client で指定した値を transfer_client として使うようになっています。今回のアップデートでは、config ファイルで transfer_client を指定できるようになったという内容だということがわかりました。

CRT を使って S3 転送を実行してみる

変更点の内容がわかったので、実際に CRT を使用して S3 転送を実行してみます。今回は s3 cp コマンドでその違いを確認してみます。

コマンドの実行詳細については --debug オプションを付けることで確認できます。

default で実行

まずは、新たに指定可能となった preferred_transfer_client を使わずに s3 cp を実行してみます。

$ aws s3 cp sample.txt s3://aws-cli-2-2-0-test-XXXXXXXXXXXX/ --debug

デバッグの出力は割と量があるので transfer で grep した結果だけ貼ります。

2021-04-28 23:27:32,931 - MainThread - botocore.hooks - DEBUG - Event load-cli-arg.custom.cp.force-glacier-transfer: calling handler <awscli.paramfile.URIArgumentHandler object at 0x7f823ca186a0>
2021-04-28 23:27:33,015 - MainThread - s3transfer.utils - DEBUG - Acquiring 0
2021-04-28 23:27:33,015 - ThreadPoolExecutor-1_0 - s3transfer.tasks - DEBUG - UploadSubmissionTask(transfer_id=0, {'transfer_future': <s3transfer.futures.TransferFuture object at 0x7f823d24e220>}) about to wait for the following futures []
2021-04-28 23:27:33,015 - ThreadPoolExecutor-1_0 - s3transfer.tasks - DEBUG - UploadSubmissionTask(transfer_id=0, {'transfer_future': <s3transfer.futures.TransferFuture object at 0x7f823d24e220>}) done waiting for dependent futures
2021-04-28 23:27:33,016 - ThreadPoolExecutor-1_0 - s3transfer.tasks - DEBUG - Executing task UploadSubmissionTask(transfer_id=0, {'transfer_future': <s3transfer.futures.TransferFuture object at 0x7f823d24e220>}) with kwargs {'client': <botocore.client.S3 object at 0x7f823d1fb6d0>, 'config': <s3transfer.manager.TransferConfig object at 0x7f823d2394c0>, 'osutil': <s3transfer.utils.OSUtils object at 0x7f823d239550>, 'request_executor': <s3transfer.futures.BoundedExecutor object at 0x7f823d239790>, 'transfer_future': <s3transfer.futures.TransferFuture object at 0x7f823d24e220>}
2021-04-28 23:27:33,022 - ThreadPoolExecutor-1_0 - s3transfer.futures - DEBUG - Submitting task PutObjectTask(transfer_id=0, {'bucket': 'aws-cli-2-2-0-test-XXXXXXXXXXXX', 'key': 'sample.txt', 'extra_args': {'ContentType': 'text/plain'}}) to executor <s3transfer.futures.BoundedExecutor object at 0x7f823d239790> for transfer request: 0.
2021-04-28 23:27:33,022 - ThreadPoolExecutor-1_0 - s3transfer.utils - DEBUG - Acquiring 0
2021-04-28 23:27:33,022 - ThreadPoolExecutor-0_0 - s3transfer.tasks - DEBUG - PutObjectTask(transfer_id=0, {'bucket': 'aws-cli-2-2-0-test-XXXXXXXXXXXX', 'key': 'sample.txt', 'extra_args': {'ContentType': 'text/plain'}}) about to wait for the following futures []
2021-04-28 23:27:33,022 - ThreadPoolExecutor-0_0 - s3transfer.tasks - DEBUG - PutObjectTask(transfer_id=0, {'bucket': 'aws-cli-2-2-0-test-XXXXXXXXXXXX', 'key': 'sample.txt', 'extra_args': {'ContentType': 'text/plain'}}) done waiting for dependent futures
2021-04-28 23:27:33,023 - ThreadPoolExecutor-1_0 - s3transfer.utils - DEBUG - Releasing acquire 0/None
2021-04-28 23:27:33,023 - ThreadPoolExecutor-0_0 - s3transfer.tasks - DEBUG - Executing task PutObjectTask(transfer_id=0, {'bucket': 'aws-cli-2-2-0-test-XXXXXXXXXXXX', 'key': 'sample.txt', 'extra_args': {'ContentType': 'text/plain'}}) with kwargs {'client': <botocore.client.S3 object at 0x7f823d1fb6d0>, 'fileobj': <s3transfer.utils.ReadFileChunk object at 0x7f823d24ea30>, 'bucket': 'aws-cli-2-2-0-test-XXXXXXXXXXXX', 'key': 'sample.txt', 'extra_args': {'ContentType': 'text/plain'}}
2021-04-28 23:27:33,024 - ThreadPoolExecutor-0_0 - botocore.endpoint - DEBUG - Making request for OperationModel(name=PutObject) with params: {'url_path': '/aws-cli-2-2-0-test-XXXXXXXXXXXX/sample.txt', 'query_string': {}, 'method': 'PUT', 'headers': {'Content-Type': 'text/plain', 'User-Agent': 'aws-cli/2.2.0 Python/3.8.8 Darwin/20.4.0 exe/x86_64 prompt/off command/s3.cp', 'Content-MD5': '1B2M2Y8AsgTpgAmY7PhCfg==', 'Expect': '100-continue'}, 'body': <s3transfer.utils.ReadFileChunk object at 0x7f823d24ea30>, 'url': 'https://s3.ap-northeast-1.amazonaws.com/aws-cli-2-2-0-test-XXXXXXXXXXXX/sample.txt', 'context': {'client_region': 'ap-northeast-1', 'client_config': <botocore.config.Config object at 0x7f823d1fb7c0>, 'has_streaming_input': True, 'auth_type': None, 'signing': {'bucket': 'aws-cli-2-2-0-test-XXXXXXXXXXXX'}}}
2021-04-28 23:27:33,025 - ThreadPoolExecutor-0_0 - botocore.hooks - DEBUG - Event request-created.s3.PutObject: calling handler <function signal_not_transferring at 0x7f823c455040>
2021-04-28 23:27:33,027 - ThreadPoolExecutor-0_0 - botocore.hooks - DEBUG - Event request-created.s3.PutObject: calling handler <function signal_transferring at 0x7f823c0360d0>
2021-04-28 23:27:33,180 - ThreadPoolExecutor-0_0 - s3transfer.utils - DEBUG - Releasing acquire 0/None

CRT の文字もなく、普通に実行されてる感があります。

crt で実行

続いて、 preferred_transfer_clientcrt を指定して実行してみます。 config ファイルでは、下記のように記述します。

[default]
region=ap-northeast-1
output=json
s3 =
  preferred_transfer_client=crt

これで実行して、先ほどと同じくデバッグの出力を transfer で grep した結果を貼ります。

2021-04-28 23:33:09,262 - MainThread - botocore.hooks - DEBUG - Event load-cli-arg.custom.cp.force-glacier-transfer: calling handler <awscli.paramfile.URIArgumentHandler object at 0x7fb2aba1a6a0>
2021-04-28 23:33:09,360 - MainThread - awscli.customizations.s3.subscribers - DEBUG - Not providing transfer size. Future: <s3transfer.crt.CRTTransferFuture object at 0x7fb2ac2a3730> does not offerthe capability to notify the size of a transfer
2021-04-28 23:33:09,365 - MainThread - botocore.hooks - DEBUG - Event request-created.s3.PutObject: calling handler <bound method BotocoreCRTRequestSerializer._capture_http_request of <s3transfer.crt.BotocoreCRTRequestSerializer object at 0x7fb2ac23b4c0>>
2021-04-28 23:33:09,366 - MainThread - botocore.hooks - DEBUG - Event before-send.s3.PutObject: calling handler <bound method BotocoreCRTRequestSerializer._make_fake_http_response of <s3transfer.crt.BotocoreCRTRequestSerializer object at 0x7fb2ac23b4c0>>
2021-04-28 23:33:09,367 - MainThread - botocore.hooks - DEBUG - Event after-call.s3.PutObject: calling handler <bound method BotocoreCRTRequestSerializer._change_response_to_serialized_http_request of <s3transfer.crt.BotocoreCRTRequestSerializer object at 0x7fb2ac23b4c0>>

CRT が使われている気配があります。

ということで、 AWS Common Runtime(CRT)を使用してS3転送を実行する実験的なサポート が追加されていることがわかり、実際に実行することができました。

そもそも AWS Common Runtime (CRT) とは

前項までの内容が AWS CLI v2.2.0 での変更点ということみたいですが、そもそも CRT って何? となったので調べてみました。

AWS Common Runtime (CRT) は、 C 言語で書かれたライブラリで、 Go を除く各言語の SDK のベースライブラリとして採用されています。ライブラリ自体は 9 個の独立したパッケージで構成されており、内容 (役割) は下記の通りです。

詳細については下記のドキュメントを参照。

AWS Common Runtime (CRT) libraries - AWS SDKs and Tools

AWS CLI は Python で実装されているので SDK for Python (boto) を使っており、その中で aws-crt-python を使っています。

CHANGELOG にも書かれていましたが、 CRT を使用して S3 転送を行うことで、スループットの向上が期待できるということです。

… このあたりは深追いするとキリがなさそうなので、ざっくりとこの辺までにしておきます。

まとめ

AWS CLI v2 のマイナーバージョンが上がったので、変更点について調べてみた話でした。ついでに AWS Common Runtime (CRT) についても少しだけ調べてみました。

v1 は新機能への対応が早いですが、 v2 はこういった実験的なサポートが追加されていくという点で v1 と差別化してる感じなんでしょうか。

とりあえず、変更点の内容が把握できたのでよしとします。


comments powered by Disqus