チュートリアル:必須タグがない Amazon EC2 インスタンスの自動停止 - AWS リソースとタグエディタのタグ付け

AWS は、タグエディタのタグ管理機能を AWS Resource Groups コンソールから AWS Resource Explorer コンソールに移動しました。Resource Explorer を使用すると、リソースを検索してフィルタリングし、単一のコンソールからリソースタグを管理できます。Resource Explorer でのリソースタグの管理の詳細については、「Resource Explorer ユーザーガイド」の「リソースの管理」を参照してください。

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

チュートリアル:必須タグがない Amazon EC2 インスタンスの自動停止

管理する AWS リソースと のプールが大きくなる AWS アカウント につれて、タグを使用してリソースの分類を容易にすることができます。タグは一般的に、コスト配分やセキュリティなどの重要な用途に使用されます。 AWS リソースを効果的に管理するには、リソースに一貫してタグを付ける必要があります。多くの場合、リソースはプロビジョニングされると適切なタグがすべて付けられます。ただし、後のプロセスでタグが変更され、企業のタグポリシーから逸脱する可能性があります。タグの変更を監視することで、タグドリフトを特定してすぐに対応できます。これにより、リソースが適切に分類されているかどうかにかかっているプロセスが、望ましい結果を生み出すという確信が持てます。

次の例は、Amazon EC2 インスタンスのタグ変更を監視して、指定したインスタンスに必要なタグが引き続き存在することを確認する方法を示しています。インスタンスのタグが変更され、インスタンスに必要なタグがなくなった場合、Lambda 関数が呼び出されてインスタンスを自動的にシャットダウンします。なぜこれを行いたいのか これにより、効果的なコスト配分を実現したり、属性ベースのアクセス制御 (ABAC) に基づくセキュリティを信頼したりするために、すべてのリソースに企業のタグポリシーに従ってタグが付けられるようになります。

重要

このチュートリアルは、重要なインスタンスをうっかりシャットダウンすることがない非運用アカウントで実行することを強くお勧めします。

このチュートリアルのサンプルコードでは、このシナリオの影響をインスタンス ID のリストにあるインスタンスのみに意図的に制限しています。テストのためにシャットダウンしてもよいインスタンス ID でリストを更新する必要があります。これにより、 のリージョン内のすべてのインスタンスを誤ってシャットダウンすることがなくなります AWS アカウント。

テスト後は、すべてのインスタンスが貴社のタグ付け戦略に従ってタグ付けされていることを確認します。その後、リスト上のインスタンス ID のみに機能を制限しているコードを削除できます。

この例では JavaScript と Node.js の 16.x バージョンを使用しています。この例では、 AWS アカウント サンプル ID 123456789012 と AWS リージョン 米国東部 (バージニア北部) () を使用していますus-east-1。テストアカウント ID とリージョンを自身のものに置き換えます。

注記

コンソールのデフォルトに別のリージョンを使用している場合は、コンソールを変更するたびに、このチュートリアルで使用しているリージョンを必ず切り替えてください。このチュートリアルが失敗する一般的な原因は、インスタンスと関数が 2 つの異なるリージョンにあることです。

us-east-1 とは異なるリージョンを使用する場合は、以下のコード例のすべての参照コードを、選択したリージョンに変更してください。

ステップ 1. Lambda 関数を作成する

