既存のリソース上にTerraformでリソースを追加してみた
はじめに
既存のVPC上にTerrafromで管理するEC2を立てるなど、既存のリソースとTerraformで管理するリソースを関連づけたいという状況がありました。
IaCの考え方として、このリソースは手動、このリソースはIaC、というように管理を分けることは推奨されないと思いますが、業務の都合上どうしても分けなければいけないケースも存在すると思います。
今回は手動で作成したVPC上にTerraformで管理するEC2を立ててみたいと思います。
イメージ図はこんな感じです。
検証に使用した環境は以下の通りです。
$ terraform --version
Terraform v1.9.5
terraform {
required_version = "~> 1.9"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~>5.63.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
VPCの作成
まずはVPCを作成します。
今回はAWS CLIを使っています。
aws ec2 create-vpc \
--cidr-block 10.0.0.0/16 \
--tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=demo_vpc}]'
次にサブネットを作成します。
aws ec2 create-subnet \
--vpc-id {VPCのID} \
--cidr-block 10.0.0.0/24 \
--availability-zone ap-northeast-1a
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=demo_subnet}]'
コンソール画面からVPCとサブネットが作成されていることを確認します。
TerraformでEC2を作成
作成したVPC上にTerraformでEC2を作成するためにはVPC上のサブネットのIDを指定する必要があります。
サブネットIDの指定には以下の方法があります。
- 直接サブネットIDを指定
- 変数を使ってサブネットIDを指定
- Data Sourcesで既存のサブネットIDを取得して指定
直接サブネットIDを指定するパターンは、説明は不要かと思いますので今回は割愛します。
変数に代入
既存サブネットIDを変数に代入する方法をやってみます。
まずは既存VPCのIDを調べます。
$ aws ec2 describe-vpcs --filters Name=tag:Name,Values=demo_vpc --query 'Vpcs[*].VpcId' --output text
vpc-03fb25adbfa800687
取得したVPC IDからサブネットIDを取得します。(コンソール画面でも確認できます)
$ aws ec2 describe-subnets --filters Name=vpc-id,Values=vpc-03fb25adbfa800687 --query 'Subnets[*].SubnetId' --output text
subnet-069203c44d7574802
取得したサブネットのIDを変数として代入してEC2を作成します。
#####################################################
# Variable
#####################################################
# Subnet ID
variable "subnet_id" {
type = string
default = "subnet-069203c44d7574802"
}
####################################################
# EC2
####################################################
# EC2
resource "aws_instance" "ec2" {
ami = "ami-08ce76bae392de7dc"
instance_type = "t3.nano"
availability_zone = "ap-northeast-1a"
subnet_id = var.subnet_id
}
それでは上記のEC2をデプロイします。
$ terraform plan
$ terraform apply
コンソール画面から確認してみましょう。
手動で作成したVPC上にEC2が立ち上がっていますね。
Data Sources
次にTerraformのData Sources機能を使ってみます。
Data SourcesはTerraformの外部で定義された情報を使用するための機能です。
今回はVPCの情報とサブネットの情報を取得して使用します。
それぞれ以下のドキュメントを参考にタグ名でフィルタリングしています。
######################################################################################
# Data Sources
######################################################################################
# VPC
data "aws_vpc" "main" {
filter {
name = "tag:Name"
values = ["demo_vpc"]
}
}
# Subnet
data "aws_subnet" "main" {
vpc_id = data.aws_vpc.main.id
filter {
name = "tag:Name"
values = ["demo_subnet"]
}
}
######################################################################################
# EC2
######################################################################################
# EC2
resource "aws_instance" "main" {
ami = "ami-08ce76bae392de7dc"
instance_type = "t3.nano"
availability_zone = "ap-northeast-1a"
+ subnet_id = data.aws_subnet.main.id
}
EC2のsubnet_idの部分にData Sourcesで取得したサブネットのIDを指定しています。
では、これでEC2をデプロイします。
$ terraform plan
$ terraform apply
既存のVPC上にEC2が起動していることが確認できますね。
Data Sourcesを使うことで、動的に既存リソースの情報を取得して利用することができました。
outputで取得した情報を確認
念の為、outputを指定してサブネットIDが取得できていることも確認しておきます。
######################################################################################
# Data Sources
######################################################################################
# VPC
data "aws_vpc" "main" {
filter {
name = "tag:Name"
values = ["demo_vpc"]
}
}
# Subnet
data "aws_subnet" "main" {
vpc_id = data.aws_vpc.main.id
filter {
name = "tag:Name"
values = ["demo_subnet"]
}
}
+# Subnet idを出力
+output "subnet" {
+ value = data.aws_subnet.main.id
+}
######################################################################################
# EC2
######################################################################################
# EC2
resource "aws_instance" "main" {
ami = "ami-08ce76bae392de7dc"
instance_type = "t3.nano"
availability_zone = "ap-northeast-1a"
subnet_id = data.aws_subnet.main.id
}
outputを追加して terraform output
します。
$ terraform output
subnet = "subnet-069203c44d7574802"
想定通りサブネットのIDが取得できていますね。
まとめ
既存リソースの値を参考にTerraformでリソースを追加する場合ってどうやるんだっけ?と疑問に思ったのでやってみました。
個人的には毎回変数を代入するのは面倒なのでData Sourcesを使うのが便利だと思いました。
また、Data Sourcesを使うと複数のサブネット情報をまとめて取得することもできるので、そういったプログラマチックな仕組みを作れるのもData Sourcesのメリットかなと思います。