作りながら覚えるTerraform入門シリーズの第2回です。
第1回の インストールと初期設定 でTerraformを使う準備ができたので、とりあえず動かしてみましょう。
最初はVPCの操作を通じてTerraformの基本的なコマンドを覚えるのが良いと思います。
作りながら覚えるTerraform入門シリーズ
- インストールと初期設定
- 基本編 => 今回はコチラ
- VPC編
- EC2編
- Route53 + ACM編
- ELB編
- RDS編
今回の学習ポイントは以下です。
- Resourceブロックの書き方
- terraform init / plan / apply / destroyの実行の流れ
- Terraformの実行計画の見方
VPCの作成
まず、作業用のフォルダを作成しておきます。
mkdir terraform
cd terraform/
provider.tf
というファイルを作成して、以下のコードを貼り付けます。
拡張子が.tf
であればファイル名は任意で大丈夫です。
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
provider.tf
にはAWSにリソースを作成するための宣言を記述します。
デフォルトリージョンもここで指定しておきます。このあたりはお決まりの構文ですね。
公式ドキュメントのAWS Providerを参考にしています。
続いて、network.tf
というファイルを作成して、以下のコードを貼り付けます。
ファイルを分ける必要はありませんが、リソースごとに分けたほうが管理がしやすくなります。
# Resourceブロックで「aws_vpc」を指定してVPCを作成
resource "aws_vpc" "vpc" {
cidr_block = "10.0.0.0/16"
instance_tenancy = "default"
tags = {
Name = "my-vpc"
}
}
resource
から始まる箇所をResourceブロックと呼びます。
resource
に続けて以下の引数を与えて、波括弧{}で囲った中にパラメータを記述します。
①第1引数:リソースタイプ
②第2引数:任意の識別名
①はAWSのリソースタイプで、aws_*
の形になっています。Azureであればazurerm_*
といった形。
基本的には*の箇所にサービス名が入るので連想しやすいですが、公式リファレンスを参照しながら記述します。
aws_vpc
であれば、Resource: aws_vpc です。
②は識別名なので自由に命名できますが、他のリソースと重複はできません。
ここの命名に意外と悩んだりしますが、最初はとりあえず動かすことを目的としてexample
やmain
としておくのも一つの手です。
作成したコードを元にリソースを作成してみましょう。
リソースを作成するには、terraform apply
を実行します。
terraform apply
╷
│ Error: Could not load plugin
│
│
│ Plugin reinitialization required. Please run "terraform init".
:
そうすると、プラグインが読み込めないのでterraform init
を実行するようエラーが表示されます。Terraformのインストールによってコマンド自体は利用できるようになりますが、AWSやAzureなど各サービス(プロバイダー)を利用するためのプラグインは分離されているため、まず最初にterraform init
を実行してダウンロード(初期化)する必要があります。
terraform init
Initializing the backend...
Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v3.44.0...
- Installed hashicorp/aws v3.44.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!
:
terraform init
を実行すると、.terraform
ディレクトリと.terraform.lock.hcl
ファイルが作成されます。.terraform
ディレクトリが「AWS」というプロバイダーを利用するためのもの、.terraform.lock.hcl
は依存関係をコントロールするためのロックファイル、くらいに考えておきましょう。
tree -a
.
├── .terraform
│ └── providers
│ └── registry.terraform.io
│ └── hashicorp
│ └── aws
│ └── 3.44.0
│ └── darwin_amd64
│ └── terraform-provider-aws_v3.44.0_x5
├── .terraform.lock.hcl
├── network.tf
└── provider.tf
それでは、改めてterraform apply
を実行してみます。
「Do you want to perform these actions?」と確認を求められるので「yes」と入力して進めます。
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_vpc.vpc will be created
+ resource "aws_vpc" "vpc" {
+ arn = (known after apply)
+ assign_generated_ipv6_cidr_block = false
+ 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
+ id = (known after apply)
+ instance_tenancy = "default"
+ ipv6_association_id = (known after apply)
+ ipv6_cidr_block = (known after apply)
+ main_route_table_id = (known after apply)
+ owner_id = (known after apply)
+ tags = {
+ "Name" = "my-vpc"
}
+ tags_all = {
+ "Name" = "my-vpc"
}
}
Plan: 1 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.vpc: Creating...
aws_vpc.vpc: Creation complete after 2s [id=vpc-0e32cf9d1213b770d]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
最後の「Apply complete!」の行を見ると1 added
となっていて、1つのリソースが追加されたことがわかります。コンソール画面を確認してみると、「my-vpc」のNameタグが付いたVPCが作成できていることがわかります。
VPCの更新
続いて、更新の動きを見ていきましょう。
試しにnetwork.tf
のNameタグを「my-first-vpc」に変更してみます。
resource "aws_vpc" "vpc" {
cidr_block = "10.0.0.0/16"
instance_tenancy = "default"
tags = {
Name = "my-first-vpc"
}
}
もう一度terraform apply
を実行して適用してみましょう。
terraform apply
aws_vpc.vpc: Refreshing state... [id=vpc-0e32cf9d1213b770d]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
~ update in-place
Terraform will perform the following actions:
# aws_vpc.vpc will be updated in-place
~ resource "aws_vpc" "vpc" {
id = "vpc-0e32cf9d1213b770d"
~ tags = {
~ "Name" = "my-vpc" -> "my-first-vpc"
}
~ tags_all = {
~ "Name" = "my-vpc" -> "my-first-vpc"
}
# (14 unchanged attributes hidden)
}
Plan: 0 to add, 1 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.vpc: Modifying... [id=vpc-0e32cf9d1213b770d]
aws_vpc.vpc: Modifications complete after 2s [id=vpc-0e32cf9d1213b770d]
Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
1 changed
と表示されて更新されたことがわかります。
コンソール画面からもNameタグが変更できていることを確認しておきましょう。
次はcidr_block
を「192.168.0.0/16」に変更してみます。
resource "aws_vpc" "vpc" {
cidr_block = "192.168.0.0/16"
instance_tenancy = "default"
tags = {
Name = "my-first-vpc"
}
}
terraform apply
を実行して適用してみましょう。
terraform apply
aws_vpc.vpc: Refreshing state... [id=vpc-0e32cf9d1213b770d]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement
Terraform will perform the following actions:
# aws_vpc.vpc must be replaced
-/+ resource "aws_vpc" "vpc" {
~ arn = "arn:aws:ec2:ap-northeast-1:123456789012:vpc/vpc-0e32cf9d1213b770d" -> (known after apply)
~ cidr_block = "10.0.0.0/16" -> "192.168.0.0/16" # forces replacement
~ default_network_acl_id = "acl-009e09c086ff9c692" -> (known after apply)
~ default_route_table_id = "rtb-0b555443103cfbe0b" -> (known after apply)
~ default_security_group_id = "sg-0af32faf28e1dfa87" -> (known after apply)
~ dhcp_options_id = "dopt-2489e243" -> (known after apply)
~ enable_classiclink = false -> (known after apply)
~ enable_classiclink_dns_support = false -> (known after apply)
~ enable_dns_hostnames = false -> (known after apply)
~ id = "vpc-0e32cf9d1213b770d" -> (known after apply)
+ ipv6_association_id = (known after apply)
+ ipv6_cidr_block = (known after apply)
~ main_route_table_id = "rtb-0b555443103cfbe0b" -> (known after apply)
~ owner_id = "123456789012" -> (known after apply)
tags = {
"Name" = "my-first-vpc"
}
# (4 unchanged attributes hidden)
}
Plan: 1 to add, 0 to change, 1 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.vpc: Destroying... [id=vpc-0e32cf9d1213b770d]
aws_vpc.vpc: Destruction complete after 0s
aws_vpc.vpc: Creating...
aws_vpc.vpc: Creation complete after 3s [id=vpc-05c92959157ff59d0]
Apply complete! Resources: 1 added, 0 changed, 1 destroyed.
今回のcidr_block
の変更のように既存リソースの変更では対応できないケースは削除→作成の置き換えの動作になります。
後述しますが、実行計画の中に「replaced」や「forces replacement」という文字が含まれている場合は、それが意図したものなのか十分に確認してから実行する必要があります。
VPCの削除
最後に、作成したVPCを削除してみましょう。
リソースを削除するには、terraform destroy
を実行します。
applyの時と同じように「yes」を入力して実行してみましょう。
terraform destroy
aws_vpc.vpc: Refreshing state... [id=vpc-05c92959157ff59d0]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
# aws_vpc.vpc will be destroyed
- resource "aws_vpc" "vpc" {
- arn = "arn:aws:ec2:ap-northeast-1:123456789012:vpc/vpc-05c92959157ff59d0" -> null
- assign_generated_ipv6_cidr_block = false -> null
- cidr_block = "192.168.0.0/16" -> null
- default_network_acl_id = "acl-0896f7ab7cd8e3bbd" -> null
- default_route_table_id = "rtb-0ba11eb799c733669" -> null
- default_security_group_id = "sg-0ddd72a743034c145" -> null
- dhcp_options_id = "dopt-2489e243" -> null
- enable_classiclink = false -> null
- enable_classiclink_dns_support = false -> null
- enable_dns_hostnames = false -> null
- enable_dns_support = true -> null
- id = "vpc-05c92959157ff59d0" -> null
- instance_tenancy = "default" -> null
- main_route_table_id = "rtb-0ba11eb799c733669" -> null
- owner_id = "123456789012" -> null
- tags = {
- "Name" = "my-first-vpc"
} -> null
- tags_all = {
- "Name" = "my-first-vpc"
} -> null
}
Plan: 0 to add, 0 to change, 1 to destroy.
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
aws_vpc.vpc: Destroying... [id=vpc-05c92959157ff59d0]
aws_vpc.vpc: Destruction complete after 0s
Destroy complete! Resources: 1 destroyed.
1 destroyed
と表示されて削除されたことがわかりますね。
Terraformの実行計画
これまで見てきたように、terraform apply
やterraform destroy
を実行すると、これから起こる変更差分を「実行計画」として表示してくれます。
実行したコマンドの中にあるTerraform will perform the following actions
の箇所を振り返ってみてください。それぞれこれから行われる処理を示してくれています。
- aws_vpc.vpc will be created
- aws_vpc.vpc will be updated in-place
- aws_vpc.vpc must be replaced
- aws_vpc.vpc will be destroyed
リソースやパラメータの頭にある記号からも判別できます。
なお、何も変更がない場合はNo changes.
と表示されます。
- 作成: +
- 更新: ~
- 削除: -
- 置き換え: -/+
繰り返しになりますが、単なる更新で済む場合と、作り直しになる場合があります。このあたりの挙動はコンソール画面から実施する場合と同じですが、実行計画はよく確認するように心がけましょう。
Terraformの基本コマンド
この記事ではVPCの作成と削除を通じて、init → apply → destroyを実行して、初期化 → 適用 → 削除を行いましたが、その他のよく使うコマンドも確認しておきましょう。
validate
terraform validate
を実行すると、構文に誤りがないか、パラメータが適切かチェックすることができます。
# valid
terraform validate
Success! The configuration is valid.
# invalid (cidr_blockの範囲が誤っている例)
terraform validate
Error: expected cidr_block to contain a valid network Value, expected 10.0.0.0/16, got 10.0.1.0/16
│
│ with aws_vpc.vpc,
│ on network.tf line 2, in resource "aws_vpc" "vpc":
│ 2: cidr_block = "10.0.1.0/16"
plan
先に実践した例ではterraform apply
をいきなり実行しましたが、terraform plan
を実行すると実行計画の確認のみ行うことができます。applyやdestroyはせずに実行計画だけ確認したい場合に利用します。
fmt
terraform fmt
を実行するとインデントを整えて見た目をキレイにしてくれます。-recursive
のオプションを付け加えるとサブディレクトリ含めて再帰的にフォーマットしてくれます。(付けない場合はカレントディレクトリの.tfファイルのみ)
が、インストールと初期設定でご紹介したように、VSCode拡張機能を利用して自動フォーマットを有効にすることをオススメします。
console
terraform console
を実行すると対話型のコンソールを起動することができます。変数の値や関数の評価結果を確認したい場合に便利です。コンソールを終了するにはexit
を入力します。
terraform console
> max(5, 12, 9)
12
他にもありますが、とりあえずこのあたりの基本コマンドを覚えておけば困らないと思います。
コマンド実行の流れ
私の場合は、initのあとはvalidate → plan → applyを繰り返して、いらなくなったらdestoryするって形で学習を進めました。学習環境は作って壊すの繰り返しなので、インストールと初期設定でご紹介したように、applyとdestoryの時に「yes」を入力しなくて済むように-auto-approve
を付け加えたエイリアス設定を利用してtf init → tfv → tfp → tfa → tfdの流れで実行しています。エイリアス設定を再掲しておきます。
alias tf="terraform"
alias tfp="terraform plan"
alias tfv="terraform validate"
alias tff="terraform fmt -recursive"
alias tfa="terraform apply -auto-approve"
alias tfd="terraform destroy -auto-approve"
今回は以上です。次回はVPC編ということで、サブネットやルートテーブルなど含め、改めてVPC関連のリソースを作成する方法について書いてみたいと思います!