Lambda 関数を作成するには
  1. AWS Lambda マネジメントコンソールを開きます。

  2. 関数の作成を選択し、一から作成を選択します。

  3. 関数名 に「AutoEC2Termination」と入力します。

  4. ランタイムNode.js 16.x を選択します。

  5. 他のすべてのフィールドはデフォルト値のままにして、関数の作成 選択します。

  6. AutoEC2Termination詳細ページの「コード」タブで、index.js ファイルを開いてコードを表示します。

    • index.js のタブが開いている場合は、そのタブの編集ボックスを選択してコードを編集できます。

    • index.js のタブが開いていない場合は、ナビゲーションウィンドウで AutoEC2Terminator フォルダにある index.js ファイルを右クリックします。次に、Open を選択します。

  7. index.js タブのエディタボックスに次のコードを貼り付け、既存のコードを置き換えます。

    RegionToMonitor 値を、この関数を実行したいリージョンに置き換えます。

    // Set the following line to specify which Region's instances you want to monitor // Only instances in this Region are succesfully stopped on a match const RegionToMonitor = "us-east-1" // Specify the instance ARNs to check. // This limits the function for safety to avoid the tutorial shutting down all instances in account // The first ARN is a "dummy" that matches the test event you create in Step 3. // Replace the second ARN with one that matches a real instance that you want to monitor and that you can // safely stop const InstanceList = [ "i-0000000aaaaaaaaaa", "i-05db4466d02744f07" ]; // The tag key name and value that marks a "valid" instance. Instances in the previous list that // do NOT have the following tag key and value are stopped by this function const ValidKeyName = "valid-key"; const ValidKeyValue = "valid-value"; // Load and configure the AWS SDK const AWS = require('aws-sdk'); // Set the AWS Region AWS.config.update({region: RegionToMonitor}); // Create EC2 service object. const ec2 = new AWS.EC2({apiVersion: '2016-11-15'}); exports.handler = (event, context, callback) => { // Retrieve the details of the reported event. var detail = event.detail; var tags = detail["tags"]; var service = detail["service"]; var resourceType = detail["resource-type"]; var resource = event.resources[0]; var resourceSplit = resource.split("/"); var instanceId = resourceSplit[resourceSplit.length - 1]; // If this event is not for an EC2 resource, then do nothing. if (!(service === "ec2")) { console.log("Event not for correct service -- no action (", service, ")" ); return; } // If this event is not about an instance, then do nothing. if (!(resourceType === "instance")) { console.log("Event not for correct resource type -- no action (", resourceType, ")" ); return; } // CAUTION - Removing the following 'if' statement causes the function to run against // every EC2 instance in the specified Region in the calling AWS アカウント. // If you do this and an instance is not tagged with the approved tag key // and value, this function stops that instance. // If this event is not for the ARN of an instance in our include list, then do nothing. if (InstanceList.indexOf(instanceId)<0) { console.log("Event not for one of the monitored instances -- no action (", resource, ")"); return; } console.log("Tags changed on monitored EC2 instance (",instanceId,")"); // Check attached tags for expected tag key and value pair if ( tags.hasOwnProperty(ValidKeyName) && tags[ValidKeyName] == "valid-value"){ // Required tags ARE present console.log("The instance has the required tag key and value -- no action"); callback(null, "no action"); return; } // Required tags NOT present console.log("This instance is missing the required tag key or value -- attempting to stop the instance"); var params = { InstanceIds: [instanceId], DryRun: true }; // call EC2 to stop the selected instances ec2.stopInstances(params, function(err, data) { if (err && err.code === 'DryRunOperation') { // dryrun succeeded, so proceed with "real" stop operation params.DryRun = false; ec2.stopInstances(params, function(err, data) { if (err) { console.log("Failed to stop instance"); callback(err, "fail"); } else if (data) { console.log("Successfully stopped instance", data.StoppingInstances); callback(null, "Success"); } }); } else { console.log("Dryrun attempt failed"); callback(err); } }); };
  8. ディプロイを選択して変更を保存し、新しいバージョンの関数をアクティブにします。

この Lambda 関数は、EventBridge のタグ変更イベントによって報告された Amazon EC2 インスタンスのタグをチェックします。この例では、イベント内のインスタンスに必要なタグキー valid-key がない場合や、そのタグに valid-value 値がない場合、関数はインスタンスを停止しようとします。このロジカルチェックやタグ要件は、各自の使用事例に合わせて変更できます。

Lambda コンソールのウィンドウは開いたままにします。

ステップ 2. 必要な IAM アクセス権限をセットアップする

関数を正常に実行するには、EC2 インスタンスを停止する権限を関数に付与する必要があります。 AWS 指定されたロールには、そのアクセス許可lambda_basic_executionがありません。このチュートリアルでは、AutoEC2Termination-role-uniqueid という名前の関数の実行ロールにアタッチされているデフォルトの IAM アクセス権限ポリシーを変更します。このチュートリアルで最低限必要な追加権限は ec2:StopInstances です。

Amazon EC2 固有の IAM ポリシーの作成に関する詳細情報は、「IAM ユーザーガイド」の「Amazon EC2: EC2 インスタンスの起動または停止、およびセキュリティグループの変更を、プログラムによりおよびコンソールで許可する」を参照してください。

