iT邦幫忙

2023 iThome 鐵人賽

DAY 4
0
DevOps

大家都在用 Terraform 實作 IaC 為什麼不將程式寫得更簡潔易讀呢?系列 第 4

如何利用 HCL 語言的撰寫 Terraform 專案的基本介紹 (Part IV) - 套用 HCL 代碼

  • 分享至 

  • xImage
  •  
  1. 更新 Terraform 的提供者 (providers) 到最新版本:
  • 由於的最新版本的提供者包括安全更新,用於修復已知的漏洞或問題,來確保減少潛在的安全風險。
  • 另外,Terraform 的新版本可能需要新的提供者版本,以確保兼容性。

請執行下面的指令terraform init --upgrade,並會得到以下的輸出結果:


Initializing the backend...
Initializing modules...
- my_ec2_instances in modules/ec2_instances

Initializing provider plugins...
- Finding hashicorp/aws versions matching "5.15.0"...
- Installing hashicorp/aws v5.15.0...
- Installed hashicorp/aws v5.15.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!

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.
  1. 生成 Terraform 執行計劃,並將計劃保存到指定的文件(在這個例子中是 .plan)。
  • 生成計劃: terraform plan 命令會分析你的 Terraform 配置文件並計算出在應用變更之前和之後的狀態差異,它會列出將要新增、修改和刪除的資源,以及任何相關的變更。
  • 預覽變更: 使用 terraform plan 可以預覽 Terraform 將對基礎設施進行的變更,這有助於你在應用實際變更之前查看可能的影響和問題。
  • 保存計劃: 使用 --out 選項,你可以將計劃保存到一個二進制文件中,你可以在確定計劃是符合預期的後,再執行應用變更的步驟,而不需要重新計算計劃。這對於在多個環境中套用相同的計劃非常有用。

請執行下面的指令terraform plan --out .plan,並會得到以下的輸出結果:

