利用Terraform学习(第三章:执行Terraform)
首先
由于Terraform的开发环境已经准备就绪,我打算从这次开始尝试使用Terraform来进行AWS的构建工作。
- 【前】Terraformを使って覚える。(その2:git-secretsとVS Codeのインストール)
执行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"
}
您可以在以下的在线文档中查阅各种可在不同资源中指定的设置和选项。
- AWS Provider
在这种情况下,Terraform会隐式地判断为执行AWS操作,使用已设置的AWS CLI默认凭证信息进行连接。因此,即使没有提供provider块,它仍然可以正常工作。为了避免意外行为,我们应明确地进行说明。
执行terraform init(仅初次执行)
通过运行terraform init命令,在当前目录下创建了.terraform.locl.hcl文件和.terraform文件夹,并且下载了各种提供者资源创建所需的二进制文件到该文件夹中。
.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 plan
Terraform使用所选的提供程序生成以下执行计划。资源操作使用以下符号表示:
+ 创建
Terraform将执行以下操作:
# aws_instance.testtf 将被创建
+ resource “aws_instance” “testtf” {
+ ami = “ami-0b7546e839d7ace12”
+ arn = (在应用后确定)
+ associate_public_ip_address = (在应用后确定)
+ availability_zone = (在应用后确定)
+ cpu_core_count = (在应用后确定)
+ cpu_threads_per_core = (在应用后确定)
+ disable_api_stop = (在应用后确定)
+ disable_api_termination = (在应用后确定)
+ ebs_optimized = (在应用后确定)
+ get_password_data = false
+ host_id = (在应用后确定)
+ id = (在应用后确定)
+ instance_initiated_shutdown_behavior = (在应用后确定)
+ instance_state = (在应用后确定)
+ instance_type = “t3.micro”
+ ipv6_address_count = (在应用后确定)
+ ipv6_addresses = (在应用后确定)
+ key_name = (在应用后确定)
+ monitoring = (在应用后确定)
+ outpost_arn = (在应用后确定)
+ password_data = (在应用后确定)
+ placement_group = (在应用后确定)
+ placement_partition_number = (在应用后确定)
+ primary_network_interface_id = (在应用后确定)
+ private_dns = (在应用后确定)
+ private_ip = (在应用后确定)
+ public_dns = (在应用后确定)
+ public_ip = (在应用后确定)
+ secondary_private_ips = (在应用后确定)
+ security_groups = (在应用后确定)
+ source_dest_check = true
+ subnet_id = (在应用后确定)
+ tags_all = (在应用后确定)
+ tenancy = (在应用后确定)
+ user_data = (在应用后确定)
+ user_data_base64 = (在应用后确定)
+ user_data_replace_on_change = false
+ vpc_security_group_ids = (在应用后确定)
+ capacity_reservation_specification {
+ capacity_reservation_preference = (在应用后确定)
+ capacity_reservation_target {
+ capacity_reservation_id = (在应用后确定)
+ capacity_reservation_resource_group_arn = (在应用后确定)
}
}
+ ebs_block_device {
+ delete_on_termination = (在应用后确定)
+ device_name = (在应用后确定)
+ encrypted = (在应用后确定)
+ iops = (在应用后确定)
+ kms_key_id = (在应用后确定)
+ snapshot_id = (在应用后确定)
+ tags = (在应用后确定)
+ throughput = (在应用后确定)
+ volume_id = (在应用后确定)
+ volume_size = (在应用后确定)
+ volume_type = (在应用后确定)
}
+ enclave_options {
+ enabled = (在应用后确定)
}
+ ephemeral_block_device {
+ device_name = (在应用后确定)
+ no_device = (在应用后确定)
+ virtual_name = (在应用后确定)
}
+ maintenance_options {
+ auto_recovery = (在应用后确定)
}
+ metadata_options {
+ http_endpoint = (在应用后确定)
+ http_put_response_hop_limit = (在应用后确定)
+ http_tokens = (在应用后确定)
+ instance_metadata_tags = (在应用后确定)
}
+ network_interface {
+ delete_on_termination = (在应用后确定)
+ device_index = (在应用后确定)
+ network_card_index = (在应用后确定)
+ network_interface_id = (在应用后确定)
}
+ private_dns_name_options {
+ enable_resource_name_dns_a_record = (在应用后确定)
+ enable_resource_name_dns_aaaa_record = (在应用后确定)
+ hostname_type = (在应用后确定)
}
+ root_block_device {
+ delete_on_termination = (在应用后确定)
+ device_name = (在应用后确定)
+ encrypted = (在应用后确定)
+ iops = (在应用后确定)
+ kms_key_id = (在应用后确定)
+ tags = (在应用后确定)
+ throughput = (在应用后确定)
+ volume_id = (在应用后确定)
+ volume_size = (在应用后确定)
+ volume_type = (在应用后确定)
}
}
计划:添加1个,更改0个,销毁0个。
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
注意:您没有使用 -out 选项保存此计划,因此如果您现在运行 “terraform apply”,Terraform无法保证完全按照此计划执行操作。
执行terraform apply
执行terraform apply时,会执行代码并在每个提供商环境(本例为AWS)中创建各种资源。
此外,在过程中会有资源创建确认,并且需要输入,因此输入“是”然后执行。
如果要进行自动化等操作,并且想要省略对”yes”的输入,只需在执行时添加-auto-approve选项即可省略输入。
$ terraform apply
Terraform使用所选提供程序生成以下执行计划。资源操作用以下符号表示:
+ 创建
Terraform将执行以下操作:
# 将创建aws_instance.testtf
+ resource “aws_instance” “testtf” {
+ ami = “ami-0b7546e839d7ace12”
+ arn = (申请后已知)
+ associate_public_ip_address = (申请后已知)
+ availability_zone = (申请后已知)
+ cpu_core_count = (申请后已知)
+ cpu_threads_per_core = (申请后已知)
+ disable_api_stop = (申请后已知)
+ disable_api_termination = (申请后已知)
+ ebs_optimized = (申请后已知)
+ get_password_data = false
+ host_id = (申请后已知)
+ id = (申请后已知)
+ instance_initiated_shutdown_behavior = (申请后已知)
+ instance_state = (申请后已知)
+ instance_type = “t3.micro”
+ ipv6_address_count = (申请后已知)
+ ipv6_addresses = (申请后已知)
+ key_name = (申请后已知)
+ monitoring = (申请后已知)
+ outpost_arn = (申请后已知)
+ password_data = (申请后已知)
+ placement_group = (申请后已知)
+ placement_partition_number = (申请后已知)
+ primary_network_interface_id = (申请后已知)
+ private_dns = (申请后已知)
+ private_ip = (申请后已知)
+ public_dns = (申请后已知)
+ public_ip = (申请后已知)
+ secondary_private_ips = (申请后已知)
+ security_groups = (申请后已知)
+ source_dest_check = true
+ subnet_id = (申请后已知)
+ tags_all = (申请后已知)
+ tenancy = (申请后已知)
+ user_data = (申请后已知)
+ user_data_base64 = (申请后已知)
+ user_data_replace_on_change = false
+ vpc_security_group_ids = (申请后已知)
+ capacity_reservation_specification {
+ capacity_reservation_preference = (申请后已知)
+ capacity_reservation_target {
+ capacity_reservation_id = (申请后已知)
+ capacity_reservation_resource_group_arn = (申请后已知)
}
}
+ ebs_block_device {
+ delete_on_termination = (申请后已知)
+ device_name = (申请后已知)
+ encrypted = (申请后已知)
+ iops = (申请后已知)
+ kms_key_id = (申请后已知)
+ snapshot_id = (申请后已知)
+ tags = (申请后已知)
+ throughput = (申请后已知)
+ volume_id = (申请后已知)
+ volume_size = (申请后已知)
+ volume_type = (申请后已知)
}
+ enclave_options {
+ enabled = (申请后已知)
}
+ ephemeral_block_device {
+ device_name = (申请后已知)
+ no_device = (申请后已知)
+ virtual_name = (申请后已知)
}
+ maintenance_options {
+ auto_recovery = (申请后已知)
}
+ metadata_options {
+ http_endpoint = (申请后已知)
+ http_put_response_hop_limit = (申请后已知)
+ http_tokens = (申请后已知)
+ instance_metadata_tags = (申请后已知)
}
+ network_interface {
+ delete_on_termination = (申请后已知)
+ device_index = (申请后已知)
+ network_card_index = (申请后已知)
+ network_interface_id = (申请后已知)
}
+ private_dns_name_options {
+ enable_resource_name_dns_a_record = (申请后已知)
+ enable_resource_name_dns_aaaa_record = (申请后已知)
+ hostname_type = (申请后已知)
}
+ root_block_device {
+
+ delete_on_termination = (申请后已知)
+ device_name = (申请后已知)
+ encrypted = (申请后已知)
+ iops = (申请后已知)
+ kms_key_id = (申请后已知)
+ tags = (申请后已知)
+ throughput = (申请后已知)
+ volume_id = (申请后已知)
+ volume_size = (申请后已知)
+ volume_type = (申请后已知)
}
}
计划:添加1个,更改0个,删除0个。
您要执行这些操作吗?
Terraform将执行上述操作。
只接受“是”以批准。
请输入一个值:是
aws_instance.testtf:创建中…
aws_instance.testtf:仍在创建中…[已过去10秒]
aws_instance.testtf:创建完成,耗时13秒[id=i-058f9caf6b5fabfd0]
应用完成!资源:新增1个,更改0个,删除0个。
对应于中国的互联网,terraform apply执行后,将在当前目录下创建一个名为terraform.tfstate的文件。
terraform.tfstate文件记录了在terraform apply执行时的每个提供程序(本例中为AWS)环境的状态,并且在下一次terraform apply执行时,会将其与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
aws_instance.testtf: 刷新状态… [id=i-058f9caf6b5fabfd0]
Terraform使用所选的提供程序生成以下执行计划。资源操作用以下符号表示:
– 销毁
Terraform将执行以下操作:
# aws_instance.testtf将被销毁
– 资源 “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
}
}
计划: 添加0个,更改0个,销毁1个。
您真的要销毁所有资源吗?
Terraform将销毁所有您管理的基础架构,如上所示。
没有撤销。只接受“yes”以确认。
输入一个值: yes
aws_instance.testtf: 正在销毁… [id=i-058f9caf6b5fabfd0]
aws_instance.testtf: 仍在销毁… [id=i-058f9caf6b5fabfd0,已过去10秒]
aws_instance.testtf: 仍在销毁… [id=i-058f9caf6b5fabfd0,已过去20秒]
aws_instance.testtf: 仍在销毁… [id=i-058f9caf6b5fabfd0,已过去30秒]
aws_instance.testtf: 仍在销毁… [id=i-058f9caf6b5fabfd0,已过去40秒]
aws_instance.testtf: 仍在销毁… [id=i-058f9caf6b5fabfd0,已过去50秒]
aws_instance.testtf: 50秒后销毁完成
销毁完成!资源:1个已销毁。
最后
为了记住使用Terraform进行构建的流程,本次尝试执行了各种基本操作。
我们将学习使用Terraform编写代码时的基本语法以及各种文档用于查询语法等相关内容。