IAM アクセス権限ポリシーを作成して Lambda 関数の実行ロールにアタッチするには
  1. 別のブラウザタブまたはウィンドウで、IAM コンソールの Roles (ロール)ページを開きます。

  2. ロール名 AutoEC2Termination の入力を開始し、リストに表示されたらそのロール名を選択します。

  3. ロールの 概要ページで 権限タブを選択し、すでにアタッチされている 1 つのポリシーの名前を選択します。

  4. ポリシーの概要ページで ポリシーの編集を選択します。

  5. ビジュアルエディタタブで、さらにアクセス許可を追加する を選択します。

  6. サービスEC2 を選択します。

  7. アクションStopInstancesを選択します。検索バーで Stop と入力して、検索バーが表示されるタイミングで StopInstances を選択します。

  8. リソースすべてのリソースを選択し、レビューポリシーを選択し、最後に変更を保存を選択します。

    これにより、ポリシーの新しいバージョンが自動的に作成され、デフォルトとしてこのバージョンが設定されます。

    最終的なポリシーは次の例のようになります。

    { "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": "ec2:StopInstances", "Resource": "*" }, { "Sid": "VisualEditor1", "Effect": "Allow", "Action": "logs:CreateLogGroup", "Resource": "arn:aws:logs:us-east-1:123456789012:*" }, { "Sid": "VisualEditor2", "Effect": "Allow", "Action": [ "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/AutoEC2Termination:*" } ] }

ステップ 3. Lambda 関数の予備テストを行います。

このステップでは、関数にテストイベントを送信します。Lambda テスト機能は、手動で提供したテストイベントを送信することで機能します。この関数は、あたかもイベントが EventBridge から発生したかのようにテストイベントを処理します。異なる値で複数のテストイベントを定義して、コードのさまざまな部分をすべて試すことができます。このステップでは、Amazon EC2 インスタンスのタグが変更されましたが、新しいタグには必要なタグキーと値が含まれていないことを示すテストイベントを送信します。

Lambda 関数をテストします。
  1. Lambda コンソールのウィンドウまたはタブに戻り、「AutoEC2Termination 関数の テストタブを開きます。

  2. 新規イベントの作成 ()を選択します。

  3. イベント名()で、SampleBadTagChangeEvent と入力します。

  4. イベント JSON ()内のテキストを、次のテキスト例に示されているサンプルイベントに置き換えます。このテストイベントが正しく動作するためには、アカウント、リージョン、インスタンス ID を変更する必要はありません。

    { "version": "0", "id": "bddcf1d6-0251-35a1-aab0-adc1fb47c11c", "detail-type": "Tag Change on Resource", "source": "aws.tag", "account": "123456789012", "time": "2018-09-18T20:41:38Z", "region": "us-east-1", "resources": [ "arn:aws:ec2:us-east-1:123456789012:instance/i-0000000aaaaaaaaaa" ], "detail": { "changed-tag-keys": [ "valid-key" ], "tags": { "valid-key": "NOT-valid-value" }, "service": "ec2", "resource-type": "instance", "version": 3 } }
  5. Save (保存) を選択してから、テストを選択します。

    テストは失敗したようですが、問題ありません。

    レスポンス ()の 実行結果 ()タブに次のエラーが表示されるはずです。

    { "errorType": "InvalidInstanceID.NotFound", "errorMessage": "The instance ID 'i-0000000aaaaaaaaaa' does not exist", ... }

    このエラーは、テストイベントで指定されたインスタンスが存在しないために発生します。

    [関数ログ] セクションの [実行結果]タブの情報は、Lambda 関数が EC2 インスタンスを正常に停止しようとしたことを示しています。しかし、コードで最初にインスタンスを停止する DryRun 操作が試行され、インスタンス ID が無効であることが示されたため、失敗しました。

    START RequestId: 390c1f8d-0d9b-4b44-b087-8de64479ab44 Version: $LATEST 2022-11-30T20:17:30.427Z 390c1f8d-0d9b-4b44-b087-8de64479ab44 INFO Tags changed on monitored EC2 instance ( i-0000000aaaaaaaaaa ) 2022-11-30T20:17:30.427Z 390c1f8d-0d9b-4b44-b087-8de64479ab44 INFO This instance is missing the required tag key or value -- attempting to stop the instance 2022-11-30T20:17:31.206Z 390c1f8d-0d9b-4b44-b087-8de64479ab44 INFO Dryrun attempt failed 2022-11-30T20:17:31.207Z 390c1f8d-0d9b-4b44-b087-8de64479ab44 ERROR Invoke Error {"errorType":"InvalidInstanceID.NotFound","errorMessage":"The instance ID 'i-0000000aaaaaaaaaa' does not exist","code":"InvalidInstanceID.NotFound","message":"The instance ID 'i-0000000aaaaaaaaaa' does not exist","time":"2022-11-30T20:17:31.205Z","requestId":"a5192c3b-142d-4cec-bdbc-685a9b7c7abf","statusCode":400,"retryable":false,"retryDelay":36.87870631147607,"stack":["InvalidInstanceID.NotFound: The instance ID 'i-0000000aaaaaaaaaa' does not exist"," at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/services/ec2.js:50:35)"," at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:106:20)"," at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:78:10)"," at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:686:14)"," at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)"," at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)"," at /var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10"," at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9)"," at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:688:12)"," at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:116:18)"]} END RequestId: 390c1f8d-0d9b-4b44-b087-8de64479ab44
  6. 正しいタグが使用されてもコードがインスタンスを停止しようとしないことを確認するには、別のテストイベントを作成して送信します。

    コードソースの上にある テスト タブを選択します。コンソールには既存の SampleBadTagChangeEvent テストイベントが表示されます。

  7. 新規イベントの作成 ()を選択します。

  8. イベント名 に、「SampleGoodTagChangeEvent」と入力します。

  9. 17 行目で、NOT- を削除して値を valid-value に変更します。

  10. テストイベントウィンドウの上部で 保存を選択し、次に テストを選択します。

    出力には以下が表示されます。これは、関数が有効なタグを認識し、インスタンスをシャットダウンしようとしないことを示しています。

    START RequestId: 53631a49-2b54-42fe-bf61-85b9e91e86c4 Version: $LATEST 2022-12-01T23:24:12.244Z 53631a49-2b54-42fe-bf61-85b9e91e86c4 INFO Tags changed on monitored EC2 instance ( i-0000000aaaaaaaaaa ) 2022-12-01T23:24:12.244Z 53631a49-2b54-42fe-bf61-85b9e91e86c4 INFO The instance has the required tag key and value -- no action END RequestId: 53631a49-2b54-42fe-bf61-85b9e91e86c4

    ブラウザで Lambda コンソールを開いておきます。

