[Terraform][CloudFormation]最新のAMI IDの取得方法

# はじめに
AWSが管理するAMI（Amazon Linux2など）はAMI IDが定期的に更新されますので、TerraformとCloudFormationでEC2を構築する際に、常に最新のAMI IDを自動で取得する方法をまとめてみました。
- Terraform: v1.3.5、aws provider: v4.55.0
- CloudFormation AWSTemplateFormatVersion: 2010-09-09 

# AMIの検索方法
管理コンソールやCLIで検索できます。詳しくは公式ドキュメントをご参照ください。
- [Linux AMI の検索](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/finding-an-ami.html)
- [Windows AMI の検索](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/finding-an-ami.html)

# Terraform
「Data Source」で最新のAMIを検索して取得します。「most_recent」を「true」にすることで、検索条件に一致するAMIが複数存在する場合最新のAMIを取得できます。「owners」でAMIの所有者を指定できます。「filter」ブロックの中で取得したいAMIの検索条件を指定できます。

以下のように記述すると、2023/02/18時点の最新の「Amazon Linux 2 AMI (HVM) - Kernel 4.14, SSD Volume Type」のAMI（ami-0e2faefe48ba06395）を取得できます。
```terraform
data "aws_ami" "amzlinux2" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
  }
}
```
filterブロックに「root-device-type」や「architecture」などの検索条件を個別に指定することもできます。以下のように記述しても上記と同じAMIを取得できます。
```terraform
data "aws_ami" "amzlinux2" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*"]
  }
  filter {
    name   = "root-device-type"
    values = ["ebs"]
  }
  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
  filter {
    name   = "architecture"
    values = ["x86_64"]
  }
  filter {
    name   = "block-device-mapping.volume-type"
    values = ["gp2"]
  }
}
```
インスタンスを作成する際に「aws_instance」リソースで上記の「Data Source」を参照します。
```terraform
resource "aws_instance" "main" {
  ami           = data.aws_ami.amzlinux2.id
  instance_type = "t2.micro"
}
```
※AMI IDの更新によってterraform apply時にインスタンスが再作成される場合があります。AMI IDの変更による再作成を避けたい場合はlifecycleのignore_changesに「ami」を追加することができます。
```terraform
resource "aws_instance" "main" {
  ami           = data.aws_ami.amzlinux2.id
  instance_type = "t2.micro"

  lifecycle {
    ignore_changes = [
      ami,
    ]
  }
}
```


# CloudFormation
Amazon EC2のAMIは、固有のパブリックパラメータストア名前空間を持っていますので、CloudFormationのパラメータセクションで該当SSMパラメータを参照できます。SSMパラメータを使ったAMIの検索方法は公式ドキュメントをご参照ください。（[Linux AMI の検索](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/finding-an-ami.html)、[Windows AMI の検索](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/finding-an-ami.html)）

以下のように記述すると、2023/02/18時点の最新の「Amazon Linux 2 AMI (HVM) - Kernel 4.14, SSD Volume Type」のAMI（ami-0e2faefe48ba06395）を取得してインスタンスを作成できます。
```yaml
AWSTemplateFormatVersion: "2010-09-09"

Parameters:
  EC2ImageId:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"

Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref EC2ImageId
      InstanceType: t2.micro

```

# 参考
- [aws provider - Data Source: aws_ami](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami)
- [AWS CloudFormation - テンプレートの操作 - テンプレートの構造分析 - パラメータ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html)
- [Linux AMI の検索](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/finding-an-ami.html)
- [Windows AMI の検索](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/finding-an-ami.html)