Terraform入门笔记:Terraform命令行工具安装~在IBM Cloud VPC中创建VSI

主要参考以下内容进行实施。终端设备为Windows10。

在IBM Cloud上开始使用Terraform
为VPC提供IBM Cloud虚拟服务器

在终端上安装Terraform CLI。

创建一个Terraform目录。

PS C:\work> mkdir terraform; cd terraform

    ディレクトリ: C:\work

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----        2021/06/16     13:17                terraform

PS C:\work\terraform>

请下载并解压Terraform软件,
链接:https://releases.hashicorp.com/terraform/

PS C:\work\terraform> dir

    ディレクトリ: C:\work\terraform

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----        2021/06/16     13:18                terraform_0.14.11_windows_amd64
-a----        2021/06/16     13:15       34043279 terraform_0.14.11_windows_amd64.zip

PS C:\work\terraform> dir terraform_0.14.11_windows_amd64

    ディレクトリ: C:\work\terraform\terraform_0.14.11_windows_amd64

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        2021/06/16     13:18       84003704 terraform.exe

PS C:\work\terraform>

通过路径执行命令进行确认。

PS C:\work\terraform> $ENV:Path=$ENV:Path+";C:\work\terraform\terraform_0.14.11_windows_amd64"
PS C:\work\terraform> terraform
Usage: terraform [global options] <subcommand> [args]

The available commands for execution are listed below.
The primary workflow commands are given first, followed by
less common or more advanced commands.

Main commands:
  init          Prepare your working directory for other commands
  validate      Check whether the configuration is valid
  plan          Show changes required by the current configuration
  apply         Create or update infrastructure
  destroy       Destroy previously-created infrastructure

All other commands:
  console       Try Terraform expressions at an interactive command prompt
  fmt           Reformat your configuration in the standard style
  force-unlock  Release a stuck lock on the current workspace
  get           Install or upgrade remote Terraform modules
  graph         Generate a Graphviz graph of the steps in an operation
  import        Associate existing infrastructure with a Terraform resource
  login         Obtain and save credentials for a remote host
  logout        Remove locally-stored credentials for a remote host
  output        Show output values from your root module
  providers     Show the providers required for this configuration
  refresh       Update the state to match remote systems
  show          Show the current state or a saved plan
  state         Advanced state management
  taint         Mark a resource instance as not fully functional
  untaint       Remove the 'tainted' state from a resource instance
  version       Show the current Terraform version
  workspace     Workspace management

Global options (use these before the subcommand, if any):
  -chdir=DIR    Switch to a different working directory before executing the
                given subcommand.
  -help         Show this help output, or the help for a specified subcommand.
  -version      An alias for the "version" subcommand.
PS C:\work\terraform>

准备VPC环境

这次我们将使用GUI进行操作。具体细节省略。

sg.PNG

创建.tf文件

versions.tf 的不同版本

可以在以下链接中确认Terraform的版本。
https://registry.terraform.io/providers/IBM-Cloud/ibm/latest

terraform {
   required_providers {
      ibm = {
         source = "IBM-Cloud/ibm"
         version = "1.26.2"
      }
    }
}

terraform.tfvars 可以被一个名为 terraform.tfvars 的文件 natively 包含。

变量的定义

ibmcloud_api_key="xxxxxx"
resource_group="c6bcd9b18bb64c288510d19806dd12dc"

※API密钥请使用之前已创建的密钥,详细信息略过
※资源组ID可以通过下面的方式确认

PS C:\work\terraform> ibmcloud resource groups
Retrieving all resource groups under account 1234567890a1234567890b1234567890 as xxxx@jp.ibm.com...
OK
Name                    ID                                 Default Group   State
resourcegroup1   c6bcd9b18bb64c288510d19806dd12dc   false           ACTIVE

请提供provider.tf文件。

variable "ibmcloud_api_key" {}
variable "resource_group" {}

provider "ibm" {
  ibmcloud_api_key = var.ibmcloud_api_key
  region           = "jp-tok"
  resource_group   = var.resource_group
}

对于VSI测试,请提供一种本地化的中文解释。

定義创建 VSI(Virtual Server Instance)和 Floating IP 所需的信息。

localsはローカル変数

dataは既存のIBM Cloudリソースの情報を取得

VPC等々既存リソースのリソース名を指定

