

5分でわかるIaC(Terraform)でのAWS構築
こんにちは!プラットフォーム技術部の斉藤信次です。
昨今のAWS基盤開発要件で、IaC(Infrastructure as Code)を求められることが多くなった気がします。
そこで今回は、Terraformを使ってAWSの基本的なリソース作成を試してみようと思います。
Terraformとは
HashiCorp社が開発したクラウドやオンプレミスのリソースを、安全かつ効率的に構築、変更、バージョン管理するためのInfrastructure as Codeツールです。詳細はこちらをご参照ください。
IaC ( Infrastructure as Code ) とは?
簡単に要約すると「基盤開発をコードでインフラストラクチャーを定義し、構成管理する」手法です。AWSが提唱しているIaCはこちらをご参照ください。
作成するAWSリソース
AWSマネジメントコンソールから新規VPCを作成する際、セットで必要となる設定群を対象にterraformを使って一括作成してみようと思います。


事前準備
今回準備した環境は以下です。
- AWS
- IAMユーザー
- IAMユーザーには「AdministratorAccess」ポリシーをアタッチし、アクセスキーを発行しています。
- AWSアカウントに対してフルアクセス権限を付与することになるため十分に注意して利用してください。
- IAMユーザー
- ローカル環境
- Windows 10
インストール
Install Terraformからダウンロードして任意の場所に保存します。
私は「"C:\Windows\terraform\terraform.exe"」に保存しました。
コマンドプロンプトまたはPower Shellを起動して、「terraform」コマンドを実行してみましょう。
PS C:> terraform
Usage: terraform [global options] <subcommand> [args]
The available commands for execution are listed below.
The primary workflow commands are given first, followed by
less common or more advanced commands.
Main commands:
init Prepare your working directory for other commands
validate Check whether the configuration is valid
plan Show changes required by the current configuration
apply Create or update infrastructure
destroy Destroy previously-created infrastructure
All other commands:
console Try Terraform expressions at an interactive command prompt
fmt Reformat your configuration in the standard style
force-unlock Release a stuck lock on the current workspace
get Install or upgrade remote Terraform modules
graph Generate a Graphviz graph of the steps in an operation
import Associate existing infrastructure with a Terraform resource
login Obtain and save credentials for a remote host
logout Remove locally-stored credentials for a remote host
output Show output values from your root module
providers Show the providers required for this configuration
refresh Update the state to match remote systems
show Show the current state or a saved plan
state Advanced state management
taint Mark a resource instance as not fully functional
test Experimental support for module integration testing
untaint Remove the 'tainted' state from a resource instance
version Show the current Terraform version
workspace Workspace management
Global options (use these before the subcommand, if any):
-chdir=DIR Switch to a different working directory before executing the
given subcommand.
-help Show this help output, or the help for a specified subcommand.
-version An alias for the "version" subcommand.
PS C:>
バージョンを確認する場合は、「terraform -v」で確認できます。
PS C:> terraform -v
Terraform v1.3.3
on windows_amd64
Your version of Terraform is out of date! The latest version
is 1.3.9. You can update by downloading from https://www.terraform.io/downloads.html
PS C:>
Terraformの実行環境が整ったので、実際にコードを書いていきたいと思います。
Tfファイルを準備しよう
Terraformが読み込むファイルは「tfファイル」です。サンプルコードと同じように、今回は「main.tf」を1つ作成します。
main.tfの構造
ファイルの中身は、JSON形式で記載します。今回はAWSにリソースを作成するため、providersブロックはawsを指定します。IAMユーザーのアクセスキー、シークレットキーを追記しています(発行したキーに修正してください)。
providersブロックのあとに作成するAWSリソースのブロックを追記していきます。
リソースブロックの書き順は特にありません。Terraformは実行するときに全コードをチェックして、正しい順番で作成してくれます。
ブロックの説明はこちらをご参照ください。
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
}
}
}
provider "aws" {
region = "ap-northeast-1"
access_key = "ABCDEFGHIJK"
secret_key = "abcdefghijk123456789"
}
VPC
1から記載する必要はなく、公式ドキュメントのVPCサンプルコードがあるためそこからコピーします。
今回は「terraform-vpc」という名前のVPCを1つ作成します。
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
instance_tenancy = "default"
tags = {
Name = "terraform-vpc"
}
}
サブネット
サブネットはpublicサブネットと、privateサブネットを1つずつ作成します。サブネットサンプルコードからコピーします。
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.0.0/20"
availability_zone = "ap-northeast-1a"
tags = {
Name = "terraform-public-subnet"
}
}
resource "aws_subnet" "private" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.128.0/20"
availability_zone = "ap-northeast-1a"
tags = {
Name = "terraform-private-subnet"
}
}
Internet Gateway( IGW )
IGWは1つ作成します。IGWサンプルコードからコピーします。
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.main.id
tags = {
Name = "terraform-igw"
}
}
ルートテーブル
ルートテーブルは2つ作成します。publicサブネット用とprivateサブネット用の2つです。
public用ルートテーブルではIGW経由でインターネットに出ていく必要があるため、route定義を追記しています。
ルートテーブルサンプルコードからコピーします。
resource "aws_route_table" "public_rtb" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
tags = {
Name = "terraform-public-rtb"
}
}
resource "aws_route_table" "private_rtb" {
vpc_id = aws_vpc.main.id
tags = {
Name = "terraform-private-rtb"
}
}
ルートテーブルの関連付け
ルートテーブルを作成したあとは、サブネットにアタッチする必要があります。public用ルートテーブルはpublicサブネットに、privateルートテーブルはprivateサブネットにアタッチします。
ルートテーブル関連付けサンプルコードからコピーします。
resource "aws_route_table_association" "public_rtb_attach" {
subnet_id = aws_subnet.public.id
route_table_id = aws_route_table.public_rtb.id
}
resource "aws_route_table_association" "private_rtb_attach" {
subnet_id = aws_subnet.private.id
route_table_id = aws_route_table.private_rtb.id
}
完成したmain.tf
各ブロック単位を順に記載してできたmain.tfです。
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
}
}
}
provider "aws" {
region = "ap-northeast-1"
access_key = "ABCDEFGHIJK"
secret_key = "abcdefghijk123456789"
}
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
instance_tenancy = "default"
tags = {
Name = "terraform-vpc"
}
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.0.0/20"
availability_zone = "ap-northeast-1a"
tags = {
Name = "terraform-public-subnet"
}
}
resource "aws_subnet" "private" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.128.0/20"
availability_zone = "ap-northeast-1a"
tags = {
Name = "terraform-private-subnet"
}
}
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.main.id
tags = {
Name = "terraform-igw"
}
}
resource "aws_route_table" "public_rtb" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
tags = {
Name = "terraform-public-rtb"
}
}
resource "aws_route_table" "private_rtb" {
vpc_id = aws_vpc.main.id
tags = {
Name = "terraform-private-rtb"
}
}
resource "aws_route_table_association" "public_rtb_attach" {
subnet_id = aws_subnet.public.id
route_table_id = aws_route_table.public_rtb.id
}
resource "aws_route_table_association" "private_rtb_attach" {
subnet_id = aws_subnet.private.id
route_table_id = aws_route_table.private_rtb.id
}
Terraformを実行してみよう
作成したmain.tfファイルを任意の場所に保存します。
私はわかりやすく、terraformと同じ場所「"C:\Windows\terraform\main.tf"」に保存しています。
terraform command
terraformコマンドの意味を見てみましょう。
Main commands:
init Prepare your working directory for other commands
validate Check whether the configuration is valid
plan Show changes required by the current configuration
apply Create or update infrastructure
destroy Destroy previously-created infrastructure
All other commands:
fmt Reformat your configuration in the standard style
基本的には、main commandの順序で実行すれば問題はありません。
JSON形式で記載されていない箇所を自動成形してくれる「fmt」コマンドは便利なので、ぜひ覚えておいてください。実行する前に「fmt」コマンドを実行することをお勧めします。
今回は作成だけするので「destroy(削除)」はしません。
terraform init
コマンドプロンプトまたはPower Shellを起動して実行してみましょう。
main.tfがあるディレクトリに移動したら、コマンドを実行します。
24行目に「Terraform has been successfully initialized!」と表示されているのと、39行名に「.terraform」ディレクトリが作成されているのがわかります。
これで初期化が終わりました。
PS C:Windowsterraform> Get-ChildItem
ディレクトリ: C:Windowsterraform
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2023/02/17 10:52 1620 main.tf
-a---- 2023/02/16 15:10 62153392 terraform.exe
PS C:Windowsterraform> terraform init
Initializing the backend...
Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v4.55.0...
- Installed hashicorp/aws v4.55.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
PS C:Windowsterraform> Get-ChildItem
ディレクトリ: C:Windowsterraform
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2023/02/17 11:21 .terraform
-a---- 2023/02/17 11:21 1377 .terraform.lock.hcl
-a---- 2023/02/17 10:52 1620 main.tf
-a---- 2023/02/16 15:10 62153392 terraform.exe
PS C:Windowsterraform>
terraform fmt
意図的に1ヶ所だけJSON形式ではないようにして、main.tfを保存しています。
この状態で「fmt」コマンドを実行してみます。コードをチェックして自動的に成形してくれると思いますので実行してみましょう。
PS C:Windowsterraform> terraform fmt
main.tf
PS C:Windowsterraform>
PS C:Windowsterraform> terraform fmt
PS C:Windowsterraform>
2行目に「main.tf」と表示されているので成形されました。
もう一度実行してみます。間違っている箇所がない場合は、何も表示されないので問題がないということがわかります。
terraform validate
validateコマンドは構文チェックです。各ブロックで記載した内容に問題ないか確認してくれます。
PS C:Windowsterraform> terraform validate
Success! The configuration is valid.
PS C:Windowsterraform>
2行目に「Success! The configuration is valid.」と表示されたので構文チェックはOKです。
意図的に間違えた状態で実行してみようと思います。
PS C:Windowsterraform> terraform validate
╷
│ Error: Reference to undeclared resource
│
│ on main.tf line 43, in resource "aws_internet_gateway" "igw":
│ 43: vpc_id = aws_vpc.mainn.id
│
│ A managed resource "aws_vpc" "mainn" has not been declared in the root module.
╵
PS C:Windowsterraform>
main.tf の 43行目が間違っていると言われていますね。aws_vpc.mainn.idが違うようです。
指摘箇所は意図的に間違えた箇所であり、n を一つ多く記述しています。これで構文チェックされていることがわかります。
terraform plan
planを実行すると実際に作られるリソース一覧が出力されます。ここで最後の間違いに気づけますので、必ず実行しましょう。
PS C:Windowsterraform> terraform plan
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
+ create
Terraform will perform the following actions:
# aws_internet_gateway.igw will be created
+ resource "aws_internet_gateway" "igw" {
+ arn = (known after apply)
+ id = (known after apply)
+ owner_id = (known after apply)
+ tags = {
+ "Name" = "terraform-igw"
}
+ tags_all = {
+ "Name" = "terraform-igw"
}
+ vpc_id = (known after apply)
}
# aws_route_table.private_rtb will be created
+ resource "aws_route_table" "private_rtb" {
+ arn = (known after apply)
+ id = (known after apply)
+ owner_id = (known after apply)
+ propagating_vgws = (known after apply)
+ route = (known after apply)
+ tags = {
+ "Name" = "terraform-private-rtb"
}
+ tags_all = {
+ "Name" = "terraform-private-rtb"
}
+ vpc_id = (known after apply)
}
# aws_route_table.public_rtb will be created
+ resource "aws_route_table" "public_rtb" {
+ arn = (known after apply)
+ id = (known after apply)
+ owner_id = (known after apply)
+ propagating_vgws = (known after apply)
+ route = [
+ {
+ carrier_gateway_id = ""
+ cidr_block = "0.0.0.0/0"
+ core_network_arn = ""
+ destination_prefix_list_id = ""
+ egress_only_gateway_id = ""
+ gateway_id = (known after apply)
+ instance_id = ""
+ ipv6_cidr_block = ""
+ local_gateway_id = ""
+ nat_gateway_id = ""
+ network_interface_id = ""
+ transit_gateway_id = ""
+ vpc_endpoint_id = ""
+ vpc_peering_connection_id = ""
},
]
+ tags = {
+ "Name" = "terraform-public-rtb"
}
+ tags_all = {
+ "Name" = "terraform-public-rtb"
}
+ vpc_id = (known after apply)
}
# aws_route_table_association.private_rtb_attach will be created
+ resource "aws_route_table_association" "private_rtb_attach" {
+ id = (known after apply)
+ route_table_id = (known after apply)
+ subnet_id = (known after apply)
}
# aws_route_table_association.public_rtb_attach will be created
+ resource "aws_route_table_association" "public_rtb_attach" {
+ id = (known after apply)
+ route_table_id = (known after apply)
+ subnet_id = (known after apply)
}
# aws_subnet.private will be created
+ resource "aws_subnet" "private" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = "ap-northeast-1a"
+ availability_zone_id = (known after apply)
+ cidr_block = "10.0.128.0/20"
+ enable_dns64 = false
+ enable_resource_name_dns_a_record_on_launch = false
+ enable_resource_name_dns_aaaa_record_on_launch = false
+ id = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ ipv6_native = false
+ map_public_ip_on_launch = false
+ owner_id = (known after apply)
+ private_dns_hostname_type_on_launch = (known after apply)
+ tags = {
+ "Name" = "terraform-private-subnet"
}
+ tags_all = {
+ "Name" = "terraform-private-subnet"
}
+ vpc_id = (known after apply)
}
# aws_subnet.public will be created
+ resource "aws_subnet" "public" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = "ap-northeast-1a"
+ availability_zone_id = (known after apply)
+ cidr_block = "10.0.0.0/20"
+ enable_dns64 = false
+ enable_resource_name_dns_a_record_on_launch = false
+ enable_resource_name_dns_aaaa_record_on_launch = false
+ id = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ ipv6_native = false
+ map_public_ip_on_launch = false
+ owner_id = (known after apply)
+ private_dns_hostname_type_on_launch = (known after apply)
+ tags = {
+ "Name" = "terraform-public-subnet"
}
+ tags_all = {
+ "Name" = "terraform-public-subnet"
}
+ vpc_id = (known after apply)
}
# aws_vpc.main will be created
+ resource "aws_vpc" "main" {
+ arn = (known after apply)
+ cidr_block = "10.0.0.0/16"
+ default_network_acl_id = (known after apply)
+ default_route_table_id = (known after apply)
+ default_security_group_id = (known after apply)
+ dhcp_options_id = (known after apply)
+ enable_classiclink = (known after apply)
+ enable_classiclink_dns_support = (known after apply)
+ enable_dns_hostnames = (known after apply)
+ enable_dns_support = true
+ enable_network_address_usage_metrics = (known after apply)
+ id = (known after apply)
+ instance_tenancy = "default"
+ ipv6_association_id = (known after apply)
+ ipv6_cidr_block = (known after apply)
+ ipv6_cidr_block_network_border_group = (known after apply)
+ main_route_table_id = (known after apply)
+ owner_id = (known after apply)
+ tags = {
+ "Name" = "terraform-vpc"
}
+ tags_all = {
+ "Name" = "terraform-vpc"
}
}
Plan: 8 to add, 0 to change, 0 to destroy.
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if
you run "terraform apply" now.
PS C:Windowsterraform>
ブロック単位でリソース定義した箇所が表示されていることがわかります。IDなどは表示されません。なぜなら、実際に作成しないと発行されない箇所になるからです。
164行目に「Plan: 8 to add, 0 to change, 0 to destroy.」と出力されています。これはAddが8なので、8個のリソースを作成するということです。変更と削除はないため、0個です。
terraform apply
applyでAWSにリソースを作成します。
PS C:Windowsterraform> terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
+ create
Terraform will perform the following actions:
# aws_internet_gateway.igw will be created
+ resource "aws_internet_gateway" "igw" {
+ arn = (known after apply)
+ id = (known after apply)
+ owner_id = (known after apply)
+ tags = {
+ "Name" = "terraform-igw"
}
+ tags_all = {
+ "Name" = "terraform-igw"
}
+ vpc_id = (known after apply)
}
# aws_route_table.private_rtb will be created
+ resource "aws_route_table" "private_rtb" {
+ arn = (known after apply)
+ id = (known after apply)
+ owner_id = (known after apply)
+ propagating_vgws = (known after apply)
+ route = (known after apply)
+ tags = {
+ "Name" = "terraform-private-rtb"
}
+ tags_all = {
+ "Name" = "terraform-private-rtb"
}
+ vpc_id = (known after apply)
}
# aws_route_table.public_rtb will be created
+ resource "aws_route_table" "public_rtb" {
+ arn = (known after apply)
+ id = (known after apply)
+ owner_id = (known after apply)
+ propagating_vgws = (known after apply)
+ route = [
+ {
+ carrier_gateway_id = ""
+ cidr_block = "0.0.0.0/0"
+ core_network_arn = ""
+ destination_prefix_list_id = ""
+ egress_only_gateway_id = ""
+ gateway_id = (known after apply)
+ instance_id = ""
+ ipv6_cidr_block = ""
+ local_gateway_id = ""
+ nat_gateway_id = ""
+ network_interface_id = ""
+ transit_gateway_id = ""
+ vpc_endpoint_id = ""
+ vpc_peering_connection_id = ""
},
]
+ tags = {
+ "Name" = "terraform-public-rtb"
}
+ tags_all = {
+ "Name" = "terraform-public-rtb"
}
+ vpc_id = (known after apply)
}
# aws_route_table_association.private_rtb_attach will be created
+ resource "aws_route_table_association" "private_rtb_attach" {
+ id = (known after apply)
+ route_table_id = (known after apply)
+ subnet_id = (known after apply)
}
# aws_route_table_association.public_rtb_attach will be created
+ resource "aws_route_table_association" "public_rtb_attach" {
+ id = (known after apply)
+ route_table_id = (known after apply)
+ subnet_id = (known after apply)
}
# aws_subnet.private will be created
+ resource "aws_subnet" "private" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = "ap-northeast-1a"
+ availability_zone_id = (known after apply)
+ cidr_block = "10.0.128.0/20"
+ enable_dns64 = false
+ enable_resource_name_dns_a_record_on_launch = false
+ enable_resource_name_dns_aaaa_record_on_launch = false
+ id = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ ipv6_native = false
+ map_public_ip_on_launch = false
+ owner_id = (known after apply)
+ private_dns_hostname_type_on_launch = (known after apply)
+ tags = {
+ "Name" = "terraform-private-subnet"
}
+ tags_all = {
+ "Name" = "terraform-private-subnet"
}
+ vpc_id = (known after apply)
}
# aws_subnet.public will be created
+ resource "aws_subnet" "public" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = "ap-northeast-1a"
+ availability_zone_id = (known after apply)
+ cidr_block = "10.0.0.0/20"
+ enable_dns64 = false
+ enable_resource_name_dns_a_record_on_launch = false
+ enable_resource_name_dns_aaaa_record_on_launch = false
+ id = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ ipv6_native = false
+ map_public_ip_on_launch = false
+ owner_id = (known after apply)
+ private_dns_hostname_type_on_launch = (known after apply)
+ tags = {
+ "Name" = "terraform-public-subnet"
}
+ tags_all = {
+ "Name" = "terraform-public-subnet"
}
+ vpc_id = (known after apply)
}
# aws_vpc.main will be created
+ resource "aws_vpc" "main" {
+ arn = (known after apply)
+ cidr_block = "10.0.0.0/16"
+ default_network_acl_id = (known after apply)
+ default_route_table_id = (known after apply)
+ default_security_group_id = (known after apply)
+ dhcp_options_id = (known after apply)
+ enable_classiclink = (known after apply)
+ enable_classiclink_dns_support = (known after apply)
+ enable_dns_hostnames = (known after apply)
+ enable_dns_support = true
+ enable_network_address_usage_metrics = (known after apply)
+ id = (known after apply)
+ instance_tenancy = "default"
+ ipv6_association_id = (known after apply)
+ ipv6_cidr_block = (known after apply)
+ ipv6_cidr_block_network_border_group = (known after apply)
+ main_route_table_id = (known after apply)
+ owner_id = (known after apply)
+ tags = {
+ "Name" = "terraform-vpc"
}
+ tags_all = {
+ "Name" = "terraform-vpc"
}
}
Plan: 8 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_vpc.main: Creating...
aws_vpc.main: Creation complete after 1s [id=vpc-080f8dbc317a17f9c]
aws_internet_gateway.igw: Creating...
aws_route_table.private_rtb: Creating...
aws_subnet.private: Creating...
aws_subnet.public: Creating...
aws_internet_gateway.igw: Creation complete after 1s [id=igw-00a43d4e6323e8933]
aws_route_table.public_rtb: Creating...
aws_route_table.private_rtb: Creation complete after 1s [id=rtb-01fd73b9b4c410575]
aws_subnet.private: Creation complete after 1s [id=subnet-0ed97fac09d417599]
aws_route_table_association.private_rtb_attach: Creating...
aws_subnet.public: Creation complete after 1s [id=subnet-080cff740fbc9bdd4]
aws_route_table_association.private_rtb_attach: Creation complete after 0s [id=rtbassoc-0b05c320fa2675774]
aws_route_table.public_rtb: Creation complete after 1s [id=rtb-0ae5793471c343776]
aws_route_table_association.public_rtb_attach: Creating...
aws_route_table_association.public_rtb_attach: Creation complete after 0s [id=rtbassoc-0b87f7557f3d73d75]
Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
PS C:Windowsterraform>
170行目で「yes」を入力しています。実行を許可するためには「yes」を入力しないと実行されません。
189行目に「Apply complete!」と出力されているので全てのリソースが作成されたことを意味します。
実際にAWSマネジメントコンソールから作成されているか見てみましょう。








全て作成されていました。applyは1分もかかっていないので、このぐらいのリソースなら数秒で作成されている感じですね。
まとめ
今回はTerraformの基本的な使い方を紹介しました。作るリソース数が多い場合や構成管理する場合などにIaCはとても便利なツールだと思います。
次回は、Terraformの少し応用的な使い方を紹介します。