ステップ 4. 関数を起動する EventBridge ルールを作成するには

これで、イベントと一致し、Lambda 関数を指す EventBridge ルールを作成できます。

EventBridge ルールを作成するには
  1. 別のブラウザタブまたはウィンドウで、EventBridgeコンソールを開いて ルールの作成ページを開きます。

  2. 名前 に「ec2-instance-rule」と入力し、次へを選択します。

  3. 作成方法 まで下にスクロールし、カスタムパターン (JSON エディタ)を選択します。

  4. 編集ボックスに、次のパターンテキストを貼り付け、「次へを選択します。

    { "source": [ "aws.tag" ], "detail-type": [ "Tag Change on Resource" ], "detail": { "service": [ "ec2" ], "resource-type": [ "instance" ] } }

    このルールは Amazon EC2 インスタンスの Tag Change on Resource イベントを照合し、次のステップでターゲットとして指定したものをすべて呼び出します。

  5. 次に、ターゲットとして Lambda 関数を追加します。ターゲット 1ボックスの ターゲットの選択で、Lambda 関数を選択します。

  6. 関数 で、前に作成した AutoEC2Termination 関数を選択し、次へ を選択します。

  7. ログ記録の設定ページで、次へをクリックします。確認して作成ページで、ルールの作成を選択します。これにより、指定された Lambda 関数を呼び出す EventBridge のアクセス許可も自動的に付与されます。

ステップ 5. ソリューション全体をテストしてください。

EC2 インスタンスを作成し、タグを変更するとどうなるかを確認することで、最終結果をテストできます。

