EC2 Image BuilderのライフサイクルポリシーでAWS Organizations配下に共有された古いイメージを削除してみた

子アカウントでライフサイクル管理用のIAMロールの作成が必要となります。今回はCloudFormation StackSetsを使用し、AWS Organizationsで新規アカウントが追加されたときにIAMロールを自動作成するよう設定を行います。
2024.03.05

共有された古いイメージを削除したい

こんにちは!AWS事業本部のおつまみです。

みなさん、EC2 Image Builderで作成したイメージが残り続けて困った経験はありますか?私はあります。

EC2 Image Builder では、パイプラインを実行する度にイメージを自動で作成してくれます。しかし、古いイメージが残り続けることで、AMIに関連付いているEBSスナップショットの料金が発生してしまいます。
そのため、ライフサイクル機能を使用し、古いイメージを削除することでコストを削減することができます。

今回はAWS Organizations配下に共有された古いイメージを削除する機会があったので、その手順をご紹介します。

古いイメージが削除されてしまうため、EC2 Auto Scallingの起動テンプレートにイメージを使用している場合は、本実装を適用しないでください。

前提条件

以下の構成までできていることを前提として進めます。

  • EC2 ImageBuilderでパイプラインの構築が完了している
  • AWS Organizationsで他アカウントにイメージが共有されている

前提条件の手順については、こちらのブログをご参考ください。

構成図

今回構築する構成です。

以下の流れで作業を進めていきます。

1. EC2 Image Builderを構築している管理アカウントでライフサイクル管理用のIAMロールを作成

2. EC2 Image Builderでライフサイクルポリシーを作成

3. 子アカウントにライフサイクル管理用のIAMロールを作成するCloudFormation StackSetsの設定

CloudFormation StackSetsを使用することで、AWS Organizationsで新規アカウントが作成される度に自動でそのアカウント内にライフサイクル管理用のIAMロールを作成することができます。
これにより、共有されたイメージがアカウント内に残り続けることを防ぎます。

やってみた

IAMロールの作成

ライフサイクルポリシーでは、EC2 Image Builder にライフサイクル実行時に必要となるアクセス許可をIAM ロールとして関連付ける必要があります。
公式ドキュメントの手順をもとに設定します。

  • IAM コンソールを開きます。

  • [ロールの作成] を選択し、[信頼されたエンティティタイプ] に、[カスタム信頼ポリシー] を選択します。

  • 以下の JSON 信頼ポリシーをコピーして、[カスタム信頼ポリシー] のテキスト領域に貼り付け、サンプルテキストと置き換えます。この信頼ポリシーで、Image Builder はライフサイクルアクションを実行するために作成したロールを引き継ぐことができます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "sts:AssumeRole"
            ],
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "imagebuilder.amazonaws.com"
                ]
            }
        }
    ]
}

  • リストから管理ポリシー [EC2ImageBuilderLifecycleExecutionPolicy] を選択し、[次へ] を選択します。ポリシーには、ライフサイクルポリシーのアクションに必要なアクセス許可が一式含まれています。

  • [ロール名]に任意の名前を入力し、[ロールを作成] を選択します。今回はEC2ImageBuilderLifecycleExecutionRoleとしました。