$ terraform plan --out .plan
module.my_ec2_instances.data.aws_ami.selected_ami: Reading...
module.my_ec2_instances.data.aws_ami.selected_ami: Read complete after 1s [id=ami-0f419d2f905bb344e]

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:

  # module.my_ec2_instances.aws_instance.example[0] will be created
  + resource "aws_instance" "example" {
      + ami                                  = "ami-0f419d2f905bb344e"
      + 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                        = "t3a.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
      + spot_instance_request_id             = (known after apply)
      + subnet_id                            = (known after apply)
      + tags                                 = {
          + "Environment" = "Production"
          + "Name"        = "ec2-instance-0"
        }
      + tags_all                             = {
          + "Environment" = "Production"
          + "Name"        = "ec2-instance-0"
        }
      + 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)
    }

  # module.my_ec2_instances.aws_instance.example[1] will be created
  + resource "aws_instance" "example" {
      + ami                                  = "ami-0f419d2f905bb344e"
      + 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                        = "t3a.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
      + spot_instance_request_id             = (known after apply)
      + subnet_id                            = (known after apply)
      + tags                                 = {
          + "Environment" = "Production"
          + "Name"        = "ec2-instance-1"
        }
      + tags_all                             = {
          + "Environment" = "Production"
          + "Name"        = "ec2-instance-1"
        }
      + 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: 2 to add, 0 to change, 0 to destroy.

───────────────────────────────────────────────────────────────────────

Saved the plan to: .plan

To perform exactly these actions, run the following command to apply:
    terraform apply ".plan"
  1. 套用前一部建立的 Terraform 執行計劃,其說明如下:
  • 套用計劃: terraform apply 命令使用之前生成的計劃文件 .plan 來套用對基礎設施的變更。
  • 確保一致性: 使用計劃文件,你可以確保在應用變更之前,你看到的計劃是符合預期的,這有助於避免意外的變更,確保計劃的一致性。
  • 避免重複套用: 由於計劃文件已經包含了計算出的變更,因此使用 terraform apply .plan 可以避免重新計算計劃,從而節省時間和資源。
  • 多環境佈署: 如果你的基礎設施佈署涉及多個階段(例如,開發、測試、生產),你可以在不同的環境中使用相同的計劃文件,確保在每個環境中套用相同的變更。

請執行下面的指令 terraform apply ".plan",並會得到以下的輸出結果:

module.my_ec2_instances.aws_instance.example[1]: Creating...
module.my_ec2_instances.aws_instance.example[0]: Creating...
module.my_ec2_instances.aws_instance.example[1]: Still creating... [10s elapsed]
module.my_ec2_instances.aws_instance.example[0]: Still creating... [10s elapsed]
module.my_ec2_instances.aws_instance.example[0]: Creation complete after 13s [id=i-083c2d59bb1871ef7]
module.my_ec2_instances.aws_instance.example[1]: Creation complete after 14s [id=i-0436f01af4aa76c7a]

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
  1. 列出 Terraform 管理的當前基礎設施狀態(state)中的所有資源,其說明如下:
  • 查看當前狀態:通過運行 terraform state list,你可以輕鬆查看 Terraform 記錄的當前基礎設施狀態,這可以幫助你確認哪些資源已經被 Terraform 記錄,以及它們的名稱和類型。
  • 定位資源: 在大型基礎設施中,可能會有很多資源,如果用手動查找特定資源變得困難,透過 terraform state list 可以讓你快速定位和識別特定資源的名稱,以便進一步操作。
  • 檢查狀態一致性: 如果你對 Terraform 管理的基礎設施進行了手動更改或者有其他方式導致狀態不一致,terraform state list 可以幫助你檢查哪些資源與 Terraform 狀態不一致,以便進一步修復。
  • 自動化操作:通過結合其他 Terraform 狀態命令,如 terraform state rmterraform state mv,你可以自動化地對基礎設施狀態進行操作,從而更輕鬆地管理配置。

請執行下面的指令 terraform state list,並會得到以下的輸出結果:

module.my_ec2_instances.aws_instance.example[0]
module.my_ec2_instances.aws_instance.example[1]
  1. 從基礎設施中刪除 Terraform 管理的所有資源,即撤銷已經建立的基礎設施,其說明如下:
  • 資源清理: terraform destroy 用於確保你不再需要的基礎設施資源被完全清理,以避免不必要的成本和資源浪費,這尤其對於暫時性的環境,如測試環境或開發環境,非常有幫助。
  • 避免資源雜亂: 在開發過程中,可能會需要多次新建和刪除資源,可能會在你的 AWS 帳戶中留下許多無用的資源,透過 terraform destroy 可以幫助你保持資源的整潔,減少不必要的混亂。
  • 重建測試: 在開發過程中,terraform destroy 允許你輕鬆地將資源還原到初始狀態,以便進行重新建立和測試。
  • 安全性: 如果你確保在不再需要基礎設施資源時銷毀它們,可以減少安全風險,不需要的資源可能成為潛在的攻擊目標。

請執行下面的指令 terraform destroy,並會得到以下的輸出會有提示問題確認是否銷毀,這時輸入yes就會開始銷毀程序:

module.my_ec2_instances.data.aws_ami.selected_ami: Reading...
module.my_ec2_instances.data.aws_ami.selected_ami: Read complete after 0s [id=ami-0f419d2f905bb344e]
module.my_ec2_instances.aws_instance.example[1]: Refreshing state... [id=i-0436f01af4aa76c7a]
module.my_ec2_instances.aws_instance.example[0]: Refreshing state... [id=i-083c2d59bb1871ef7]

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:

  # module.my_ec2_instances.aws_instance.example[0] will be destroyed
  - resource "aws_instance" "example" {
      - ami                                  = "ami-0f419d2f905bb344e" -> null
      - arn                                  = "arn:aws:ec2:ap-northeast-1:597635706810:instance/i-083c2d59bb1871ef7" -> 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-083c2d59bb1871ef7" -> null
      - instance_initiated_shutdown_behavior = "stop" -> null
      - instance_state                       = "running" -> null
      - instance_type                        = "t3a.micro" -> null
      - ipv6_address_count                   = 0 -> null
      - ipv6_addresses                       = [] -> null
      - monitoring                           = false -> null
      - placement_partition_number           = 0 -> null
      - primary_network_interface_id         = "eni-0e0d9db2b2fa7bf16" -> null
      - private_dns                          = "ip-172-31-18-98.ap-northeast-1.compute.internal" -> null
      - private_ip                           = "172.31.18.98" -> null
      - public_dns                           = "ec2-18-180-158-245.ap-northeast-1.compute.amazonaws.com" -> null
      - public_ip                            = "18.180.158.245" -> null
      - secondary_private_ips                = [] -> null
      - security_groups                      = [
          - "default",
        ] -> null
      - source_dest_check                    = true -> null
      - subnet_id                            = "subnet-c9e366e2" -> null
      - tags                                 = {
          - "Environment" = "Dev"
          - "Name"        = "ec2-instance-0"
        } -> null
      - tags_all                             = {
          - "Environment" = "Dev"
          - "Name"        = "ec2-instance-0"
        } -> null
      - tenancy                              = "default" -> null
      - user_data_replace_on_change          = false -> null
      - vpc_security_group_ids               = [
          - "sg-92a2c4d1",
        ] -> 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 = 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                  = 0 -> null
          - tags                  = {} -> null
          - throughput            = 0 -> null
          - volume_id             = "vol-0ef9454ca594e5df6" -> null
          - volume_size           = 8 -> null
          - volume_type           = "standard" -> null
        }
    }

  # module.my_ec2_instances.aws_instance.example[1] will be destroyed
  - resource "aws_instance" "example" {
      - ami                                  = "ami-0f419d2f905bb344e" -> null
      - arn                                  = "arn:aws:ec2:ap-northeast-1:597635706810:instance/i-0436f01af4aa76c7a" -> 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-0436f01af4aa76c7a" -> null
      - instance_initiated_shutdown_behavior = "stop" -> null
      - instance_state                       = "running" -> null
      - instance_type                        = "t3a.micro" -> null
      - ipv6_address_count                   = 0 -> null
      - ipv6_addresses                       = [] -> null
      - monitoring                           = false -> null
      - placement_partition_number           = 0 -> null
      - primary_network_interface_id         = "eni-09b7262af40684e4d" -> null
      - private_dns                          = "ip-172-31-31-213.ap-northeast-1.compute.internal" -> null
      - private_ip                           = "172.31.31.213" -> null
      - public_dns                           = "ec2-35-74-235-177.ap-northeast-1.compute.amazonaws.com" -> null
      - public_ip                            = "35.74.235.177" -> null
      - secondary_private_ips                = [] -> null
      - security_groups                      = [
          - "default",
        ] -> null
      - source_dest_check                    = true -> null
      - subnet_id                            = "subnet-c9e366e2" -> null
      - tags                                 = {
          - "Environment" = "Dev"
          - "Name"        = "ec2-instance-1"
        } -> null
      - tags_all                             = {
          - "Environment" = "Dev"
          - "Name"        = "ec2-instance-1"
        } -> null
      - tenancy                              = "default" -> null
      - user_data_replace_on_change          = false -> null
      - vpc_security_group_ids               = [
          - "sg-92a2c4d1",
        ] -> 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 = 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                  = 0 -> null
          - tags                  = {} -> null
          - throughput            = 0 -> null
          - volume_id             = "vol-08fbc8ebcf3e701e4" -> null
          - volume_size           = 8 -> null
          - volume_type           = "standard" -> null
        }
    }

