AWS System Manager AutomationでLinux AMIを作る

2021年11月26日

AWS System Manager

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 など権限周りでつまづいたので、そのあたり補足しながら紹介します。

目次

  1. AWS-UpdateLinuxAmi ランブックを選択する
  2. IAM instance profile と IAM Role を作成する
  3. AWS-UpdateLinuxAmi ランブックを実行する
  4. うまくいかない場合は
  5. AWS-UpdateLinuxAmi ランブックで何をやっているか
  6. 外部スクリプトで AMI をカスタマイズ
  7. 独自のランブックを作ることもできる
  8. AMI に SSM Agent が含まれる

AWS-UpdateLinuxAmi ランブックを選択する

AWS マネジメントコンソールから System Manager を開き、左側のメニューから Automation (自動化)を選択します。

Automation で Execute automation ボタンをクリックします。

Execute automation

Choose document で左メニューから AMI management にチェックをいれ、AWS-UpdateLinuxAMI にチェックをいれます。

Choose AMI

下にスクロールをして Next をクリックします。

IAM instance profile と IAM Role を作成する

以下のように Execute automation document の画面が開きます。ここでベースとなる AMI など、AMI を作成するためのパラメータを設定します。

Execute automation document

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 が作成されます。

Execution detail: AWS-UpdateLinuxAmi

うまくいかない場合は

IAM Role と IAM Profile に原因があることが多いと思います。Troubleshooting Systems Manager Automation - AWS Systems Manager が参考になりました。

AWS-UpdateLinuxAmi ランブックで何をやっているか

少し前の Choose document の手順で、AWS-UpdateLinuxAmi を選択する画面がありました。そこで AWS-UpdateLinuxAmi のリンクをクリックすると、Description や Content タブで詳細を確認することができます。

AWS-UpdateLinuxAmi

ドキュメント にも書かれていますが、AWS-UpdateLinuxAmi ランブックでは、EC2 を起動し、User Data で SSM Agent をインストールした後、インストールされているパッケージを更新したあと、EC2 を停止して AMI を作成しています。パッケージの更新の前後で任意のスクリプトを実行することもできます。

外部スクリプトで AMI をカスタマイズ

ランブックを実行するときのパラメータ PreUpdateScriptPostPudateScript に実行したいスクリプトのファイルの URL を記載することで任意のコマンドを実行できます。スクリプトの書かれたファイルを S3 や GitHub などに置き、curl や wget コマンドでダウンロードできるようにしておきます。

独自のランブックを作ることもできる

AWS-UpdateLinuxAmi や他のランブックを参考にして独自のランブックも作成できます。ただし、よく使うであろう AWS-RunShellScriptドキュメントに指定できるコマンドが文字列の配列になっているので、ランブック内で複雑なコマンドを構築するのは大変なことが予想されます。ランブックに直接コマンドを書く場合はコマンドが数行の単純なケースにとどめ、それ以外は外部ファイルからダウンロードして実行するようにしたほうが良さそうです。

AMI に SSM Agent が含まれる

EC2 の起動時に UserData で SSM Agent をインストールし、その後は SystemManager の各種機能を使っているため、結果として AMI には SSM Agent が含まれます。SSM Agent が不要な AMI が必要なこともあると思います。AMI のビルドの最後に SSM Agent を削除できると良いのですが、良い方法が見つかっていません。

-技術ブログ
-