ライフサイクルポリシーの作成

  • EC2 Image Builder コンソールを開き、ナビゲーションペインから [ライフサイクルポリシー] を選択します。

  • [ライフサイクルポリシーを作成] を選択します。

  • [一般]のセクションで以下を設定します。
    • ポリシータイプ:AMI
    • ポリシー名:任意のポリシー名(例:test-policy
    • IAM ロール:手順1で作成したIAMロール

なおデフォルト設定ではライフサイクルポリシーが有効になっており、すぐにスケジュールに追加されます。ポリシーをすぐに適用したくない場合は、[アクティブ化] をオフにします。

  • [ルール範囲] を設定します。フィルタの種類として、レシピもしくはタグから選択できます。今回はレシピを選択し、パイプライに紐づいているレシピを選択します。

  • [ライフサイクルルール] のセクションで以下を設定し、[ルールの作成]を選択します。設定内容は自身の環境に合わせて設定してください。

    • [削除ルール]:オン
    • カウント別:1
    • AMI の登録を解除:オン
    • スナップショットを削除:オン

これでEC2 Image Builderを構築している管理アカウントでは、ライフサイクル管理によりイメージを削除することができるようになりました。

ポリシーによりライフサイクルが実行されているかは、ライフサイクルポリシーの[アクションタブ]から確認できます。
ステータスが失敗となっている場合は、上手く実行されていないので設定を見直しましょう。ちなみにこの時はIAMロールにアタッチするポリシーを間違えていたため、1回目は失敗になっています。

しかし、このままでは子アカウントに共有したイメージを削除できません。
イメージの削除には、子アカウント内でライフサイクル管理用のIAMロールの作成が必要となります。

Image Builder クロスアカウントライフサイクル管理用の IAM ロールを作成する

1アカウントずつ作成するのは手間かつ新規で追加されたアカウント内にもIAMロールを作成したいので、今回はCloudFormation StackSetsを使用します。

CloudFormation StackSetsの設定

組織全体にライフサイクル管理用のIAMロールを作成するよう設定を行います。
EC2 ImageBuilderを構築したアカウントで実施します。

  • CloudFormation コンソールを開き、ナビゲーションペインから [StackSets] を選択します。

  • [テンプレートファイルのアップロード]でテンプレートをアップロードします。

IAMロールを作成するために使用したテンプレートはこちらです。

AWSTemplateFormatVersion: '2010-09-09'
Description: 'Create IAM Role for EC2 Image Builder Cross Account Access with parameterized Source Account'

Parameters:
  SourceAccount:
    Type: String
    Description: AWS Account ID that the Image Builder should assume role from

Resources:
  Ec2ImageBuilderCrossAccountLifecycleAccessRole:
    Type: 'AWS::IAM::Role'
    Properties:
      RoleName: Ec2ImageBuilderCrossAccountLifecycleAccess
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: imagebuilder.amazonaws.com
            Action: 'sts:AssumeRole'
            Condition:
              StringEquals:
                aws:SourceAccount: !Ref SourceAccount
              StringLike:
                aws:SourceArn: 'arn:*:imagebuilder:*:*:image/*/*/*'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/EC2ImageBuilderLifecycleExecutionPolicy

Outputs:
  RoleArn:
    Description: 'The ARN of the created IAM Role'
    Value: !GetAtt Ec2ImageBuilderCrossAccountLifecycleAccessRole.Arn
  • StackSet の詳細の指定で以下を設定します。
    • StackSet名:任意の名前(例:create-ec2ImageBuilder-LifecycleExecution-iam-role
    • StackSetの説明:任意の説明文(例:Image Builder のクロスアカウントライフサイクル管理用のIAMロールを作成
    • パラメータ:EC2 ImageBuilderを構築したアカウントのAWSアカウントID

  • StackSet オプションの設定はデフォルトのまま[次へ]を選択します。

  • デプロイオプションの設定で以下を設定します。
    • スタックセットにスタックを追加:新しいスタックのデプロイ
    • デプロイターゲット:組織へのデプロイ(※OU単位で共有してる場合は、OUへのデプロイを選択)
    • 自動デプロイ:アクティブ化済み(デフォルトのまま)
    • アカウント削除の動作:スタックを削除(デフォルトのまま)

  • リージョンの設定はCloudFormationスタックを作成したいリージョンを選択します。今回はIAMロールの作成のため、任意のリージョン1つを選択しましょう。

  • 最後にレビュー画面で内容の確認をし、[作成]を選択します。

  • 作成後、[スタックインスタンス]のタブからOrganizations内の子アカウントでスタックが作成されていることが確認できます。

  • このように子アカウントに切り替えると、子アカウントでもスタックが作成されていることを確認できます。

以上で設定は完了です。

動作確認

ライフサイクルポリシーで古いイメージが削除されることを確認します。

まずEC2 Image Builderのパイプラインを実行し、このようにイメージを3個作成しました。

また、各々のアカウントで実体となるAMIも3つ作成されていることが確認できます。

  • 管理アカウント

  • 子アカウント

子アカウントは[プライベートイメージ]に切り替えてください。

ライフサイクルポリシーが実行されるまで待ちます。

なおライフサイクルポリシーの実行時間は明確に決まっておりません。
検証した限り、ライフサイクルポリシー作成後、一定期間(24 時間以上)経過後に、1 日 1 回実行されるようでした。

ライフサイクルポリシーのアクションログからライフサイクルが実行されたことを確認しました。

実行IDを選択すると、削除されたイメージも確認できます。

パイプラインの出力イメージを確認からも、最新の 1 つのみが保持されており、残りの 2 つは削除されていることが確認できました。

このようにAMIも1つのみ保持されていることが確認できました。

  • 管理アカウント

  • 子アカウント

おまけ①:パイプラインを削除してもイメージは削除されません

EC2 Image Builderによるイメージの作成が不要になって、パイプラインのみ削除していないでしょうか?

パイプラインの削除のみでは、イメージを完全に削除することができません。
削除するための手順をご紹介します。

  • EC2 Image Builderのナビゲーションペインから [イメージ] を選択します。

  • 該当のイメージを選択後、[アクション]→[Delete Image]を選択します。

  • [AMIの登録を解除]、[スナップショットを解除]にチェックをし、ライフサイクルポリシーで作成したIAMロールを選択後に[削除する]を選択します。

  • 解除プロセスが実行されるので、しばらく待ちます。

  • 15分ほど経つと、イメージが削除されていることが確認できました。

  • 管理アカウント

  • 子アカウント

あとは不要になったパイプラインやライフサイクルポリシーも削除しておきましょう。

おまけ②:パイプラインを構築しているアカウントが管理アカウントではない場合

管理アカウントからCloudFormation StackSets の委任管理者設定することで、EC2 Image Builderを構築しているアカウントからでも組織全体に対してCloudFormation StackSetsを実行することが可能になります。

手順はこちらのブログをご参考ください。

注意点として、公式ドキュメントにあるよう、委任された管理者の操作は管理アカウント側から制限することができません。

委任された管理者は、組織内のアカウントにデプロイするための完全なアクセス許可を持っています。管理アカウントでは、特定の OU にデプロイしたり、特定のスタックセットの操作を実行したりする、委任された管理者のアクセス許可を制限することはできません。

そのため、そのアカウントに許可を与えてよいかは、十分検討するようにしましょう。

最後に

今回はEC2 Image Builderのライフサイクル機能でAWS Organizations配下に共有された古いイメージを削除する方法をご紹介しました。

イメージが残り続けることで発生していたコストを削減することができるので、ぜひ利用を検討してみましょう!

最後までお読みいただきありがとうございました!
どなたかのお役に立てれば幸いです。

以上、おつまみ(@AWS11077)でした!

参考

ライフサイクルポリシーの作成 - EC2 Image Builder

EC2 Image Builder イメージのライフサイクル管理の前提条件 - EC2 Image Builder

AWS CloudFormation StackSets と AWS Organizations - AWS Organizations

委任された管理者の登録 - AWS CloudFormation