Plan: 0 to add, 0 to change, 2 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

輸入確認後,會看到銷毀資源的結果輸出:

module.my_ec2_instances.aws_instance.example[0]: Destroying... [id=i-083c2d59bb1871ef7]
module.my_ec2_instances.aws_instance.example[1]: Destroying... [id=i-0436f01af4aa76c7a]
module.my_ec2_instances.aws_instance.example[1]: Still destroying... [id=i-0436f01af4aa76c7a, 10s elapsed]
module.my_ec2_instances.aws_instance.example[0]: Still destroying... [id=i-083c2d59bb1871ef7, 10s elapsed]
module.my_ec2_instances.aws_instance.example[0]: Still destroying... [id=i-083c2d59bb1871ef7, 20s elapsed]
module.my_ec2_instances.aws_instance.example[1]: Still destroying... [id=i-0436f01af4aa76c7a, 20s elapsed]
module.my_ec2_instances.aws_instance.example[0]: Still destroying... [id=i-083c2d59bb1871ef7, 30s elapsed]
module.my_ec2_instances.aws_instance.example[1]: Still destroying... [id=i-0436f01af4aa76c7a, 30s elapsed]
module.my_ec2_instances.aws_instance.example[0]: Destruction complete after 31s
module.my_ec2_instances.aws_instance.example[1]: Still destroying... [id=i-0436f01af4aa76c7a, 40s elapsed]
module.my_ec2_instances.aws_instance.example[1]: Still destroying... [id=i-0436f01af4aa76c7a, 50s elapsed]
module.my_ec2_instances.aws_instance.example[1]: Destruction complete after 51s

Destroy complete! Resources: 2 destroyed.

接下來將介紹如何在多個佈署環境,使用不同的 tfvars 檔案。


上一篇
如何利用 HCL 語言的撰寫 Terraform 專案的基本介紹 (Part III) - 模組化
下一篇
如何利用 HCL 語言的撰寫 Terraform 專案的基本介紹 (Part V) - 使用 tfvars 多環境佈署
系列文
大家都在用 Terraform 實作 IaC 為什麼不將程式寫得更簡潔易讀呢?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言