resourceのパラメータで既存リソースのID値を指定する必要があるが、ここで取得しておけばID値を調べることなく data.xxx.id のように指定できる

resourceが作成するリソースの情報(GUIならオーダー画面で指定する項目に相当)

locals {
  ZONE     = "jp-tok-2"
  BASENAME = "test"
}

data "ibm_is_vpc" "vpc" {
  name = "vpc-${local.BASENAME}"
}

data "ibm_is_subnet" "sbn" {
  name = "sbn-${local.BASENAME}"
}

data "ibm_is_security_group" "sg" {
  name = "sg-${local.BASENAME}"
}

data "ibm_is_image" "centos" {
  name = "ibm-centos-8-3-minimal-amd64-3"
}

data "ibm_is_ssh_key" "ssh_key" {
  name = "key-test"
}

resource "ibm_is_instance" "vsi" {
  name    = "vsi-test"
  vpc     = data.ibm_is_vpc.vpc.id
  zone    = local.ZONE
  keys    = [data.ibm_is_ssh_key.ssh_key.id]
  image   = data.ibm_is_image.centos.id
  profile = "cx2-2x4"
  primary_network_interface {
    subnet = data.ibm_is_subnet.sbn.id
    security_groups = [data.ibm_is_security_group.sg.id]
  }
  resource_group = var.resource_group
}

resource "ibm_is_floating_ip" "fip" {
  name   = "fip-${local.BASENAME}"
  target = ibm_is_instance.vsi.primary_network_interface[0].id
  resource_group = var.resource_group
}

执行terraform

初始化terraform

PS C:\work\terraform> terraform init

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of ibm-cloud/ibm from the dependency lock file
- Using previously-installed ibm-cloud/ibm v1.26.2

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.
PS C:\work\terraform>

执行Terraform计划

PS C:\work\terraform> terraform plan

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # ibm_is_floating_ip.fip will be created
  + resource "ibm_is_floating_ip" "fip" {
      + address                 = (known after apply)
      + id                      = (known after apply)
      + name                    = "fip-test"
      + resource_controller_url = (known after apply)
      + resource_crn            = (known after apply)
      + resource_group          = "c6bcd9b18bb64c288510d19806dd12dc"
      + resource_group_name     = (known after apply)
      + resource_name           = (known after apply)
      + resource_status         = (known after apply)
      + status                  = (known after apply)
      + tags                    = (known after apply)
      + target                  = (known after apply)
      + zone                    = (known after apply)
    }

  # ibm_is_instance.vsi will be created
  + resource "ibm_is_instance" "vsi" {
      + disks                   = (known after apply)
      + gpu                     = (known after apply)
      + id                      = (known after apply)
      + image                   = "r022-95e7a9a1-8707-49ea-bdef-693311570ce0"
      + keys                    = [
        ]
      + memory                  = (known after apply)
      + name                    = "vsi-test"
      + profile                 = "cx2-2x4"
      + resource_controller_url = (known after apply)
      + resource_crn            = (known after apply)
      + resource_group          = "c6bcd9b18bb64c288510d19806dd12dc"
      + resource_group_name     = (known after apply)
      + resource_name           = (known after apply)
      + resource_status         = (known after apply)
      + status                  = (known after apply)
      + tags                    = (known after apply)
      + vcpu                    = (known after apply)
      + volume_attachments      = (known after apply)
      + vpc                     = "r022-45600dc1-1f1a-4a09-a0a7-6131cbbdcfb4"
      + wait_before_delete      = true
      + zone                    = "jp-tok-2"

      + boot_volume {
          + encryption = (known after apply)
          + iops       = (known after apply)
          + name       = (known after apply)
          + profile    = (known after apply)
          + size       = (known after apply)
        }

      + primary_network_interface {
          + allow_ip_spoofing    = false
          + id                   = (known after apply)
          + name                 = (known after apply)
          + primary_ipv4_address = (known after apply)
          + security_groups      = [
              + "r022-9101424b-84e2-4081-8484-53baffaeb9b7",
            ]
          + subnet               = "02f7-3d141b46-f9ac-46d6-9645-748471961b84"
        }
    }

Plan: 2 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

PS C:\work\terraform>

部署terraform

