概要
必要にかられて、こんなものを作ったのでメモがてら。
- 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: 'tag-key',
values: ['Name'],
},
{
name: 'tag-value',
values: [name],
},
]
})
if describe_instances.reservations.empty? then
puts "#{name}: not found."
next
end
describe_instances.reservations[0].instances.each do |item|
puts "#{name}: restart #{item.instance_id}"
ec2_client.reboot_instances({
instance_ids: [
item.instance_id,
],
})
end
end
{ statusCode: 200, body: 'finish.' }
end