モニタリングソリューションを実際のインスタンスでテストするには
  1. Amazon EC2 コンソールインスタンスページを開きます。

  2. Amazon EC2 インスタンスを作成します。起動する前に、キー valid-key と値 valid-value を含むタグをアタッチしてください。インスタンスの作成と起動の詳細については、Amazon EC2 ユーザーガイドの「ステップ 1: インスタンスを起動する」を参照してください。「インスタンスを起動するには」手順のステップ 3 で、名前タグを入力し、その他のタグを追加 を選択し、タグを追加を選択してから、 valid-keyキーvalid-valueを入力します。このインスタンスがこのチュートリアルのみを目的としており、完了後にこのインスタンスを削除する予定がある場合は、キーのペアなしで続行できます。ステップ 1 が終わったら、このチュートリアルに戻ってください。ステップ 2: インスタンスに接続する必要はありません。

  3. インスタンスId をコンソールからコピーします。

  4. Amazon EC2 コンソールから Lambda コンソールに切り替えます。AutoEC2 Termination関数を選択し、コードタブを選択し、次に index.jsタブを選択してコードを編集します。

  5. Amazon EC2 コンソールからコピーした値を貼り付けて、 InstanceList の 2 番目のエントリを変更します。RegionToMonitor 値が、貼り付けたインスタンスを含むリージョンと一致することを確認してください。

  6. ディプロイを選択して変更を有効にします。これで、指定したリージョンのインスタンスへのタグ変更によって関数を有効化する準備が整いました。

  7. Lambda コンソールから Amazon EC2 コンソールに切り替えます。

  8. valid-key を削除するか、そのキーの値を変更して、インスタンスにアタッチされている タグを変更します。

    注記

    実行中の Amazon EC2 インスタンスのタグを変更する方法については、Amazon EC2 ユーザーガイドの「個々のリソースのタグの追加と削除」を参照してください。

  9. 数秒間待ってから、コンソールを更新します。インスタンスは 、インスタンスの状態停止中に変更し、次に 停止済みに変更する必要があります。

  10. Amazon EC2 コンソールから関数を使用して Lambda コンソールに切り替え、監視 タブを選択します。

  11. ログ」タブを選択し、最近の呼び出し」 ()テーブルで、ログストリーム 列の最新のエントリを選択します。

    Amazon CloudWatch コンソールが開き、Lambda 関数を最後に呼び出したときの ログイベント ページが表示されます。最後のエントリーは次のように表示されます。

    2022-11-30T12:03:57.544-08:00 START RequestId: b5befd18-2c41-43c8-a320-3a4b2317cdac Version: $LATEST 2022-11-30T12:03:57.548-08:00 2022-11-30T20:03:57.548Z b5befd18-2c41-43c8-a320-3a4b2317cdac INFO Tags changed on monitored EC2 instance ( arn:aws:ec2:us-west-2:123456789012:instance/i-1234567890abcdef0 ) 2022-11-30T12:03:57.548-08:00 2022-11-30T20:03:57.548Z b5befd18-2c41-43c8-a320-3a4b2317cdac INFO This instance is missing the required tag key or value -- attempting to stop the instance 2022-11-30T12:03:58.488-08:00 2022-11-30T20:03:58.488Z b5befd18-2c41-43c8-a320-3a4b2317cdac INFO Successfully stopped instance [ { CurrentState: { Code: 64, Name: 'stopping' }, InstanceId: 'i-1234567890abcdef0', PreviousState: { Code: 16, Name: 'running' } } ] 2022-11-30T12:03:58.546-08:00 END RequestId: b5befd18-2c41-43c8-a320-3a4b2317cdac

チュートリアルのまとめ

このチュートリアルでは、Amazon EC2 インスタンスのリソースイベントのタグ変更と照合する EventBridge ルールを作成する方法を示しました。このルールは、必要なタグがない場合にインスタンスを自動的にシャットダウンする Lambda 関数を指していました。

AWS リソースのタグ変更に対する Amazon EventBridge のサポートにより、多くの でイベント駆動型のオートメーションを構築できます AWS のサービス。この機能と を組み合わせると AWS Lambda 、 AWS リソースに安全にアクセスし、オンデマンドでスケールし、コスト効率の高いサーバーレスソリューションを構築するためのツールが提供されます。

リソース上でのタグ変更 EventBridge イベントのその他の使用事例としては、次のものが考えられます。

  • 誰かが通常とは異なる IP アドレスからリソースにアクセスした場合に警告を表示する — タグを使用して、リソースにアクセスする各訪問者のソース IP アドレスを保存します。タグを変更すると CloudWatch イベントが生成されます。このイベントを使用して、ソース IP アドレスを有効な IP アドレスのリストと比較し、ソース IP アドレスが有効でない場合は警告メールをアクティブ化できます。

  • リソースのタグベースのアクセス制御に変更がないか監視する属性(タグ)ベースのアクセス制御 (ABAC) を使用してリソースへのアクセスを設定している場合、タグへの変更によって生成された EventBridge イベントを使用して、セキュリティチームによる監査を促すことができます。