はじめに
こんにちは、mori (@morimori) です。
弊社では昔から使っているAWS CloudFormationのテンプレートがあり、その中にEC2インスタンスを作成するものがあります。そのテンプレートでは、EC2を作成するたびに最新のAMI IDをマネジメントコンソールで調べて、テンプレートに直接指定するというやり方をとっていました。
毎回地味に手間がかかるのももちろんですが、それ以上に困るのがAMI IDの有効期限です。AMIはしばらくすると使えなくなってしまうことがあります。開発環境と本番環境の構築に期間が空く場合、開発環境を作ったときのAMI IDがすでに無効になっており、本番環境の構築でエラーになってしまう——そんなケースも実際に起きていました。最近は生成AIを使ってCloudFormationを書くことも増えてきました。そんな中、生成AIが出力したテンプレートの中にこの問題をうまく解決しているコードを見つけました。「これだ」と思ったので、今後のテンプレートに取り入れていきたいと思います。この記事では、その内容を紹介します。
やり方
CloudFormationのパラメータに AWS::SSM::Parameter::Value<AWS::EC2::Image::Id> という型を指定することで、SSMパラメータストアの値を自動的に参照できます。
AWSはAmazon Linux 2023の最新AMI IDを以下のSSMパラメータパスで公開しています。
AmiId:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64
Description: Amazon Linux 2023 の最新 AMI(SSM パラメータから自動取得)
Default にSSMのパスを指定しておくと、スタック作成・更新時にその時点での最新AMI IDが自動で取得されます。
このSSMパラメータパスはAWSの公式ドキュメントにも記載されています。
https://docs.aws.amazon.com/ja_jp/linux/al2023/ug/ec2.html
テンプレート全体の例
実際に使えるテンプレートの例です。
AWSTemplateFormatVersion: "2010-09-09"
Description: Amazon Linux 2023 EC2 instance
Parameters:
AmiId:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64
Description: Amazon Linux 2023 の最新 AMI(SSM パラメータから自動取得)
InstanceType:
Type: String
Default: t3.micro
Resources:
MyInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref AmiId
InstanceType: !Ref InstanceType
ポイント
- リージョンに依存しない — SSMパラメータはリージョンごとに最新のAMI IDを保持しているため、どのリージョンでも同じテンプレートが使えます
- 常に最新 — スタックを更新するたびに最新のAMIが適用されます
- AMI IDの管理が不要 — ハードコードを避けられるのでメンテナンスが楽になります
SSMパラメータパスを少し深掘りしてみる
せっかくなので、パスのバリエーションも調べてみました。以下のAWS CLIコマンドで東京リージョンのパス一覧を確認できます。
aws ssm get-parameters-by-path \
--path /aws/service/ami-amazon-linux-latest/ \
--region ap-northeast-1 \
--query 'Parameters[?contains(Name, `al2023`)].Name'
実行結果はこんな感じです。
[
"/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-arm64",
"/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64",
"/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-6.18-arm64",
"/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-arm64",
"/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.12-x86_64",
"/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-6.1-arm64",
"/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-6.1-x86_64",
"/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-6.12-arm64",
"/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.18-arm64",
"/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64",
"/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-6.18-x86_64",
"/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64",
"/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-6.12-x86_64",
"/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.12-arm64",
"/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.18-x86_64",
"/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"
]
パスは AMIの種類 × カーネルバージョン × アーキテクチャ の組み合わせで構成されています。
AMIの種類
- 標準:
al2023-ami-kernel-* - minimal(軽量版):
al2023-ami-minimal-kernel-*
カーネルバージョン
-
default: その時点での最新カーネル -
6.1/6.12/6.18: バージョンを固定したい場合
アーキテクチャ
-
x86_64: 一般的なIntel/AMD系 -
arm64: AWS Gravitonプロセッサ
通常は kernel-default を使っておけば常に最新のカーネルが適用されます。カーネルバージョンを固定したい事情がある場合に、特定バージョンのパスを選ぶと良いでしょう。
パスの詳細は以下の記事も参考になりました。
https://zenn.dev/haggar/articles/4a1941d86c3058
まとめ
AWS::SSM::Parameter::Value<AWS::EC2::Image::Id> 型を使うだけで、AMI IDのハードコードから解放されます。シンプルですが効果的なテクニックです。
今回のテンプレートはもともと自分が作ったものです。動いているからそれでいい、と思っていたら気づかなかったかもしれません。生成AIにCloudFormationを書かせてみたところ、こういったベストプラクティスな実装を自然に提案してくれて、「こんな書き方ができるのか」という発見がありました。
動いているコードをあえて直そうとはなかなか思えないものですが、生成AIが幅広い知識をもとに改善案を出してくれることで、自分では気づきにくい改善の余地に気づけるのは、うれしい副産物だなと感じています。
「動いているからOK」で止まらず、こういった小さな改善を積み重ねていくことが、長く使えるインフラを作ることにつながると思っています。これからも生成AIをうまく活用しながら、少しずつブラッシュアップしていきたいと思います。