AWS環境で作業していると、マネジメントコンソールでは操作できるのに、AWS CLIから実行すると失敗することがあります。
今回のトラブルは、その典型例です。
AWS CLIからAWS Backup関連のAPIを実行しようとしたところ、AWS Backupのサービスエンドポイントに通信できませんでした。
最初は、IAM権限不足、AWS CLIの設定ミス、認証情報の不備を疑いました。
しかし、原因はそこではありませんでした。
問題は、AWS CLIがAWSサービスのAPIエンドポイントへ到達するための通信経路が、実行環境側で正しく設定されていなかったことです。
今回のトラブル
具体的には、AWS CLIを使ってAWS Backup関連の操作を自動化しようとした際に、対象サービスのエンドポイントへ到達できず、コマンドが失敗しました。
AWS CLIとは、AWSが提供しているコマンドラインツールです。
マネジメントコンソールから画面操作する代わりに、コマンドでAWSサービスを操作できます。
たとえば、EC2、S3、RDS、CloudWatch、AWS Backupなど、さまざまなAWSサービスに対して、コマンドやスクリプトからAPIを実行できます。
運用作業を自動化したり、複数サービスをまたいだ処理をスクリプト化したりする場合、AWS CLIは非常に便利です。
ただし、AWS CLIはローカルのコマンドに見えても、実際にはAWSサービスのAPIエンドポイントへHTTPS通信を行っています。
つまり、AWS CLIを使うには、認証情報やIAM権限だけでなく、AWSサービスのエンドポイントへ到達できるネットワーク経路も必要です。
ここを見落とすと、CLIコマンド自体は正しくても通信できません。
何が起きていたのか
対象環境は、セキュリティ要件の強い閉域寄りのAWS環境でした。
EC2インスタンスは、インターネットへ直接通信する構成ではありません。
外部通信が必要な場合は、プロキシサーバを経由する設計になっていました。
AWSサービスへのAPI通信についても、VPCエンドポイント経由で閉じるのか、プロキシ経由でAWSサービスのエンドポイントへ到達させるのかを整理する必要があります。
今回の環境では、AWS CLIからAWS Backup APIを呼び出す際、プロキシ経由でAWSサービスエンドポイントへ到達させる必要がありました。
しかし、そのプロキシ設定がAWS CLIの実行環境に反映されていませんでした。
その結果、AWS CLIを実行しても、AWS Backupのサービスエンドポイントへ到達できず、通信エラーになりました。
今回の構成を図にすると、次のようになります。