PS C:\work\terraform> terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # ibm_is_floating_ip.fip will be created
  + resource "ibm_is_floating_ip" "fip" {
      + address                 = (known after apply)
      + id                      = (known after apply)
      + name                    = "fip-test"
      + resource_controller_url = (known after apply)
      + resource_crn            = (known after apply)
      + resource_group          = "c6bcd9b18bb64c288510d19806dd12dc"
      + resource_group_name     = (known after apply)
      + resource_name           = (known after apply)
      + resource_status         = (known after apply)
      + status                  = (known after apply)
      + tags                    = (known after apply)
      + target                  = (known after apply)
      + zone                    = (known after apply)
    }

  # ibm_is_instance.vsi will be created
  + resource "ibm_is_instance" "vsi" {
      + disks                   = (known after apply)
      + gpu                     = (known after apply)
      + id                      = (known after apply)
      + image                   = "r022-95e7a9a1-8707-49ea-bdef-693311570ce0"
      + keys                    = [
          + "r022-fba74a1a-c774-429f-b833-906cd913a64e",
        ]
      + memory                  = (known after apply)
      + name                    = "vsi-test"
      + profile                 = "cx2-2x4"
      + resource_controller_url = (known after apply)
      + resource_crn            = (known after apply)
      + resource_group          = "c6bcd9b18bb64c288510d19806dd12dc"
      + resource_group_name     = (known after apply)
      + resource_name           = (known after apply)
      + resource_status         = (known after apply)
      + status                  = (known after apply)
      + tags                    = (known after apply)
      + vcpu                    = (known after apply)
      + volume_attachments      = (known after apply)
      + vpc                     = "r022-45600dc1-1f1a-4a09-a0a7-6131cbbdcfb4"
      + wait_before_delete      = true
      + zone                    = "jp-tok-2"

      + boot_volume {
          + encryption = (known after apply)
          + iops       = (known after apply)
          + name       = (known after apply)
          + profile    = (known after apply)
          + size       = (known after apply)
        }

      + primary_network_interface {
          + allow_ip_spoofing    = false
          + id                   = (known after apply)
          + name                 = (known after apply)
          + primary_ipv4_address = (known after apply)
          + security_groups      = [
              + "r022-9101424b-84e2-4081-8484-53baffaeb9b7",
            ]
          + subnet               = "02f7-3d141b46-f9ac-46d6-9645-748471961b84"
        }
    }

Plan: 2 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

ibm_is_instance.vsi: Creating...
ibm_is_instance.vsi: Still creating... [10s elapsed]
ibm_is_instance.vsi: Still creating... [20s elapsed]
ibm_is_instance.vsi: Still creating... [30s elapsed]
ibm_is_instance.vsi: Creation complete after 30s [id=02f7_d2362719-28e8-4a58-8c60-102892ce46cd]
ibm_is_floating_ip.fip: Creating...
ibm_is_floating_ip.fip: Still creating... [10s elapsed]
ibm_is_floating_ip.fip: Creation complete after 15s [id=r022-512fdb3d-5525-4082-82c0-10c6a1be2456]

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
PS C:\work\terraform>

确认已创建的VSI

VSI已经创建并处于运行状态。

PS C:\work\terraform> ibmcloud is instances
Listing instances for generation 2 compute in resource group resourcegroup1 and region jp-tok under account IBM as user xxxx@jp.ibm.com...
ID                                          Name            Status    Address       Floating IP      Profile   Image                            VPC                Zone       Resource group
02f7_d2362719-28e8-4a58-8c60-102892ce46cd   vsi-test   running   yyy.yyy.yyy.yyy   xxx.xxx.xxx.xxx   cx2-2x4   ibm-centos-8-3-minimal-amd64-3   vpc-test   jp-tok-2   resourcegroup1
PS C:\work\terraform>

浮动IP成功SSH连接。
它是在指定的操作系统上创建的。

PS C:\work\terraform> ssh -i C:\Users\AaaBbb\.ssh\key-test root@xxx.xxx.xxx.xxx
The authenticity of host 'xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx)' can't be established.
ECDSA key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxx.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'xxx.xxx.xxx.xxx' (ECDSA) to the list of known hosts.
[root@vsi-test ~]# cat /etc/redhat-release
CentOS Linux release 8.3.2011
[root@vsi-test ~]#

當關閉 VPN 時,無法進行連接(確保安全組仍然有效)。

PS C:\work\terraform> ssh -i C:\Users\AaaBbb\.ssh\key-test root@xxx.xxx.xxx.xxx
ssh: connect to host xxx.xxx.xxx.xxx port 22: Connection timed out
PS C:\work\terraform>

