Terraform Workflow¶
Terraform的完整工作流程如圖所示,用戶編寫了 HCL 語法的IaC腳本,在Init與腳本語法驗證除錯後,經歷了Plan和Apply兩個階段後,最後透過配置的 Provider(比如AWS、GCP、Azure、Alibaba等雲端平台)去佈建後面的運算、儲存或網路資源,以建構所需的基礎建設,以下針對每一個工作階段做更細緻的說明。
下述操作須包含先決條件:
- 已安裝 terraform
- 已安裝 awc cli
- 已設定 aws configure 並擁有創建aws相關資源的使用者權限
Init¶
Terraform是由Go語言編寫而成,在IaC所要控制管理的每一個Provider都是個別獨立的Go插件,因此在一個Terraform腳本要運行之前,需要先確認Provider所需要下載安裝的套件,這便是Init初始化的工作內容,比如我們可以在一個即將要運行AWS相關部署的Terrafrom工作目錄裡看到經歷過init的後果,即是於隱藏目錄 .terraform
裡下載了所需的 terraform-provider-aws_v5.31.0_x5
Go插件,這裡需要注意的是,在init前需要先給予Terraform一個副檔名為 *.rt
的IaC定義檔(本例為 terraform-provider.tf
)、並在裡面優先定義provider的內容。
[test@host terraform]$ cat terraform-provider.tf
provider "aws" {
region = "ap-northeast-1"
}
[test@host terraform]$ terraform init
[test@host terraform]$ tree -a
.
├── terraform-provider.tf
├── .terraform
│ └── providers
│ └── registry.terraform.io
│ └── hashicorp
│ └── aws
│ └── 5.31.0
│ └── linux_amd64
│ └── terraform-provider-aws_v5.31.0_x5
Validate¶
Terrafrom的腳本是採用HCL語法編寫,而這個階段是在IaC腳本運行前的語法檢查,不一定要進行,因為如果語法寫錯,那麼在下一個步驟「Plan」時也會報錯。
[test@host terraform]$ terraform validate
Success! The configuration is valid.
Plan¶
在這個工作階段,Plan會將腳本裡所需要建構或移除的資源一一條列出來給用戶檢查確認,可以說是在部署前的最後一次檢查,同時如果有語法或參數錯誤的情況下,也會在這個階段報錯通知,本例我們加入一個 ec2.tf
定義檔案,目的是添加一個ec2的運算資源。
[test@host terraform]$ cat ec2.tf
resource "aws_instance" "example-ec2" {
ami = "ami-0dfa284c9d7b2adad"
instance_type = "t3.small"
}
[test@host terraform]$ 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.example-ec2 will be created
+ resource "aws_instance" "example-ec2" {
+ ami = "ami-0dfa284c9d7b2adad"
+ 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)
+ host_resource_group_arn = (known after apply)
+ iam_instance_profile = (known after apply)
+ id = (known after apply)
+ instance_initiated_shutdown_behavior = (known after apply)
+ instance_lifecycle = (known after apply)
+ instance_state = (known after apply)
+ instance_type = "t3.small"
+ 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
+ spot_instance_request_id = (known after apply)
+ 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)
}
Plan: 1 to add, 0 to change, 0 to destroy.
Apply¶
在確認了Plan的內容無誤後,就可以執行Apply,讓Terraform去實踐IaC腳本中新增、修改或移除基礎建設的需求。
[test@host terraform]$ terraform 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.example-ec2: Creating...
aws_instance.example-ec2: Still creating... [10s elapsed]
aws_instance.example-ec2: Creation complete after 13s [id=i-0f844375630e9eef3]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
回到AWS上可以看到已自動新增了一台ec2,其中的執行個體ID i-0f844375630e9eef3
與上面Terraform所建立的Instance id相同一致。
Destroy¶
要刪除先前IaC腳本所建立的基礎建設也很簡單,透過Destroy一鍵移除。
[test@host terraform]$ terraform destroy
aws_instance.example-ec2: Refreshing state... [id=i-0f844375630e9eef3]
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.example-ec2 will be destroyed
- resource "aws_instance" "example-ec2" {
- ami = "ami-0dfa284c9d7b2adad" -> null
- arn = "arn:aws:ec2:ap-northeast-1:390932880188:instance/i-0f844375630e9eef3" -> null
- associate_public_ip_address = true -> null
- availability_zone = "ap-northeast-1a" -> 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-0f844375630e9eef3" -> null
- instance_initiated_shutdown_behavior = "stop" -> null
- instance_state = "running" -> null
- instance_type = "t3.small" -> null
- ipv6_address_count = 0 -> null
- ipv6_addresses = [] -> null
- monitoring = false -> null
- placement_partition_number = 0 -> null
- primary_network_interface_id = "eni-051ef3ee0fb94522c" -> null
- private_dns = "ip-172-31-36-74.ap-northeast-1.compute.internal" -> null
- private_ip = "172.31.36.74" -> null
- public_dns = "ec2-13-115-209-208.ap-northeast-1.compute.amazonaws.com" -> null
- public_ip = "13.115.209.208" -> null
- secondary_private_ips = [] -> null
- security_groups = [
- "default",
] -> null
- source_dest_check = true -> null
- subnet_id = "subnet-ed39c9a5" -> null
- tags = {} -> null
- tags_all = {} -> null
- tenancy = "default" -> null
- user_data_replace_on_change = false -> null
- vpc_security_group_ids = [
- "sg-3129544f",
] -> null
- capacity_reservation_specification {
- capacity_reservation_preference = "open" -> null
}
- cpu_options {
- core_count = 1 -> null
- threads_per_core = 2 -> 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_protocol_ipv6 = "disabled" -> null
- http_put_response_hop_limit = 2 -> null
- http_tokens = "required" -> 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 = 3000 -> null
- tags = {} -> null
- throughput = 125 -> null
- volume_id = "vol-03a3e4009df570167" -> null
- volume_size = 8 -> null
- volume_type = "gp3" -> 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.example-ec2: Destroying... [id=i-0f844375630e9eef3]
aws_instance.example-ec2: Still destroying... [id=i-0f844375630e9eef3, 10s elapsed]
aws_instance.example-ec2: Still destroying... [id=i-0f844375630e9eef3, 20s elapsed]
aws_instance.example-ec2: Still destroying... [id=i-0f844375630e9eef3, 30s elapsed]
aws_instance.example-ec2: Destruction complete after 40s
Destroy complete! Resources: 1 destroyed.
回到頁首