AWS Systems Manager Automation を使って Linux の Amazon Machine Image(AMI) を作成する方法を紹介します。これまで AMI を作るときは HashiCorp の Packer を使っていたのですが、AWS System Manager の機能で AMI が作れるようなので試してみました。
基本的には Walkthrough: Patch a Linux AMI (console) - AWS Systems Manager の通りですが、IAM Role など権限周りでつまづいたので、そのあたり補足しながら紹介します。
目次
- AWS-UpdateLinuxAmi ランブックを選択する
- IAM instance profile と IAM Role を作成する
- AWS-UpdateLinuxAmi ランブックを実行する
- うまくいかない場合は
- AWS-UpdateLinuxAmi ランブックで何をやっているか
- 外部スクリプトで AMI をカスタマイズ
- 独自のランブックを作ることもできる
- AMI に SSM Agent が含まれる
AWS-UpdateLinuxAmi ランブックを選択する
AWS マネジメントコンソールから System Manager を開き、左側のメニューから Automation (自動化)を選択します。
Automation で Execute automation ボタンをクリックします。
Choose document で左メニューから AMI management にチェックをいれ、AWS-UpdateLinuxAMI にチェックをいれます。
下にスクロールをして Next をクリックします。
IAM instance profile と IAM Role を作成する
以下のように Execute automation document の画面が開きます。ここでベースとなる AMI など、AMI を作成するためのパラメータを設定します。
IamInstanceProfileName に ManagedInstanceProfile
、AutomationAssumeRole に arn:aws:iam::{{global:ACCOUNT_ID}}:role/AutomationServiceRole
がデフォルトで設定されています。これは何でしょうか。
ドキュメント によると、IamInstanceProfileName は AMI を作成するために起動する EC2 の Instance Profile に設定され、AutomationAssumeRole は Automation サービスでランブックを実行する際に利用されるようです。これらは AWS が用意してくれていないので、自身で作成する必要があります。
ManagedInstanceProfile
の作り方は Step 4: Create an IAM instance profile for Systems Manager - AWS Systems Manager に書かれています。arn:aws:iam::{{global:ACCOUNT_ID}}:role/AutomationServiceRole
の作り方は Setting up Automation - AWS Systems Manager に書かれています。
ドキュメントの通り手作業で作っていってもいいのですが、後から見たときに何のために作ったか忘れてしまいそうだったので、以下のように CloudFormation で作成しました。
system-manager-automation-setup.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: AWS CloudFormation template IAM Roles for Systems Manager Automation Service
Resources:
ManagedInstanceRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
Path: "/"
RoleName: ManagedInstanceRole
ManagedInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
InstanceProfileName: ManagedInstanceProfile
Path: "/"
Roles:
- !Ref ManagedInstanceRole
AutomationServiceRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- ssm.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonSSMAutomationRole
Path: "/"
Policies:
- PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- iam:PassRole
Resource:
- !GetAtt ManagedInstanceRole.Arn
PolicyName: PassRole
RoleName: AutomationServiceRole
AWS-UpdateLinuxAmi ランブックを実行する
上記の CloudFormation テンプレートなどで Instance Profile と IAM Role を作ったらあと少しです。先程の Execute automation document の画面に戻り、SourceAmiId にベースとなる AMI の ID を入れ、下にある Execute ボタンを押します。
うまくいくと以下のように AMI が作成されます。
うまくいかない場合は
IAM Role と IAM Profile に原因があることが多いと思います。Troubleshooting Systems Manager Automation - AWS Systems Manager が参考になりました。
AWS-UpdateLinuxAmi ランブックで何をやっているか
少し前の Choose document の手順で、AWS-UpdateLinuxAmi を選択する画面がありました。そこで AWS-UpdateLinuxAmi のリンクをクリックすると、Description や Content タブで詳細を確認することができます。
ドキュメント にも書かれていますが、AWS-UpdateLinuxAmi ランブックでは、EC2 を起動し、User Data で SSM Agent をインストールした後、インストールされているパッケージを更新したあと、EC2 を停止して AMI を作成しています。パッケージの更新の前後で任意のスクリプトを実行することもできます。
外部スクリプトで AMI をカスタマイズ
ランブックを実行するときのパラメータ PreUpdateScript
や PostPudateScript
に実行したいスクリプトのファイルの URL を記載することで任意のコマンドを実行できます。スクリプトの書かれたファイルを S3 や GitHub などに置き、curl や wget コマンドでダウンロードできるようにしておきます。
独自のランブックを作ることもできる
AWS-UpdateLinuxAmi や他のランブックを参考にして独自のランブックも作成できます。ただし、よく使うであろう AWS-RunShellScript
ドキュメントに指定できるコマンドが文字列の配列になっているので、ランブック内で複雑なコマンドを構築するのは大変なことが予想されます。ランブックに直接コマンドを書く場合はコマンドが数行の単純なケースにとどめ、それ以外は外部ファイルからダウンロードして実行するようにしたほうが良さそうです。
AMI に SSM Agent が含まれる
EC2 の起動時に UserData で SSM Agent をインストールし、その後は SystemManager の各種機能を使っているため、結果として AMI には SSM Agent が含まれます。オプションで SSM Agent を削除できると良いのですが、良い方法が見つかっていません。