サービス開発課のくればやしです。ドラクエⅠ ・Ⅱが楽しみすぎます☺️
AWSでは様々なリソースをAPIで操作可能です。
それらを簡単に扱うため、AWS公式からPythonやGo等のライブラリが提供されており、RubyのSDK(AWS SDK for Ruby、以下Ruby SDK)もその中の一つです。本記事ではRubyを用いてAWSのAPIに入門してみたいと思います。
本記事の対象
- RubyでAWSのAPIプログラミングを試してみたい人
事前準備
以下の環境で動作確認しました。
- ホスト: Amazon Linux 2023
- Ruby: #3.2.2
- AWS SDK for Ruby: 3.232.0
SDK等インストール手順(サンプル)
# Ruby本体やAWS SDK の実行に必要なライブラリのインストール > sudo yum install ruby ruby-devel gcc > ruby -v # Version が表示されることを確認 > bundle init > vim Gemfile gem "aws-sdk-ec2" gem "aws-sdk-iam" gem "ox" > bundle install
環境準備
EC2インスタンスの操作を例にしてみるので、リソース操作の対象のEC2インスタンスを停止済みで準備してください。
基本的な方法
まずは停止しているEC2インスタンスを開始する操作を通じて簡単な使い方を確認します。インスタンスID等は適宜読み替えてください。
基本的な流れとしては、操作したいリソースのサービスのクライアントを生成し、それを用いてオペレーションを実行します。
例として、以下のコードを実行することで、EC2インスタンスの開始をリクエストできます。AWSマネジメントコンソール等で確認すると、停止していたインスタンスが起動することを確認できると思います。
require "aws-sdk-ec2" client = Aws::EC2::Client.new client.start_instances( instance_ids: ["i-xxxxxxxxxxxxx"] )
EC2のクライアントのAPIドキュメントは以下になりますので、こちらでオプション等確認できます。
Class: Aws::EC2::Client — AWS SDK for Ruby V3
オプションとして、例えば、認証情報やリージョンの設定が可能です。以下のように記載することで、リージョンとアクセスキーによる認証情報を指定できます。
Aws::EC2::Client.new( region: "us-east-1", credentials: Aws::Credentials("access_key_id", "secret_access_key") )
認証情報については、アクセスキーの他、STSを用いた設定等も可能です。以下にドキュメントがあります。
操作結果の確認
上記でリソースの操作をリクエストするところまで確認したので、ここからは操作結果を確認していきます。
AWSではリソースにもよりますが、APIの実行成功 = 意図したステータスへの変更とは限りません。EC2インスタンスのように stopped -> pending -> running のように状態が遷移するものが多くあります。
実際に、停止状態のインスタンスを開始したときのレスポンスの中身を展開してみましょう。 current_state が pending になっていることが分かります。これが running に変われば開始処理が最終的に成功したことを確認できます。
response = client.start_instances( instance_ids: ["i-xxxxxxxxxxxxx"] ) #<struct Aws::EC2::Types::StartInstancesResult starting_instances= [#<struct Aws::EC2::Types::InstanceStateChange current_state=#<struct Aws::EC2::Types::InstanceState code=0, name="pending">, instance_id="i-xxxxxxxxxxxxx", previous_state=#<struct Aws::EC2::Types::InstanceState code=80, name="stopped">>]>
APIを実行後に意図したステータスに変更が完了したかを確認するためには、API実行後にステータスのチェックをポーリングする必要があります。ステータスのチェックは #describe_instances APIで可能です。
例えば、1分おきに10回まで状態を確認するのであれば以下のように実装できます。
Class: Aws::EC2::Client — AWS SDK for Ruby V3
10.times do |i| res = client.describe_instances(instance_ids: ["i-xxxxxxxxxxxxx"]) status = res.reservations[0].instances[0].state.name if status == "running" break end sleep(60) end
ただし、少し実装が直接的で煩わしいと思うかもしれません。そこで、Ruby SDKにはウェイターという仕組みがあります。 以下のようにウェイターを実行することで、インスタンスが指定のステータスになるまで待機します。
# インスタンスが runngin になるまで待機 client.wait_until(:instance_running, instance_ids:['i-xxxxxxxxxxxxxxxx'])
リトライ
APIとのやり取りにあたっては、サーバー側の一時的なエラー等で接続に失敗することがあるため、リトライの整理が必須となります。Ruby SDK でもリトライの仕組みが実装されており、デフォルトで3回リトライされます。また、リトライのアルゴリズムはデフォルトで、exponential backoffが用いられます。
これらの設定はカスタマイズが可能です。例えば、リトライ回数を5回に調整するには以下のように指定します。
client = Aws::EC2::Client.new( retry_limit: 5, )
その他のオプションについては、各サービスのクライアントのドキュメント等に詳細が記載されています。
https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/EC2/Client.html
ページング
API経由でのAWSのリソースの取得は大量になることがあるため、一度のAPI実行で取得しきれない場合、 Ruby SDKではバックグランドでページングを行い全件取得します。
レスポンスのインスタンスがEnumerableになっており、 Enumerable なメソッドを用いることで、リソース全件を参照できます。実際にコードで確認してみましょう。
IAMのポリシーはブログ執筆時点で、 1600 ほどあり、一度のAPIコールで100件取得されます。ページングの動作確認にちょうどいいので、これを使います。
まずは Enumerable なメソッドを使わずにレスポンス中に含まれるポリシーの数を確認します。すると100件であることが分かります。
# APIコールの動作を確認するためにデバッグモードで # クライアントを生成します client = Aws::IAM::Client.new( logger: Logger.new($stdout), log_level: :debug, ) res = client.list_policies.size # 100
次は、レスポンスに対して Enumerable なメソッドを呼んでみます。出力の結果をわかりやすく確認するため、最終的に取得できるポリシーの総数等を取得します。
count = 0 policies_count = 0 res = client.list_policies res.each do |r| count += 1 policies_count += r.policies.size p count # => インクリメント end p policies_count # => 1584
実行すると以下のような出力を得られます。
each 内でループするたびに、APIコールし、必要なデータを取得していることが見て取れます。 marker は前回リクエストからの続きのリソースを取得するのに必要なパラメータです。
D, [2025-09-17T11:14:42.659059 #13676] DEBUG -- : [Aws::IAM::Client 200 0.976706 0 retries] list_policies() 1 D, [2025-09-17T11:14:43.059577 #13676] DEBUG -- : [Aws::IAM::Client 200 0.398486 0 retries] list_policies(marker:"xxxxxxxxxxxxxxx") 2 D, [2025-09-17T11:14:43.300114 #13676] DEBUG -- : [Aws::IAM::Client 200 0.235317 0 retries] list_policies(marker:"xxxxxxxxxxxxxxx") ... 1584
アプリケーションの都合で、自動で全件取得するのではなく、自分で繰り返し処理をコントロールしたいときもあるかもしれません。そのような場合は、 例えば、以下のように marker を自分で取り回して処理することで、(この例では)100件ずつ処理を進めることができます。
res = client.list_policies loop do if res.is_truncated res = client.list_policies(marker: res.marker) else break end end
リソースインターフェース
また、リソースの情報の取得には、クライアントのインスタンスにより取得する方法とは別のアプローチが用意されています。 https://github.com/aws/aws-sdk-ruby#resource-interfaces
以下のように指定することで、AWSのリソースをより直感的に取得できます。
ec2 = Aws::EC2::Resource.new pp ec2.instances.first # Aws::EC2::Instance
ただし、こちらは提供されているサービスが限られているため、利用の前には注意が必要です。
Only a few services implement a resource interface. They are defined by hand in JSON and have limitations. Please use the Client API instead.
エラーハンドリング
次に、エラーハンドリグについて確認しておきたいと思います。EC2を例にすると、エラークラスの継承関係は以下のようになっています。
EC2の個別のエラー < Aws::EC2::Errors::ServiceError < Aws::Errors::ServiceError Module: Aws::EC2::Errors — AWS SDK for Ruby V3
すなわち、個別にハンドリングしたいエラーがある場合は、そのエラークラスを指定し、EC2サービス全体、あるいはAWSのサービス全体でハンドリングしたい場合は、それぞれ指定できます。
def test ... rescue Aws::EC2::Errors::InvalidInstanceIDNotFound => e # インスタンスIDが見つからなかった場合 rescue Aws::EC2::Errors::ServiceError => e # それ以外のEC2関係のエラー rescue Aws::Errors::ServiceError => e # EC2以外のAWSのエラー end
上記ドキュメントを確認すると分かるようにサービスによっては、エラークラスが動的に定義されている場合があるため、検証等を通じてエラークラスを確認しておく必要はあると思います。
Additionally, error classes are dynamically generated for service errors based on the error code if they are not defined above.
EC2では静的に定義されている個別のエラークラスはドキュメント上で確認できませんでしたが、例えばFSxでは静的に定義されているエラークラスが確認できますので、実装の際はまずはこれらを確認しておくと良さそうです。
AccessPointAlreadyOwnedByYou
ActiveDirectoryError
BackupBeingCopied
...
Module: Aws::FSx::Errors — AWS SDK for Ruby V3
テスト
アプリケーション開発ではテスト(Spec)の実装を行うことが多いと思います。AWSのリソース操作をスタブするための機能が Ruby SDK には用意されています。
クライアントのインスタンス生成時にスタブを行うことを指定し、ダミーのデータを登録します。
client = Aws::EC2::Client.new(stub_responses: true) client.stub_responses(:describe_volumes, { volumes: [ {volume_id: "volume-11111111", state: "available"}, ] }) response = client.describe_volumes pp response.volumes
以下のようにダミーのデータが取得されます。
[#<struct Aws::EC2::Types::Volume attachments=[], availability_zone=nil, create_time=nil, encrypted=nil, kms_key_id=nil, outpost_arn=nil, size=nil, snapshot_id=nil, state="available", volume_id="volume-11111111", iops=nil, tags=[], volume_type=nil, fast_restored=nil, multi_attach_enabled=nil>]
その他の使い方については以前別の記事でも書きましたので、こちらを参照頂けたらと思います。
おわりに
本記事では、AWS SDK for Rubyを用いてAWSのAPIプログラミングの基本をご紹介しました。どなたかのお役にたてば幸いです。
関連
紅林輝(くればやしあきら)(サービス開発部) 記事一覧
サービス開発部所属。2015年にサーバーワークスにJOIN。クラウドインテグレーション部を経て、現在はCloud Automatorの開発に従事。ドラクエ部。推しナンバーはⅤ、推しモンスターはクックルー。