2025/08/19
対象を実行中のインスタンスのみに変更
インスタンスの起動手順によっては対象のインスタンスを正しく抽出できていなかった問題を修正
概要
必要にかられて、こんなものを作ったのでメモがてら。
- EventBridgeから定期的に
- Lambdaを起動して
- 指定された名前に合致する実行中のインスタンスに対して
- reboot(またはterminate)のリクエストを出す
作成手順
IAM
- ロールを作成
- 信頼されたエンティティを選択
- 信頼されたエンティティタイプ → AWSのサービス
- ユースケース → Lambda
- 許可を追加
- 許可ポリシー
- (何もしなくてOK)
- 許可の境界を設定
- 許可の境界なしでロールを作成(デフォルト)
- 許可ポリシー
- 名前、確認、および作成
- ロールの詳細
- ロール名 → それなりの名前(
InstanceRestarter-role等) - 説明 → お好きに
- ロール名 → それなりの名前(
- ロールの詳細
- 信頼されたエンティティを選択
- 作成したロールを選択
- 許可タブ内から
許可を追加 → インラインポリシーを作成を選択- アクセス許可を指定
- ポリシーエディタで
JSONを選択してIAM.jsonの内容を貼り付ける- rebootではなくterminateをする場合には貼り付け後に、JSON内の
ec2:RebootInstancesをec2:TerminateInstancesに書き換える
- rebootではなくterminateをする場合には貼り付け後に、JSON内の
- JSON内の
XXXXXXXXXXXXをAWSのアカウントIDに書き換える
- ポリシーエディタで
- 確認して作成
- ポリシーの詳細
- ポリシー名 → それなりの名前(
InstanceRestarter-role-policy等)
- ポリシー名 → それなりの名前(
- ポリシーの詳細
- アクセス許可を指定
Lambda
-
関数の作成ボタン- 基本的な情報
- 関数名 → それなりの名前(
InstanceRestarter-lambda等) - ランタイム →
Ruby(最新のサポート対象のものでOK) - アーキテクチャ →
x86_64 - アクセス権限 → デフォルトの実行ロールの変更 → 既存のロールを使用する
- 既存のロール → 先ほど作成したIAMを選択
- 関数名 → それなりの名前(
- 詳細設定 → すべて未チェック(デフォルト)のまま
- 基本的な情報
-
コードタブ-
lambda_function.rbをダブルクリックで開き、lambda_function.rbの内容を貼り付け、Deployボタン- rebootではなくterminateをする場合には貼り付け後に、ソース内の
ec2_client.reboot_instancesをec2_client.terminate_instancesに書き換え、Deployボタン
- rebootではなくterminateをする場合には貼り付け後に、ソース内の
-
-
設定タブ- 一般設定
- タイムアウトを必要に応じて変更する
- 30秒とか
- タイムアウトを必要に応じて変更する
- 環境変数
- キー
INSTANCE_NAMESを追加し、値として対象としたいEC2インスタンスの名前を空白区切りで列挙する
- キー
- 一般設定
EventBridge
- 左メニュー
バス>ルール内のルールを作成ボタン- ルールの詳細
- 名前 → それなりの名前(
InstanceRestarter-schedule-rule等) - 説明 → お好きに
- イベントバス → お好きに
- 選択したイベントバスでルールを有効にする → ON
- ルールタイプ → スケジュール
-
メインのボタンEventBridge Scheduler で続行ではなく続行してルールを作成するボタンで次の項目へ
- 名前 → それなりの名前(
- スケジュールを定義
- スケジュールパターン → お好きに
- 毎日3時に定期実行であれば
cron(0 18 * * ? *) - 毎日5時に定期実行であれば
cron(0 20 * * ? *)
- 毎日3時に定期実行であれば
- スケジュールパターン → お好きに
- ターゲットを選択
- ターゲットタイプ → AWSのサービス
- ターゲットを選択 → Lambda関数
- 関数 → 先ほど作成したLambdaを選択
- バージョン/エイリアスを設定
- デフォルト
- 追加設定
- すべてデフォルトのまま
- ルールの詳細
ログ
(Lambdaが実行された後に)CloudWatch Logsのロググループ/aws/lambda/{Lambda関数名}に出力される。
必要に応じてロググループの保持期間を設定する。
内容としては以下の通り
- 指定された名前の実行中インスタンスが見つからないとき
#{name}: not found.
- 指定された名前の実行中インスタンスに対しリスタート要求を出したとき
#{name}: restart #{instance_id}- 同じ名前で複数のインスタンスがあれば複数行出力される
ソース一覧
IAM.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"ec2:RebootInstances"
],
"Resource": [
"arn:aws:ec2:ap-northeast-1:XXXXXXXXXXXX:instance/*"
]
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:*:*:*"
]
}
]
}
lambda_function.rb
require 'aws-sdk-ec2'
require 'json'
def lambda_handler(event:, context:)
instance_names = ENV['INSTANCE_NAMES'].split
ec2_client = Aws::EC2::Client.new()
instance_names.each do |name|
describe_instances = ec2_client.describe_instances({
filters: [
{
name: 'instance-state-name',
values: ['running']
},
{
name: 'tag-key',
values: ['Name'],
},
{
name: 'tag-value',
values: [name],
},
]
})
if describe_instances.reservations.empty? then
puts "#{name}: not found."
next
end
describe_instances.reservations.each do |reservaion|
reservaion.instances.each do |instance|
puts "#{name}: restart #{instance.instance_id}"
ec2_client.terminate_instances({
instance_ids: [
instance.instance_id,
],
})
end
end
end
{ statusCode: 200, body: 'finish.' }
end