删除资源

销毁terraform

可以使用terraform destroy命令来删除通过terraform创建的资源。

PS C:\work\terraform> terraform destroy

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  # ibm_is_floating_ip.fip will be destroyed
  - resource "ibm_is_floating_ip" "fip" {
      - address                 = "xxx.xxx.xxx.xxx" -> null
      - id                      = "r022-512fdb3d-5525-4082-82c0-10c6a1be2456" -> null
      - name                    = "fip-test" -> null
      - resource_controller_url = "https://cloud.ibm.com/vpc-ext/network/floatingIPs" -> null
      - resource_crn            = "crn:v1:bluemix:public:is:jp-tok-2:a/1fc8373f538a408187ffedbe62e5796a::floating-ip:r022-512fdb3d-5525-4082-82c0-10c6a1be2456" -> null
      - resource_group          = "c6bcd9b18bb64c288510d19806dd12dc" -> null
      - resource_group_name     = "resourcegroup1" -> null
      - resource_name           = "fip-test" -> null
      - resource_status         = "available" -> null
      - status                  = "available" -> null
      - tags                    = [] -> null
      - target                  = "02f7-4b102bad-5d14-45b3-bda8-81657fec56a9" -> null
      - zone                    = "jp-tok-2" -> null
    }

  # ibm_is_instance.vsi will be destroyed
  - resource "ibm_is_instance" "vsi" {
      - disks                   = [] -> null
      - gpu                     = [] -> null
      - id                      = "02f7_d2362719-28e8-4a58-8c60-102892ce46cd" -> null
      - image                   = "r022-95e7a9a1-8707-49ea-bdef-693311570ce0" -> null
      - keys                    = [
          - "r022-fba74a1a-c774-429f-b833-906cd913a64e",
        ] -> null
      - memory                  = 4 -> null
      - name                    = "vsi-test" -> null
      - profile                 = "cx2-2x4" -> null
      - resource_controller_url = "https://cloud.ibm.com/vpc-ext/compute/vs" -> null
      - resource_crn            = "crn:v1:bluemix:public:is:jp-tok-2:a/1fc8373f538a408187ffedbe62e5796a::instance:02f7_d2362719-28e8-4a58-8c60-102892ce46cd" -> null
      - resource_group          = "c6bcd9b18bb64c288510d19806dd12dc" -> null
      - resource_group_name     = "resourcegroup1" -> null
      - resource_name           = "vsi-test" -> null
      - resource_status         = "running" -> null
      - status                  = "running" -> null
      - tags                    = [] -> null
      - vcpu                    = [
          - {
              - architecture = "amd64"
              - count        = 2
            },
        ] -> null
      - volume_attachments      = [
          - {
              - id          = "02f7-b0fdfe7e-27ba-41de-a46a-671de4f15bcf"
              - name        = "clubbing-divisive-pointer-letdown"
              - volume_crn  = "crn:v1:bluemix:public:is:jp-tok-2:a/1fc8373f538a408187ffedbe62e5796a::volume:r022-708837e6-4e27-44d6-b0ac-620484213e50"
              - volume_id   = "r022-708837e6-4e27-44d6-b0ac-620484213e50"
              - volume_name = "shawl-grime-detour-presoaked"
            },
        ] -> null
      - vpc                     = "r022-45600dc1-1f1a-4a09-a0a7-6131cbbdcfb4" -> null
      - wait_before_delete      = true -> null
      - zone                    = "jp-tok-2" -> null

      - boot_volume {
          - iops    = 3000 -> null
          - name    = "shawl-grime-detour-presoaked" -> null
          - profile = "general-purpose" -> null
          - size    = 100 -> null
        }

      - primary_network_interface {
          - allow_ip_spoofing    = false -> null
          - id                   = "02f7-4b102bad-5d14-45b3-bda8-81657fec56a9" -> null
          - name                 = "stalemate-theorize-donator-steerable" -> null
          - port_speed           = 0 -> null
          - primary_ipv4_address = "yyy.yyy.yyy.yyy" -> null
          - security_groups      = [
              - "r022-9101424b-84e2-4081-8484-53baffaeb9b7",
            ] -> null
          - subnet               = "02f7-3d141b46-f9ac-46d6-9645-748471961b84" -> 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

ibm_is_floating_ip.fip: Destroying... [id=r022-512fdb3d-5525-4082-82c0-10c6a1be2456]
ibm_is_floating_ip.fip: Still destroying... [id=r022-512fdb3d-5525-4082-82c0-10c6a1be2456, 10s elapsed]
ibm_is_floating_ip.fip: Destruction complete after 14s
ibm_is_instance.vsi: Destroying... [id=02f7_d2362719-28e8-4a58-8c60-102892ce46cd]
ibm_is_instance.vsi: Still destroying... [id=02f7_d2362719-28e8-4a58-8c60-102892ce46cd, 10s elapsed]
ibm_is_instance.vsi: Still destroying... [id=02f7_d2362719-28e8-4a58-8c60-102892ce46cd, 20s elapsed]
ibm_is_instance.vsi: Still destroying... [id=02f7_d2362719-28e8-4a58-8c60-102892ce46cd, 30s elapsed]
ibm_is_instance.vsi: Still destroying... [id=02f7_d2362719-28e8-4a58-8c60-102892ce46cd, 40s elapsed]
ibm_is_instance.vsi: Still destroying... [id=02f7_d2362719-28e8-4a58-8c60-102892ce46cd, 50s elapsed]
ibm_is_instance.vsi: Destruction complete after 52s

Destroy complete! Resources: 2 destroyed.
PS C:\work\terraform>

确认VSI已不在

PS C:\work\terraform> ibmcloud is instances
Listing instances for generation 2 compute in resource group resourcegroup1 and region jp-tok under account IBM as user xxxx@jp.ibm.com...
No instances were found.
PS C:\work\terraform>

错误处理备忘录

到terraform执行错误和修正vsi-test.tf文件的备忘录之前,需要创建VSI。

执行terraform plan时出现错误。

错误:找不到名称为xxx的图片。
Error: No image found with name  centos-8-amd64

  on vsi-test.tf line 36, in data "ibm_is_image" "centos":
  36: data "ibm_is_image" "centos" {

您可以通过ibmcloud is images来确认可用的image。
请使用Name的值而不是OS名称进行设置。

PS C:\work> ibmcloud is images
Listing images for generation 2 compute in resource group resourcegroup1 and region jp-tok under account IBM as user xxxx@jp.ibm.com...
ID                                          Name                                               Status       Arch    OS name                              OS version                                File size(GB)   Visibility   Owner type   Encryption   Resource group
r022-f10e4ea0-1f0b-4fb6-8cfd-1c9aad475046   ibm-centos-7-9-minimal-amd64-3                     available    amd64   centos-7-amd64                       7.x - Minimal Install                     1               public       provider     none         -
r022-95e7a9a1-8707-49ea-bdef-693311570ce0   ibm-centos-8-3-minimal-amd64-3                     available    amd64   centos-8-amd64                       8.x - Minimal Install                     1               public       provider     none         -
(略)
修正前修正後data “ibm_is_image” “centos” {
name = “centos-8-amd64”
}data “ibm_is_image” “centos” {
name = “ibm-centos-8-3-minimal-amd64-3”
}
错误:属性值类型不正确
Error: Incorrect attribute value type

  on vsi-test.tf line 53, in resource "ibm_is_instance" "vsi-test":
  53:   keys    = "r022-fba74a1a-c774-429f-b833-906cd913a64e"

Inappropriate value for attribute "keys": set of string required.

如下所示,SSH密钥需要以数组形式指定,即需要用[]括起来。
https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/is_instance

修正前修正後resource “ibm_is_instance” “vsi” {
(略)
keys = data.ibm_is_ssh_key.ssh_key.idresource “ibm_is_instance” “vsi” {
(略)
keys = [data.ibm_is_ssh_key.ssh_key.id]

terraform执行”apply”时出现错误。

错误:用户没有权限使用默认的资源组
略
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

ibm_is_instance.vsi-test: Creating...

Error: user does not have permission to use default resource group

  on vsi-test.tf line 49, in resource "ibm_is_instance" "vsi-test":
  49: resource "ibm_is_instance" "vsi-test" {

(虽然在图形用户界面中也是同样的情况),需要指定资源组。

修正前修正後resource “ibm_is_instance” “vsi” {
(略)
}

resource “ibm_is_instance” “vsi” {
(略)
resource_group = var.resource_group
}

bannerAds