TerraformでAmazon LinuxのNATインスタンス用AMIを取得するためのモジュールを作成してみました。
使い方
リージョンやバージョン等のパラメータを指定してNATインスタンス用AMIのIDを取得することができます。
module "nat_instance_ami" {
source = "github.com/atsaki/tf_aws_nat_ami"
region = "eu-central-1
version = "2015.03.0"
virttype = "pv"
volumetype = "ebs"
}
regionのみ必須で、他は省略可能です。
- region : (例:eu-central-1)
- version : (例:2015.03.0、デフォルト:2015.03.0)
- virttype : hvm or pv (デフォルト:hvm)
- volumetype : gp2 or ebs (デフォルト:gp2)
実際のtfファイル、tfvarsファイルは以下のようになります。(NATを行うためにはroute tableの設定などが必要ですが今回は割愛します。)
variable "aws_access_key" {}
variable "aws_secret_key" {}
variable "region" {}
provider "aws" {
access_key = "${var.aws_access_key}"
secret_key = "${var.aws_secret_key}"
region = "${var.region}"
}
module "nat_instance_ami" {
source = "github.com/atsaki/tf_aws_nat_ami"
region = "${var.region}"
virttype = "pv"
volumetype = "ebs"
}
resource "aws_instance" "nat_instance" {
ami = "${module.nat_instance_ami.ami_id}"
instance_type = "t1.micro"
tags {
Name = "nat_instance"
}
}
aws_access_key = "YOUR_ACCESS_KEY"
aws_secret_key = "YOUR_SECRET_KEY"
region = "YOUR_REGION"
tfファイルができたらterraform get
コマンドでモジュールをダウンロードします。
$ terraform get
この後は、通常通りterraform plan
や terraform apply
を実行可能です。
仕組み
このモジュールはterraform-community-modulesのtf_aws_fedora_ami、tf_aws_ubuntu_amiを参考に作成しました。
何れも仕組みとしては同じで前もってスクリプトでAMIのリストを取得しTerraformの変数として保存しておき、モジュールのパラメータを使ってlookupしています。
今回作成したモジュールではAWS SDK for Rubyを使って各リージョンのAMIのリストを取得し、名前がamzn-ami-vpc-nat
から始まるAMIの情報をvariables.tf.json
に保存しています。
#!/usr/bin/env ruby
require 'aws-sdk'
require 'json'
regions = Aws::EC2::Client.new(region: 'us-east-1')
.describe_regions.regions.map { |r| r.region_name }
data = {}
regions.each do |region|
images = Aws::EC2::Client.new(region: region).describe_images(
owners: ['amazon'],
filters: [{ name: 'image-type', values: ['machine'] }]
).images.select { |image|
!image.name.nil? && image.name.start_with?("amzn-ami-vpc-nat")
}
data.merge!(Hash[images.map {|i| ["#{region},#{i.name}", i.image_id]}])
end
puts JSON.pretty_generate({
variable: {
amis: {
default: data
}
}
})
variables.tf.json
の中は以下のようになっており、リージョン名とAMI名をキー、AMI idをバリューとしてAMIのリストが格納されています。
{
"variable": {
"amis": {
"default": {
"eu-central-1,amzn-ami-vpc-nat-hvm-2015.03.0.x86_64-ebs": "ami-1e073a03",
"eu-central-1,amzn-ami-vpc-nat-hvm-2014.03.2.x86_64-ebs": "ami-204c7a3d",
"eu-central-1,amzn-ami-vpc-nat-pv-2015.03.0.x86_64-ebs": "ami-3604392b",
"eu-central-1,amzn-ami-vpc-nat-hvm-2015.03.0.x86_64-gp2": "ami-46073a5b",
〜〜〜省略〜〜〜
}
}
}
}
main.tf
ではlookup
関数を使ってモジュールのパラメータで指定された条件と合致するAMIを抽出しIDを出力しています。
(lookup
やformat
についてはTerraformのドキュメントを参照)
variable "region" {}
variable "version" {
default = "2015.03.0"
}
variable "virttype" {
default = "hvm"
}
variable "volumetype" {
default = "gp2"
}
output "ami_id" {
value = "${lookup(var.amis, format(\"%s,amzn-ami-vpc-nat-%s-%s.x86_64-%s\", var.region, var.virttype, var.version, var.volumetype))}"
}