EC2 Systems ManagerでAMIの日次取得をやってみた
こんにちわ。大阪のガノタです。 EC2 Systems Managerの「Maintenance Windows」を使って、AMIを日次取得してみる機会があったのでご紹介します。 基本的には、過去のブログエントリの組み合わせで実現可能ですが、今回は設定の最初から最後までご紹介したいと思います。
今回の概要
以下の内容で行ってみたいと思います。
- 特定タグの付いたインスタンスのAMIを日次で取得
- 対象はAmazon Linuxを利用
- AMIの保持は3世代
- 指定世代よりも古いAMIは削除
- AWS CLIでAMIの取得と簡易的な世代管理
手順の概要
主な作業項目は下記の通りです。
- 対象インスタンスにSSM Agentのインストール
- 対象インスタンスにタグ設定
- IAM Roleの作成
- メンテナンスウィンドウの作成
- メンテナンスウィンドウにターゲットを設定
- メンテナンスウィンドウにタスクを設定
それでは見ていきたいと思います。
作業手順
SSM Agentインストール
最初に対象インスタンスにSSM Agentをインストールします。インストール手順は下記に詳細があります。インストール作業はドキュメントの通りで難しいものではないので、詳細は割愛させて頂きます。
SSM エージェントのインストール - Amazon EC2 Systems Manager
対象インスタンスにタグ設定
今回は、「ami-backup」というタグが「true」になっているEC2を対象にしたいと思います。下記では3台のうち1台が停止している為、実際にAMIを作成できるのは稼働している2台になります。
IAM Roleの作成
まず、Maintenance Windowを実行するためのRoleを作成します。今回は「MySsmMainteWindow」という名前で作成し、「AmazonSSMMaintenanceWindowRole」 というポリシーをアタッチします。
次に信頼関係として 「ssm.amazonaws.com」 を追加します。
追加するには 「Trust Relationships」 タブをクリックします。下記の様に「ssm.amazonaws.com」を追加します。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": [ "ssm.amazonaws.com", "ec2.amazonaws.com" ] }, "Action": "sts:AssumeRole" } ] }
次にAMIを取得・削除するための権限をEC2のIAM Roleに追加します。また、AMIの取得は「Run Command」で実行される為、AmazonEC2RoleforSSM
ポリシーも追加します。
AMI操作のポリシー(DailyAmiBackup)は下記の内容で追加しています。要件に応じたポリシー内容にして下さい。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1491462535000", "Effect": "Allow", "Action": [ "ec2:CreateImage", "ec2:DeregisterImage", "ec2:DescribeImages" ], "Resource": [ "*" ] } ] }
メンテナンスウィンドウの作成
次にメンテナンスウィンドウを設定します。初めての場合は下記のようなページが表示されますが、このまま 「Create Maintenance Window」 をクリックします。
次の画面で詳細を設定します。 「Name」 はこのメンテナンスウィンドウの名称です。今回は「daily-ami-backup」としました。
実行タイミングは、今回は 「CRON」 形式を選択してcron(0 16 * * ? *)
と設定しました。これは「日本時間のAM01:00」に指定の処理が実行されることを意味します。
その他の項目として「Duration」を「2」として、「Stop initiating tasks」を「1」にしています。これは 「メンテナンスウィンドウが終了する1時間前になれば新たなタスクは実行しない」 という意味になります。
尚、EC2 Systems Managerで指定できるCron書式は下記に詳細が記載されています。
Systems Manager の cron スケジュール - Amazon EC2 Systems Manager
メンテナンスウィンドウのターゲット設定
次に、メンテナンスウィンドウの実行対象を設定します。対象は 「ターゲット」 として設定します。
他の設定方法として、画面下の「Targets」タブにある「Registar new targets」から設定しても構いません。
今回は、タグを使ってターゲットを指定します。タグで制御できれば後から対象を変更することができて便利です。 下記のように 「Select targets by」 でターゲットの指定方法を 「Specifying tags」 にします。「Tag Filters」 でタグの指定と設定値を指定します。
ターゲットは複数設定できます。また、「Owner Information」 は任意の内容を入力して下さい。そのターゲットの内容が分かりやすいものがいいかと思います。無しでも構いません。
ターゲットの登録ができると下記のようになります。下記は複数のターゲットが設定されていますが、今回登録したターゲットは、タグ「ami-backup」が「true」のインスタンスになるので、「77c3〜」のIDのものになります。
メンテナンスウィンドウにタスクを設定
次に、メンテナンスウィンドウのタスク内容を登録します。
タスクの登録は画面下の 「Tasks」 タブにある 「Schedule new task」 から設定しても構いません。
今回はAWS CLIを使うので、ドキュメントは 「AWS-RunShellScript」 を選択します。
「Task Priority」 はタスクの優先度です。複数タスクを登録する時はこの設定で制御します。今回は1つのタスクのみなので 「1」 にします。
「Resitered Targets」 は、このメンテナンスウィンドウで設定したターゲットの中から、実行したいターゲットを選択します。今回はタグ付けしたインスタンスが対象になるので、先程登録した「77c3〜」で始まるターゲットIDを選択します。
コマンドの内容は、実際に実行する内容を記載します。
今回は下記の内容で登録します。
下記は、AMI名を 「AMI-<インスタンスID>-<取得年月日(yyyymmdd)>」 という形で取得して、「取得年月日」が3日前のAMIを削除するという内容になります。
空行があるとエラーになるので、ここでの表記として見やすくする為に「#」の行を入れています。
あくまでもサンプルなので、そのまま利用される際は自己責任でご利用下さい。
AMIDATE=`date "+%Y%m%d"` AMIDATEVER=`date "+%Y%m%d" -d "-3 day"` EC2ID=`curl -s http://169.254.169.254/latest/meta-data/instance-id` REGION=ap-northeast-1 ############################################################################### aws ec2 create-image \ --region $REGION \ --instance-id $EC2ID \ --name "AMI-$EC2ID-$AMIDATE" \ --description "AMI-$EC2ID-$AMIDATE" \ --no-reboot ############################################################################### DELAMIID=`aws ec2 describe-images \ --region $REGION \ --filters "Name=name,Values=AMI-$EC2ID-$AMIDATEVER" \ --query "Images[*].ImageId" \ --output text` ############################################################################### aws ec2 deregister-image \ --region $REGION \ --image-id $DELAMIID
また、複数のEBSボリュームがアタッチされたインスタンスに対して、RootボリュームのEBSだけアタッチされたAMIを取得したいといった場合は、aws ec2 create-image
のオプションを追加する等コマンドを適宜修正して下さい。
例えば、下記のように--block-device-mappings
オプションで/dev/sdb
としてアタッチされている追加EBSは除外する、といった指定にします。
aws ec2 create-image \ --region $REGION \ --instance-id $EC2ID \ --name "AMI-$EC2ID-$AMIDATE" \ --description "AMI-$EC2ID-$AMIDATE" \ --no-reboot \ --block-device-mappings "[{\"DeviceName\": \"/dev/sdb\",\"NoDevice\":\"\"}]"
次の 「Role」 は、メンテナンスウィンドウ用に最初に作成した「MySsmMainteWindow」を選択します。
「Execute on」 はタスクを同時実行できるターゲットの数(Targets)、またはターゲット総数の割合(Percent)の指定です。今回のようにタグで多くのインスタンスを処理対象にしている場合に有用です。今回は数も少ないので 「1」 としています。
「Stop after」 は許容されるエラー数の指定です。新しいターゲットにタスクを送信する前に許容できるエラー数です。
マネージメントコンソールでは、実行結果が2500文字までとなる為、S3にも結果を出力しておくようにします。 次の「Advanced」の欄でバケット名などをそれぞれ指定します。
ここまでできたら、最後に「Register task」をクリックしてタスクを登録します。
マネジメントコンソール上の項目名について
先程設定した「Execute on」と「Stop after」の項目は、以前はそれぞれ「Max Concurrency」、「Max Errors」という表示でした。しかし今は変わっているので注意が必要です。
ただし、AWS CLIでは「MaxConcurrency」、「MaxErrors」と表示されるのでそれぞれの対応を覚えておくとよいかと思います。
マネジメントコンソールとの表記の違いをまとめると以下のようになります。
以前の表示名 | 今の表示名 | AWS CLIの指定オプション名 | AWS CLIの出力表示 |
---|---|---|---|
Cutoff | Stop initiating tasks | --cutoff | Cutoff |
Max Concurrency | Execute on | --max-concurrency | MaxConcurrency |
Max Errors | Stop after | --max-errors | MaxErrors |
タスク実行と結果
以上の作業で日本時間のAM01:00になれば、対象インスタンスのAMIを取得して3日前のAMIが削除されます。 しかし、動作確認したいので、手動で実行時間を変えてしまいます。後で戻すことを忘れないようにしましょう。
下記のように対象のメンテナンスウィンドウを選んで 「Edit maintenance window」 を選択します。
ここで実行時間を編集します。UTC での指定になります。
タスクが実行される前のAMIは下記のようになっています。AMI名が 「AMI-[インスタンスID]-[yyyymmdd]」 となっています。 実行前は、「i-05ba〜」「i-0092〜」という2つのインスタンスのAMIが2017年4月4日〜6日の3つずつ存在しています。
タスクの実行が完了すると「History」タブに結果が表示されます。今回は成功したので「Status」に 「Success」 と表示されています。 詳細は「View datails」をクリックします。
次の画面でタスクが実行された詳細結果を確認できます。更に「View datails」をクリックします。
上記で「View datails」をクリックすると、ターゲットの各インスタンスでの詳細を確認することが出来ます。 下記では「i-009〜」のインスタンスでの実行結果ですが「Run Command」として実行されていることが分かると思います。
「Output」タブをクリックするとコマンド実行時の出力内容を確認出来ます。下記の「Output」欄にある「View Output」をクリックします。
aws ec2 create-image
を実行した結果が出力されています。
S3バケットにも下記のように標準出力と標準エラー出力の2つのファイルが作成されていました。
標準出力の内容はこちらです。
話が少し外れてしまいましたが、AMIの結果も下記の通りとなり、4月7日取得のAMIが新たに作成されて、3日前の4月4日のAMIが削除されています。
最後に
AMIの定期的な作成はLambdaの方が柔軟にできると思いますが、EC2に関してはEC2 Systems Managerを活用すれば他にも色んなことができそうですね。 Lamnbdaの利用料金がどうしても気になる場合はこういった選択肢もあるかと思います。要件に応じて使い分けて頂ければと思います。
以上です。