ちばのてっく

積極的にアウトプット

Terraformで最新の無料利用対象AMI IDを出力してみた

先日の記事で、Terraformで利用するために、最新のAMI IDをAWS CLIで取得する方法を調べたが、Terraformだけで完結できそうだと気付いたためやってみる。

はじめに結論

このtfファイルを実行することで、先日の記事と同じ結果が得られる。

作成するtfファイル

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.42"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

# ↓ここから
data "aws_ami" "latest" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["al2023-ami-2*"]
  }
}

output "latest_ami_id" {
  value = data.aws_ami.latest.id
}
# ↑ここが大事

terraform planの結果

Changes to Outputs:
  + latest_ami_id = "ami-031134f7a79b6e424"

(なお、先日の記事から数日しか経っていないが、すでに無料利用対象の最新AMIが更新されているようで、得られたAMI IDは異なっていた。)

やってみた

Terraformドキュメントに、AMIに関するData Sourceであるaws_amiが存在したので参考にする。
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami

aws_amiで利用できる引数は以下の通り。AWS CLIのdescribe-imagesコマンドで見たことのあるものが揃っているが、「most_recent」と「name_regrex」はTerraform独自の引数となる。

  • owners
  • most_recent
  • executable_users
  • include_deprecated
  • filter
  • name_regex

most_recent

most_recentがtrueの場合、返却対象のAMIが複数あったときに最新のAMI1つのみを返却する。なお、返却されるIDが1つでないとTerraformは失敗する。
先日の記事でいうと、AWS CLIでqueryオプションを使ってJMESPathでごにょごにょ書いていた箇所に相当する。

name_regex

name_regexは、AWSが返却するAMI IDのリストに対して正規表現で絞り込みを行う。
自由度の高い絞り込みができる一方で、一応の注意点としてはローカルで絞り込みを行うという点。対象となるAMI IDの量やTerraform実行環境のスペック次第では少し重い処理になる。そのため、他の引数で返却されるIDを絞って減らしておくことが推奨されている。

脇道にそれるが、name_regex使うとどれだけパフォーマンスに影響が出るのか、ちょっとやってみた。

以下2パターンで、返却時間をtimeコマンドで確認してみた。

data "aws_ami" "filter" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["al2023-ami-2*"]
  }
}

→ user 0m7.279s

data "aws_ami" "regex" {
  most_recent = true
  owners      = ["amazon"]
  name_regex  = "^al2023-ami-2.*"
}

→ user 0m12.970s

確かにパフォーマンスに少し影響が出た。大量のEC2を異なるAMIで起動するようなときなどはちょっと気を使っても良いかもしれない。

AWS CLIコマンドとの紐づけて整理

先日の記事のコマンドaws ec2 describe-images --owners amazon --filters 'Name=name,Values=al2023-ami-2*' --query 'sort_by(Images,&CreationDate)[-1].[ImageId]' --output textと紐づけて整理してみる。

AWS CLI--owners amazonは、
Terraformではowners = ["amazon"]となり、

AWS CLI--filters 'Name=name,Values=al2023-ami-2*'は、
Terraformでは

  filter {
    name   = "name"
    values = ["al2023-ami-2*"]
  }

となり、

AWS CLI--query 'sort_by(Images,&CreationDate)[-1].[ImageId]'は、
Terraformではmost_recent = trueとなった。

残課題

先日の記事に同じ。

残課題
今回のように近しい命名規則のAMIが追加された場合や、AWS側でNameの命名規則を変えた>場合に、期待通りの出力結果が得られなくなる可能性がある。無料利用対象という条件で絞り込むような、スマートな方法があるのかもしれない。