図 AWS CLIからAWS Backup APIに通信できないトラブルのイメージ図
原因
原因は、AWS CLIのプロキシ設定不足です。
もう少し正確に言うと、AWS CLIがAWSサービスのAPIエンドポイントへ通信するための経路が、実行環境側で有効になっていませんでした。
閉域寄りのAWS環境では、AWSサービスへの通信経路を意識する必要があります。
VPCエンドポイントを用意して閉域内でAWSサービスへ接続するのか。
NAT Gatewayやプロキシサーバを経由して、AWSサービスのエンドポイントへ接続するのか。
どちらを使うかは、サービスの対応状況、ネットワーク設計、セキュリティ要件、運用方針によって変わります。
今回のトラブルでは、AWS Backupそのものの操作内容ではなく、AWS CLIを実行するサーバからAWS Backup APIへ到達するためのプロキシ設定が不足していました。
AWS CLIのコマンド、認証情報、IAM権限だけを見ていると、この原因には気づきにくくなります。
IAM権限の問題ではなかった
この手のトラブルで、最初に疑われやすいのはIAM権限です。
たしかに、AWS CLIで操作する場合、IAMロールやIAMユーザーに必要な権限がなければAPIは失敗します。
しかし、IAM権限不足とネットワーク到達不可は別の問題です。
IAM権限不足であれば、AccessDenied系のエラーになります。
今回のようにサービスエンドポイントへ通信できない場合は、認証や認可以前に、そもそもAPIの宛先へ到達できていません。
確認すべきは、まずAWS CLIの認証情報が正しいかどうかであり、次にIAM権限が足りているかどうかであり、最後にAWSサービスのエンドポイントへネットワーク的に到達できるかどうかです。
閉域環境では、この最後の到達可否が意外と見落とされます。
対策
対策は、AWS CLIがプロキシサーバを経由してAWSサービスのAPIエンドポイントへ到達できるように設定することです。
AWS CLIでは、プロキシサーバを利用する場合、HTTP_PROXY や HTTPS_PROXY といった環境変数を設定します。
たとえば、Linux系の環境であれば、次のような設定です。
export HTTPS_PROXY=http://proxy.example.local:8080
export HTTP_PROXY=http://proxy.example.local:8080
プロキシを経由させたくない宛先がある場合は、必要に応じて NO_PROXY も設定します。
export NO_PROXY=169.254.169.254,localhost,127.0.0.1
ここで重要なのは、手作業で一時的に export して終わりにしないことです。
対話ログイン時の設定だけで済ませてよいのか、シェルスクリプト実行時にも同じ設定が必要なのか、cronやジョブ管理ツールから実行する場合にも環境変数が引き継がれるのかを確認する必要があります。
rootユーザーと一般ユーザーで設定差がないか、systemdサービスから実行される可能性はないか、プロキシ認証は必要か、NO_PROXY に整理すべき宛先はないか。
こうした点まで含めて、AWS CLIをどこから、誰の権限で、どう実行するのかを整理しておく必要があります。
運用で使うAWS CLIであれば、個人のシェル設定ではなく、共通設定やジョブ実行環境側の設定として管理する方が安全です。
チェックリスト
今回のようなトラブルを防ぐには、最低限、次の観点を確認しておくとよいです。
AWS CLIを実行するサーバを特定しているか
AWS CLIを実行するユーザーを特定しているか
AWSサービスAPIへの通信経路が、VPCエンドポイント経由なのかプロキシ経由なのか整理しているか
プロキシ経由の場合、AWS CLI実行時に
HTTPS_PROXY/HTTP_PROXYが有効になっているか手動実行とジョブ実行で、環境変数や実行ユーザーに差分がないか
この5点だけでも、かなりの切り分けができます。
特に最後の「手動実行とジョブ実行の差分」は重要です。
手作業では動いても、ジョブから実行すると失敗することがあります。検証用ユーザーでは問題なくても、運用ユーザーでは環境変数が設定されておらず、同じコマンドが失敗することもあります。
このようなトラブルは、AWS CLIそのものの問題ではなく、実行環境の差分で起きることがあります。
所感
今回のトラブルは、AWS Backupだけの問題ではありません。
AWS CLIを使ってAWSサービスを操作する場合、裏側ではAWSサービスのAPIエンドポイントへ通信しています。
そのため、閉域環境やプロキシ必須環境では、AWS CLIの通信経路を設計しておかないと、思わぬところで止まります。
マネジメントコンソールで見えているから大丈夫。
IAM権限を付けたから大丈夫。
AWS CLIがインストールされているから大丈夫。
そう考えてしまうと、API通信経路の確認が抜けます。
特に、バックアップ、監視、ログ収集、ジョブ実行、運用自動化のような領域では、AWS CLIやSDKを使う場面が多くなります。
そのたびに個別対応すると、設定が属人化します。
今回の教訓は、AWS CLIのトラブルをCLI単体の問題として見ないことです。
AWS CLIが通信できないときは、コマンドの書き方だけでなく、そのコマンドがどのAWSサービスAPIに、どの経路で、どの実行ユーザーから到達しようとしているのかを見る。
そこまで含めて確認することが、クラウド移行後の運用トラブルを減らすポイントだと思います。
今回のようなトラブルは、構築フェーズに入ってから初めて表面化することが多い設計リスクの一つです。AWS CLIの通信経路をどう確保するかも、本来は構築前のPoCで確認しておくべき項目に含まれます。
クラウドリフトのPoCでどこまで確認しておくべきかについては、以下の記事で整理しています。
【第1部】クラウドリフトの失敗は構築前に始まっている|PoC不足が手戻り・コスト超過・納期遅延を招く理由
参考リンク
AWS Backup と AWS PrivateLink 接続
https://docs.aws.amazon.com/aws-backup/latest/devguide/backup-network.htmlAWS CLIでHTTPプロキシを使用する
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-proxy.htmlAWS Backup エンドポイントとクォータ
https://docs.aws.amazon.com/general/latest/gr/bk.html



コメント