boto3.Session().get_available_regionsメソッドを使う時には気をつけるポイントがあるという話

boto3.Session().get_available_regionsメソッドを使ってリージョンの一覧を取得する時には、オプトインのリージョンも含みます!
2023.01.31

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

皆さん、こんにちは。

クルトンです!

今回は自分がBoto3を触っていて、少しハマった所と解決方法についてご紹介したいと思います。 同じような箇所で困っている方の助けになれば幸いです。

気をつけるポイント

早速ですが、気をつけるポイントについてです。

boto3.Session().get_available_regionsメソッドで取得できるリージョン一覧はオプトインのリージョンかどうか関係なくサービスが使える全てのリージョン

なぜこの内容について気をつけるべきなのかというと、次で例示するような「複数リージョンにおいて操作したいサービスがある」とプログラムを書いたとします。

# SageMakerが対応してるリージョン一覧を取得
regions = boto3.Session().get_available_regions('sagemaker')

# リージョンごとに稼働中のノートブックインスタンスを取得
for region in regions:
    sm = boto3.client('sagemaker', region_name=region)
    nb_list = sm.list_notebook_instances(
              StatusEquals='InService'
          )['NotebookInstances']

そうすると、UnrecognizedClientExceptionというエラーが返されてしまいます。

実際に、自分が遭遇したエラーは次のようなものでした。

[ERROR] ClientError: An error occurred (UnrecognizedClientException) when calling the ListNotebookInstances operation: The security token included in the request is invalid

プログラムが通らない理由

次の2つが噛み合っていない事が原因です。

  • boto3.Session().get_available_regionsメソッドで取得できるリージョン一覧はbotocoreの中で定義されているもの
    • オプトインのリージョンかどうか関係なくサービスが使える全てのリージョン
  • boto3.Session()で作られるセッションはグローバルのSTSエンドポイントから取得(boto3.client(サービス名)はboto3.Session()のデフォルトセッションを使用)
    • プログラムの処理を受け付けるのはデフォルトで有効化されているリージョンのみ

つまり、オプトインのリージョンを操作する際にエラーが出ているという事です。

エラーの回避方法

いくつか対応策があります。

  1. グローバルSTSエンドポイントの設定を調整して全てのAWSのリージョンで有効にする
  2. リージョナルエンドポイントを指定してAssumeRoleを行なう

上記内容ですが、すでに弊社ブログでやり方が説明されているので、これらの方法で解決したい方はぜひご参照ください。

自分のケースですと、「現状使っている全てのリージョンにおいて操作をしたい」という内容でしたので、第3の方法として次のようなコードを書きました。

# SageMakerが対応してるリージョン一覧を取得
regions = boto3.Session().get_available_regions('sagemaker')

# リージョンごとに稼働中のノートブックインスタンスを取得
for region in regions:
    sm = boto3.client('sagemaker', region_name=region)
    try:
      nb_list = sm.list_notebook_instances(
                StatusEquals='InService'
            )['NotebookInstances']
    except:
        continue

これで、エラーが回避できます。

おまけ

ちなみにですが、何かしらの操作を行ないたいサービスでどのリージョンで利用可能なのか確認するには、printメソッドを使うと確認する事が出来ます。

# SageMakerが対応してるリージョン一覧を取得
regions = boto3.Session().get_available_regions('sagemaker')

print(regions)

上記内容で取得したリージョンの名前と、例えばコンソール画面のリージョン選択から確認できる有効化されていないリージョンを見比べます。その後、明示的にサービスの操作を行なうかどうかをif文を使って「〇〇というリージョン名ならcontinueする」という内容を、メソッドの直前に書く事でエラー前に弾く事が出来ます。(サービスがどのリージョンで使えるのかを随時追っていく必要があるので、現場で実際に使うには労力がかかります。)

終わりに

今回は、複数のリージョンをBoto3で操作した時に起こったエラーの内容に対して、解決策をいくつか示しました。

情報を集めて整理したので「せっかくならば」とブログ化した次第でございます。 どなたか同じ内容で困っている方の一助になれば幸いです!

今回はここまで。

それでは、また!