專案

一般

配置概況

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.

回到頁首