はじめに
Terraform
の開発環境が整ったので、今回からTerraform
を使ってAWS
への構築を進めてみようと思います。
Terraform実行方法
実際にAWS
のEC2インスタンスを作成する例を基にTerraform
を実行してみます。
- コーディング
- terraform initの実行(初回のみ)
- terraform fmtの実行
- terraform planの実行
- terraform applyの実行
コーディング
前回インストールしたVS Code
でコーディングを行う場合、「~.tf」という拡張子にすることでTerraform
のフォーマットだと認識されます。
EC2インスタンスを作成する場合、最低限以下のようなコーディングを行うことで作成することができます。
provider "aws" {
region = "ap-northeast-1"
profile = "default"
}
resource "aws_instance" "testtf" {
ami = "ami-0b7546e839d7ace12"
instance_type = "t3.micro"
}
各種リソースで指定可能な設定やオプションは以下のオンラインドキュメントを参照することで確認できます。
今回の場合、Terraform
が暗黙でAWS
への実行だと判断し、セットアップ済みのAWS CLI
のデフォルトクレデンシャル情報を使用して接続しに行くため、provider
ブロックは無くても動作しますが、意図しない動作とならないよう、明示するようにしましょう。
terraform initの実行(初回のみ)
terraform init
コマンドを実行することで、カレントディレクトリに.terraform.locl.hcl
ファイルと.terraform
フォルダが作成され、その中に各種プロバイダのリソース作成に必要となるバイナリファイルがダウンロードされます。
ファイル・フォルダ名 | 説明 |
---|---|
main.tf | 作成したソースコード |
.terraform | AWS等の各種プロバイダリソース作成用バイナリファイル格納 |
.terraform.lock.hcl | 各種プロバイダファイルのロックファイル |
.terraform.lock.hcl
は以下のようなファイルとなります。
実行環境が変わったとしてもProvider
の動作が変わらないようにするためのファイルとのこと。
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/aws" {
version = "4.20.1"
hashes = [
"h1:mU0Rl9mMkny1Q34aiQMSTA2R/wfVPJgHQGM+/GYUfG0=",
"zh:21d064d8fac08376c633e002e2f36e83eb7958535e251831feaf38f51c49dafd",
"zh:3a37912ff43d89ce8d559ec86265d7506801bccb380c7cfb896e8ff24e3fe79d",
"zh:795eb175c85279ec51dbe12e4d1afa0860c2c0b22e5d36a8e8869f60a93b7931",
"zh:8afb61a18b17f8ff249cb23e9d3b5d2530944001ef1d56c1d53f41b0890c7ab8",
"zh:911701040395e0e4da4b7252279e7cf1593cdd26f22835e1a9eddbdb9691a1a7",
"zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
"zh:a46d54a6a5407f569f8178e916af888b2b268f86448c64cad165dc89759c8399",
"zh:c5f71fd5e3519a24fd6af455ef1c26a559cfdde7f626b0afbd2a73bb79f036b1",
"zh:df3b69d6c9b0cdc7e3f90ee08412b22332c32e97ad8ce6ccad528f89f235a7d3",
"zh:e99d6a64c03549d60c2accf792fa04466cfb317f72e895c8f67eff8a02920887",
"zh:eea7a0df8bcb69925c9ce8e15ef403c8bbf16d46c43e8f5607b116531d1bce4a",
"zh:f6a26ce77f7db1d50ce311e32902fd001fb365e5e45e47a9a5cd59d734c89cb6",
]
}
また、terraform init
を実行した場合、以下のような結果が出力され、各種プロバイダリソース作成用バイナリのダウンロードや初期化が行われます。
$ terraform init
Initializing the backend...
Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v4.20.1...
- Installed hashicorp/aws v4.20.1 (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.
terraform fmtの実行
terraform fmt
は毎回実行しなくても良いですが、terraform fmt
を実行すると、先ほどコーディングしたソースファイルのフォーマットを整えてくれるため、コーディング後には実行したほうがよいでしょう。
terraform fmt
ちなみに先ほどコーディングしたmain.tf
にterraform fmt
コマンドを実行した場合、以下のように整形されます。
provider "aws" {
region = "ap-northeast-1"
profile = "default"
}
resource "aws_instance" "testtf" {
ami = "ami-0b7546e839d7ace12"
instance_type = "t3.micro"
}
terraform planの実行
terraform plan
を実行すると、どのようなリソースが作成・変更・削除されるかといった情報を確認することができます。
確認だけで作成はされないため、次のterraform apply
コマンドを実行する前の確認用途で使います。
以下「+」で表示されるリソースは、terraform apply
実行時に作成されるリソース、(今回はありませんが)「~」で表示されるリソースはterraform apply
実行時に削除されるリソースとなります。
terraform planの実行結果(展開してください)
$ 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_instance.testtf will be created
+ resource "aws_instance" "testtf" {
+ ami = "ami-0b7546e839d7ace12"
+ arn = (known after apply)
+ associate_public_ip_address = (known after apply)
+ availability_zone = (known after apply)
+ cpu_core_count = (known after apply)
+ cpu_threads_per_core = (known after apply)
+ disable_api_stop = (known after apply)
+ disable_api_termination = (known after apply)
+ ebs_optimized = (known after apply)
+ get_password_data = false
+ host_id = (known after apply)
+ id = (known after apply)
+ instance_initiated_shutdown_behavior = (known after apply)
+ instance_state = (known after apply)
+ instance_type = "t3.micro"
+ ipv6_address_count = (known after apply)
+ ipv6_addresses = (known after apply)
+ key_name = (known after apply)
+ monitoring = (known after apply)
+ outpost_arn = (known after apply)
+ password_data = (known after apply)
+ placement_group = (known after apply)
+ placement_partition_number = (known after apply)
+ primary_network_interface_id = (known after apply)
+ private_dns = (known after apply)
+ private_ip = (known after apply)
+ public_dns = (known after apply)
+ public_ip = (known after apply)
+ secondary_private_ips = (known after apply)
+ security_groups = (known after apply)
+ source_dest_check = true
+ subnet_id = (known after apply)
+ tags_all = (known after apply)
+ tenancy = (known after apply)
+ user_data = (known after apply)
+ user_data_base64 = (known after apply)
+ user_data_replace_on_change = false
+ vpc_security_group_ids = (known after apply)
+ capacity_reservation_specification {
+ capacity_reservation_preference = (known after apply)
+ capacity_reservation_target {
+ capacity_reservation_id = (known after apply)
+ capacity_reservation_resource_group_arn = (known after apply)
}
}
+ ebs_block_device {
+ delete_on_termination = (known after apply)
+ device_name = (known after apply)
+ encrypted = (known after apply)
+ iops = (known after apply)
+ kms_key_id = (known after apply)
+ snapshot_id = (known after apply)
+ tags = (known after apply)
+ throughput = (known after apply)
+ volume_id = (known after apply)
+ volume_size = (known after apply)
+ volume_type = (known after apply)
}
+ enclave_options {
+ enabled = (known after apply)
}
+ ephemeral_block_device {
+ device_name = (known after apply)
+ no_device = (known after apply)
+ virtual_name = (known after apply)
}
+ maintenance_options {
+ auto_recovery = (known after apply)
}
+ metadata_options {
+ http_endpoint = (known after apply)
+ http_put_response_hop_limit = (known after apply)
+ http_tokens = (known after apply)
+ instance_metadata_tags = (known after apply)
}
+ network_interface {
+ delete_on_termination = (known after apply)
+ device_index = (known after apply)
+ network_card_index = (known after apply)
+ network_interface_id = (known after apply)
}
+ private_dns_name_options {
+ enable_resource_name_dns_a_record = (known after apply)
+ enable_resource_name_dns_aaaa_record = (known after apply)
+ hostname_type = (known after apply)
}
+ root_block_device {
+ delete_on_termination = (known after apply)
+ device_name = (known after apply)
+ encrypted = (known after apply)
+ iops = (known after apply)
+ kms_key_id = (known after apply)
+ tags = (known after apply)
+ throughput = (known after apply)
+ volume_id = (known after apply)
+ volume_size = (known after apply)
+ volume_type = (known after apply)
}
}
Plan: 1 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.
terraform applyの実行
terraform apply
を実行すると、コードの内容が実行されて、各プロバイダ環境(今回はAWS
)に各種リソースが作成されます。
また、途中でリソース作成確認があり、入力を求められるため、「yes」と入力して実行します。
自動化等を行っており、「yes」の入力を省きたい場合は-auto-approve
オプションを追加して実行すると、入力を省くことができます。
terraform applyの実行結果(展開してください)
$ 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_instance.testtf will be created
+ resource "aws_instance" "testtf" {
+ ami = "ami-0b7546e839d7ace12"
+ arn = (known after apply)
+ associate_public_ip_address = (known after apply)
+ availability_zone = (known after apply)
+ cpu_core_count = (known after apply)
+ cpu_threads_per_core = (known after apply)
+ disable_api_stop = (known after apply)
+ disable_api_termination = (known after apply)
+ ebs_optimized = (known after apply)
+ get_password_data = false
+ host_id = (known after apply)
+ id = (known after apply)
+ instance_initiated_shutdown_behavior = (known after apply)
+ instance_state = (known after apply)
+ instance_type = "t3.micro"
+ ipv6_address_count = (known after apply)
+ ipv6_addresses = (known after apply)
+ key_name = (known after apply)
+ monitoring = (known after apply)
+ outpost_arn = (known after apply)
+ password_data = (known after apply)
+ placement_group = (known after apply)
+ placement_partition_number = (known after apply)
+ primary_network_interface_id = (known after apply)
+ private_dns = (known after apply)
+ private_ip = (known after apply)
+ public_dns = (known after apply)
+ public_ip = (known after apply)
+ secondary_private_ips = (known after apply)
+ security_groups = (known after apply)
+ source_dest_check = true
+ subnet_id = (known after apply)
+ tags_all = (known after apply)
+ tenancy = (known after apply)
+ user_data = (known after apply)
+ user_data_base64 = (known after apply)
+ user_data_replace_on_change = false
+ vpc_security_group_ids = (known after apply)
+ capacity_reservation_specification {
+ capacity_reservation_preference = (known after apply)
+ capacity_reservation_target {
+ capacity_reservation_id = (known after apply)
+ capacity_reservation_resource_group_arn = (known after apply)
}
}
+ ebs_block_device {
+ delete_on_termination = (known after apply)
+ device_name = (known after apply)
+ encrypted = (known after apply)
+ iops = (known after apply)
+ kms_key_id = (known after apply)
+ snapshot_id = (known after apply)
+ tags = (known after apply)
+ throughput = (known after apply)
+ volume_id = (known after apply)
+ volume_size = (known after apply)
+ volume_type = (known after apply)
}
+ enclave_options {
+ enabled = (known after apply)
}
+ ephemeral_block_device {
+ device_name = (known after apply)
+ no_device = (known after apply)
+ virtual_name = (known after apply)
}
+ maintenance_options {
+ auto_recovery = (known after apply)
}
+ metadata_options {
+ http_endpoint = (known after apply)
+ http_put_response_hop_limit = (known after apply)
+ http_tokens = (known after apply)
+ instance_metadata_tags = (known after apply)
}
+ network_interface {
+ delete_on_termination = (known after apply)
+ device_index = (known after apply)
+ network_card_index = (known after apply)
+ network_interface_id = (known after apply)
}
+ private_dns_name_options {
+ enable_resource_name_dns_a_record = (known after apply)
+ enable_resource_name_dns_aaaa_record = (known after apply)
+ hostname_type = (known after apply)
}
+ root_block_device {
+
+ delete_on_termination = (known after apply)
+ device_name = (known after apply)
+ encrypted = (known after apply)
+ iops = (known after apply)
+ kms_key_id = (known after apply)
+ tags = (known after apply)
+ throughput = (known after apply)
+ volume_id = (known after apply)
+ volume_size = (known after apply)
+ volume_type = (known after apply)
}
}
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_instance.testtf: Creating...
aws_instance.testtf: Still creating... [10s elapsed]
aws_instance.testtf: Creation complete after 13s [id=i-058f9caf6b5fabfd0]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
また、terraform apply
実行後、カレントディレクトリにterraform.tfstate
というファイルが作成されます。
terraform.tfstate
ファイルはterraform apply
実行時の各プロバイダ(今回はAWS
)環境の状態を記録しているファイルとなり、次回terraform apply
実行時には、terraform.tfstate
ファイルに記載されている環境情報と比較し、差分のみを追加&削除等を行う動作となります。
terraform.tfstateファイルの表示例(展開してください)
{
"version": 4,
"terraform_version": "1.2.3",
"serial": 1,
"lineage": "f0456b47-464f-3c3f-e246-4aeea30425b8",
"outputs": {},
"resources": [
{
"mode": "managed",
"type": "aws_instance",
"name": "testtf",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
{
"schema_version": 1,
"attributes": {
"ami": "ami-0b7546e839d7ace12",
"arn": "arn:aws:ec2:ap-northeast-1:335417439444:instance/i-058f9caf6b5fabfd0",
"associate_public_ip_address": true,
"availability_zone": "ap-northeast-1d",
"capacity_reservation_specification": [
{
"capacity_reservation_preference": "open",
"capacity_reservation_target": []
}
],
"cpu_core_count": 1,
"cpu_threads_per_core": 2,
"credit_specification": [
{
"cpu_credits": "unlimited"
}
],
"disable_api_stop": false,
"disable_api_termination": false,
"ebs_block_device": [],
"ebs_optimized": false,
"enclave_options": [
{
"enabled": false
}
],
"ephemeral_block_device": [],
"get_password_data": false,
"hibernation": false,
"host_id": null,
"iam_instance_profile": "",
"id": "i-058f9caf6b5fabfd0",
"instance_initiated_shutdown_behavior": "stop",
"instance_state": "running",
"instance_type": "t3.micro",
"ipv6_address_count": 0,
"ipv6_addresses": [],
"key_name": "",
"launch_template": [],
"maintenance_options": [
{
"auto_recovery": "default"
}
],
"metadata_options": [
{
"http_endpoint": "enabled",
"http_put_response_hop_limit": 1,
"http_tokens": "optional",
"instance_metadata_tags": "disabled"
}
],
"monitoring": false,
"network_interface": [],
"outpost_arn": "",
"password_data": "",
"placement_group": "",
"placement_partition_number": null,
"primary_network_interface_id": "eni-00a399526fcba5d63",
"private_dns": "ip-172-31-21-72.ap-northeast-1.compute.internal",
"private_dns_name_options": [
{
"enable_resource_name_dns_a_record": false,
"enable_resource_name_dns_aaaa_record": false,
"hostname_type": "ip-name"
}
],
"private_ip": "172.31.21.72",
"public_dns": "ec2-35-78-254-110.ap-northeast-1.compute.amazonaws.com",
"public_ip": "35.78.254.110",
"root_block_device": [
{
"delete_on_termination": true,
"device_name": "/dev/xvda",
"encrypted": false,
"iops": 100,
"kms_key_id": "",
"tags": {},
"throughput": 0,
"volume_id": "vol-0eb3884c49cb32c24",
"volume_size": 8,
"volume_type": "gp2"
}
],
"secondary_private_ips": [],
"security_groups": [
"default"
],
"source_dest_check": true,
"subnet_id": "subnet-c50cc9ee",
"tags": null,
"tags_all": {},
"tenancy": "default",
"timeouts": null,
"user_data": null,
"user_data_base64": null,
"user_data_replace_on_change": false,
"volume_tags": null,
"vpc_security_group_ids": [
"sg-70df8a0e"
]
},
"sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo2MDAwMDAwMDAwMDAsImRlbGV0ZSI6MTIwMDAwMDAwMDAwMCwidXBkYXRlIjo2MDAwMDAwMDAwMDB9LCJzY2hlbWFfdmVyc2lvbiI6IjEifQ=="
}
]
}
]
}
尚、デフォルトではローカルのカレントディレクトリに作成されますが、複数人で開発したり、複数端末で開発するような場合、それぞれのユーザのローカルで別々に管理されてしまうと、実行するユーザによって挙動が変わってきてしまうため、その場合はローカルではなく、リモートのストレージで管理する必要があります。
リソース削除方法
作成したリソースをまとめて削除したい場合、terraform destroy
コマンドを実行することで、環境をすべて削除することができます。
削除時にもリソース削除確認があり、入力が求められるため、「yes」と入力して実行します。
terraform destroy
実行時にも-auto-approve
オプションを使用できるため、入力を省きたい場合はオプションを追加して実行します。
terraform destroyの実行結果(展開してください)
$ terraform destroy
aws_instance.testtf: Refreshing state... [id=i-058f9caf6b5fabfd0]
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_instance.testtf will be destroyed
- resource "aws_instance" "testtf" {
- ami = "ami-0b7546e839d7ace12" -> null
- arn = "arn:aws:ec2:ap-northeast-1:335417439444:instance/i-058f9caf6b5fabfd0" -> null
- associate_public_ip_address = true -> null
- availability_zone = "ap-northeast-1d" -> null
- cpu_core_count = 1 -> null
- cpu_threads_per_core = 2 -> null
- disable_api_stop = false -> null
- disable_api_termination = false -> null
- ebs_optimized = false -> null
- get_password_data = false -> null
- hibernation = false -> null
- id = "i-058f9caf6b5fabfd0" -> null
- instance_initiated_shutdown_behavior = "stop" -> null
- instance_state = "running" -> null
- instance_type = "t3.micro" -> null
- ipv6_address_count = 0 -> null
- ipv6_addresses = [] -> null
- monitoring = false -> null
- primary_network_interface_id = "eni-00a399526fcba5d63" -> null
- private_dns = "ip-172-31-21-72.ap-northeast-1.compute.internal" -> null
- private_ip = "172.31.21.72" -> null
- public_dns = "ec2-35-78-254-110.ap-northeast-1.compute.amazonaws.com" -> null
- public_ip = "35.78.254.110" -> null
- secondary_private_ips = [] -> null
- security_groups = [
- "default",
] -> null
- source_dest_check = true -> null
- subnet_id = "subnet-c50cc9ee" -> null
- tags = {} -> null
- tags_all = {} -> null
- tenancy = "default" -> null
- user_data_replace_on_change = false -> null
- vpc_security_group_ids = [
- "sg-70df8a0e",
] -> null
- capacity_reservation_specification {
- capacity_reservation_preference = "open" -> null
}
- credit_specification {
- cpu_credits = "unlimited" -> null
}
- enclave_options {
- enabled = false -> null
}
- maintenance_options {
- auto_recovery = "default" -> null
}
- metadata_options {
- http_endpoint = "enabled" -> null
- http_put_response_hop_limit = 1 -> null
- http_tokens = "optional" -> null
- instance_metadata_tags = "disabled" -> null
}
- private_dns_name_options {
- enable_resource_name_dns_a_record = false -> null
- enable_resource_name_dns_aaaa_record = false -> null
- hostname_type = "ip-name" -> null
}
- root_block_device {
- delete_on_termination = true -> null
- device_name = "/dev/xvda" -> null
- encrypted = false -> null
- iops = 100 -> null
- tags = {} -> null
- throughput = 0 -> null
- volume_id = "vol-0eb3884c49cb32c24" -> null
- volume_size = 8 -> null
- volume_type = "gp2" -> 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_instance.testtf: Destroying... [id=i-058f9caf6b5fabfd0]
aws_instance.testtf: Still destroying... [id=i-058f9caf6b5fabfd0, 10s elapsed]
aws_instance.testtf: Still destroying... [id=i-058f9caf6b5fabfd0, 20s elapsed]
aws_instance.testtf: Still destroying... [id=i-058f9caf6b5fabfd0, 30s elapsed]
aws_instance.testtf: Still destroying... [id=i-058f9caf6b5fabfd0, 40s elapsed]
aws_instance.testtf: Still destroying... [id=i-058f9caf6b5fabfd0, 50s elapsed]
aws_instance.testtf: Destruction complete after 50s
Destroy complete! Resources: 1 destroyed.
おわりに
今回はTerraform
で構築した際の流れを覚えるため、各種基本操作を実行してみました。
次回はTerraform
でコーディングする際の基本構文と、構文等調べる際に参照する各種ドキュメントについて学んでいきます。