terraform使用

terraform usage and some demo with ansible and packer.

terraform相关

安装

下载二进制方法

1
[root@VM-1-13-centos terraform]# wget https://releases.hashicorp.com/terraform/1.0.2/terraform_1.0.2_linux_amd64.zip

用unzip解压并挪到/usr/local/bin下面即可

debian安装

1
2
3
liuliancao@liuliancao:~$ mkdir terraform
liuliancao@liuliancao:~$ cd terraform/
liuliancao@liuliancao:~/terraform$ sudo apt-get update && sudo apt-get install -y gnupg software-properties-common curl && curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add - &&  sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main" && sudo apt-get update && sudo apt-get install terraform

配置自动补全

[root@VM-1-13-centos terraform]# terraform -install-autocomplete [root@VM-1-13-centos terraform]# source .bashrc 就有补全了

使用和官方文档

terraform是什么

是一种云的编排工具,用代码描述基础设施

terraform能干啥

文档列出了一些场景https://www.terraform.io/intro/use-cases.html, 不再赘述

CLI

有哪些CLI
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
  [root@VM-16-12-centos ~]# 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 # 通过传-var="x=y"类似参数或者修改配置文件,执行修改
    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
    test          Experimental support for module integration testing
    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 # 切换workspace目录
                  given subcommand.
    -help         Show this help output, or the help for a specified subcommand.
    -version      An alias for the "version" subcommand.
terraform apply

terraform正常的workflow是

  • terraform init(项目初始化和更新模块,一旦引入新的模块都会提示)
  • 编写.tf文件(包含main.tf, vars.tf…) 默认会读取所有.tf文件
  • terraform validate(语法检查) 也可以不做,执行时候会自动检查
  • terraform plan (-target resource, 可以省略) 这一步也可以省略,直接apply,这一步是告诉我们有啥变化
  • terraform apply (-target resource,可以省略) 这一步不可省略,相当于代码执行
  • terraform destory (-target resource) 销毁之前的infrastructure(基础设施)(包含所有新建的资源)

官网例子

mac下可以正常执行
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# main.tf
terraform {
  required_providers {
    docker = {
      source  = "kreuzwerker/docker"
      version = "~> 2.13.0"
    }
  }
}

provider "docker" {}

resource "docker_image" "nginx" {
  name         = "nginx:latest"
  keep_locally = false
}

resource "docker_container" "nginx" {
  image = docker_image.nginx.latest
  name  = "tutorial"
  ports {
    internal = 80
    external = 8000
  }
}
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
    learn-terraform-docker-container terraform init

    Initializing the backend...

    Initializing provider plugins...
    - Finding kreuzwerker/docker versions matching "~> 2.13.0"...
    - Installing kreuzwerker/docker v2.13.0...
    - Installed kreuzwerker/docker v2.13.0 (self-signed, key ID 24E54F214569A8A5)

    Partner and community providers are signed by their developers.
    If you'd like to know more about provider signing, you can read about it here:
    https://www.terraform.io/docs/cli/plugins/signing.html

    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.

  ➜  learn-terraform-docker-container terraform apply

  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:

    # docker_container.nginx will be created
    + resource "docker_container" "nginx" {
        + attach           = false
        + bridge           = (known after apply)
        + command          = (known after apply)
        + container_logs   = (known after apply)
        + entrypoint       = (known after apply)
        + env              = (known after apply)
        + exit_code        = (known after apply)
        + gateway          = (known after apply)
        + hostname         = (known after apply)
        + id               = (known after apply)
        + image            = (known after apply)
        + init             = (known after apply)
        + ip_address       = (known after apply)
        + ip_prefix_length = (known after apply)
        + ipc_mode         = (known after apply)
        + log_driver       = "json-file"
        + logs             = false
        + must_run         = true
        + name             = "tutorial"
        + network_data     = (known after apply)
        + read_only        = false
        + remove_volumes   = true
        + restart          = "no"
        + rm               = false
        + security_opts    = (known after apply)
        + shm_size         = (known after apply)
        + start            = true
        + stdin_open       = false
        + tty              = false

        + healthcheck {
            + interval     = (known after apply)
            + retries      = (known after apply)
            + start_period = (known after apply)
            + test         = (known after apply)
            + timeout      = (known after apply)
          }

        + labels {
            + label = (known after apply)
            + value = (known after apply)
          }

        + ports {
            + external = 8000
            + internal = 80
            + ip       = "0.0.0.0"
            + protocol = "tcp"
          }
      }

    # docker_image.nginx will be created
    + resource "docker_image" "nginx" {
        + id           = (known after apply)
        + keep_locally = false
        + latest       = (known after apply)
        + name         = "nginx:latest"
        + output       = (known after apply)
        + repo_digest  = (known after apply)
      }

  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

  docker_image.nginx: Creating...
  docker_image.nginx: Still creating... [10s elapsed]
  docker_image.nginx: Still creating... [20s elapsed]
  docker_image.nginx: Creation complete after 30s [id=sha256:4cdc5dd7eaadff5080649e8d0014f2f8d36d4ddf2eff2fdf577dd13da85c5d2fnginx:latest]
  docker_container.nginx: Creating...
  docker_container.nginx: Creation complete after 1s [id=093608090a46be609c8804158e041645778960ecb64687498b469f6822195012]

  Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

然后访问localhost:8000会显示Welcome to nginx! docker ps能查看到

1
2
3
➜  learn-terraform-docker-container docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
093608090a46        4cdc5dd7eaad        "/docker-entrypoin..."   2 minutes ago       Up 2 minutes        0.0.0.0:8000->80/tcp   tutorial

可以用terraform destroy销毁创建的容器

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
➜  learn-terraform-docker-container terraform destroy
docker_image.nginx: Refreshing state... [id=sha256:4cdc5dd7eaadff5080649e8d0014f2f8d36d4ddf2eff2fdf577dd13da85c5d2fnginx:latest]
docker_container.nginx: Refreshing state... [id=093608090a46be609c8804158e041645778960ecb64687498b469f6822195012]

Note: Objects have changed outside of Terraform

Terraform detected the following changes made outside of Terraform since the last "terraform apply":

  # docker_container.nginx has been changed
  ~ resource "docker_container" "nginx" {
      + dns               = []
      + dns_opts          = []
      + dns_search        = []
      + group_add         = []
        id                = "093608090a46be609c8804158e041645778960ecb64687498b469f6822195012"
      + links             = []
      + log_opts          = {}
        name              = "tutorial"
      + sysctls           = {}
      + tmpfs             = {}
        # (30 unchanged attributes hidden)

        # (1 unchanged block hidden)
    }

Unless you have made equivalent changes to your configuration, or ignored the relevant attributes using ignore_changes, the following plan may include actions to undo or respond to these
changes.

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

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:

  # docker_container.nginx will be destroyed
  - resource "docker_container" "nginx" {
      - attach            = false -> null
      - command           = [
          - "nginx",
          - "-g",
          - "daemon off;",
        ] -> null
      - cpu_shares        = 0 -> null
      - dns               = [] -> null
      - dns_opts          = [] -> null
      - dns_search        = [] -> null
      - entrypoint        = [
          - "/docker-entrypoint.sh",
        ] -> null
      - env               = [] -> null
      - gateway           = "172.17.0.1" -> null
      - group_add         = [] -> null
      - hostname          = "093608090a46" -> null
      - id                = "093608090a46be609c8804158e041645778960ecb64687498b469f6822195012" -> null
      - image             = "sha256:4cdc5dd7eaadff5080649e8d0014f2f8d36d4ddf2eff2fdf577dd13da85c5d2f" -> null
      - init              = false -> null
      - ip_address        = "172.17.0.2" -> null
      - ip_prefix_length  = 16 -> null
      - links             = [] -> null
      - log_driver        = "json-file" -> null
      - log_opts          = {} -> null
      - logs              = false -> null
      - max_retry_count   = 0 -> null
      - memory            = 0 -> null
      - memory_swap       = 0 -> null
      - must_run          = true -> null
      - name              = "tutorial" -> null
      - network_data      = [
          - {
              - gateway                   = "172.17.0.1"
              - global_ipv6_address       = ""
              - global_ipv6_prefix_length = 0
              - ip_address                = "172.17.0.2"
              - ip_prefix_length          = 16
              - ipv6_gateway              = ""
              - network_name              = "bridge"
            },
        ] -> null
      - network_mode      = "default" -> null
      - privileged        = false -> null
      - publish_all_ports = false -> null
      - read_only         = false -> null
      - remove_volumes    = true -> null
      - restart           = "no" -> null
      - rm                = false -> null
      - security_opts     = [] -> null
      - shm_size          = 64 -> null
      - start             = true -> null
      - stdin_open        = false -> null
      - sysctls           = {} -> null
      - tmpfs             = {} -> null
      - tty               = false -> null

      - ports {
          - external = 8000 -> null
          - internal = 80 -> null
          - ip       = "0.0.0.0" -> null
          - protocol = "tcp" -> null
        }
    }

  # docker_image.nginx will be destroyed
  - resource "docker_image" "nginx" {
      - id           = "sha256:4cdc5dd7eaadff5080649e8d0014f2f8d36d4ddf2eff2fdf577dd13da85c5d2fnginx:latest" -> null
      - keep_locally = false -> null
      - latest       = "sha256:4cdc5dd7eaadff5080649e8d0014f2f8d36d4ddf2eff2fdf577dd13da85c5d2f" -> null
      - name         = "nginx:latest" -> null
      - repo_digest  = "nginx@sha256:353c20f74d9b6aee359f30e8e4f69c3d7eaea2f610681c4a95849a2fd7c497f9" -> 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

docker_container.nginx: Destroying... [id=093608090a46be609c8804158e041645778960ecb64687498b469f6822195012]
docker_container.nginx: Destruction complete after 1s
docker_image.nginx: Destroying... [id=sha256:4cdc5dd7eaadff5080649e8d0014f2f8d36d4ddf2eff2fdf577dd13da85c5d2fnginx:latest]
docker_image.nginx: Destruction complete after 0s

Destroy complete! Resources: 2 destroyed.
➜  learn-terraform-docker-container docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

和腾讯云集成

可参考文档 https://registry.terraform.io/providers/tencentcloudstack/tencentcloud/latest/docs

安装

需要注意的是可能会卡住,因为和registry可能会不通,所以我建议下载一份到处copy即可,具体可以看下面的隐藏目录 .terraform

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

[root@VM-1-13-centos init]# terraform init

Initializing the backend...

Initializing provider plugins...
- Finding tencentcloudstack/tencentcloud versions matching "1.56.15"...
- Installing tencentcloudstack/tencentcloud v1.56.15...
- Installed tencentcloudstack/tencentcloud v1.56.15 (signed by a HashiCorp partner, key ID 84F69E1C1BECF459)

Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html

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.
[root@VM-1-13-centos init]# cat main.tf
terraform {
  required_providers {
    tencentcloud = {
      source = "tencentcloudstack/tencentcloud"
      version = "1.56.15"
    }
  }
}
使用token创建一个腾讯云机器

具体请看我的目录 /root/terraform

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
  [root@VM-1-13-centos ecs]# pwd
  /root/terraform/tecent-cloud/ecs
  [root@VM-1-13-centos ecs]# ls -al
  总用量 32
  drwxr-xr-x 3 root root 4096 7月  19 18:53 .
  drwxr-xr-x 4 root root 4096 7月  19 17:54 ..
  -rw-r--r-- 1 root root 1122 7月  19 18:48 main.tf
  -rw-r--r-- 1 root root  801 7月  19 18:31 main.tf.bak
  drwxr-xr-x 3 root root 4096 7月  19 18:21 .terraform
  -rw-r--r-- 1 root root 1275 7月  19 18:22 .terraform.lock.hcl
  -rw-r--r-- 1 root root 7859 7月  19 18:53 terraform.tfstate
  # add for tencent test by lqx
  terraform {
    required_providers {
      tencentcloud = {
        source = "tencentcloudstack/tencentcloud"
        version = "1.56.15"
      }
    }
  }
  provider "tencentcloud" {
    # 这个对应于用户列表-用户详情-API密钥的地方哈
    secret_id  = "xxx"
    secret_key = "xxx"
    region     = "ap-shanghai"
  }
  # Get availability zones
  data "tencentcloud_availability_zones" "lqx-zones" {
  }

  # Get availability instance types
  data "tencentcloud_instance_types" "lqx-instance-type" {
    cpu_core_count = 1
    memory_size    = 1
  }

  # add a new ecs with a image id and security group
  resource "tencentcloud_instance" "lqx-test-group" {
    instance_name              = "voyoger-test-lqx-gp"
    availability_zone          = data.tencentcloud_availability_zones.lqx-zones.zones.0.name
    image_id                   = "img-d3n1ffcx"
    instance_type              = "C4.LARGE16"
    system_disk_type           = "CLOUD_PREMIUM"
    system_disk_size           = 150
    allocate_public_ip         = false
    internet_max_bandwidth_out = 20
    security_groups            = ["sg-krhzolik"]
    count                      = 2
  }

然后执行terraform init && terraform plan && terraform apply

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
[root@VM-1-13-centos ecs]# terraform apply

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:

  # tencentcloud_instance.lqx-test-group[0] will be created
  + resource "tencentcloud_instance" "lqx-test-group" {
      + allocate_public_ip                      = false
      + availability_zone                       = "ap-shanghai-4"
      + create_time                             = (known after apply)
      + disable_monitor_service                 = false
      + disable_security_service                = false
      + expired_time                            = (known after apply)
      + force_delete                            = false
      + id                                      = (known after apply)
      + image_id                                = "img-d3n1ffcx"
      + instance_charge_type                    = "POSTPAID_BY_HOUR"
      + instance_charge_type_prepaid_renew_flag = (known after apply)
      + instance_count                          = 1
      + instance_name                           = "voyoger-test-lqx-gp"
      + instance_status                         = (known after apply)
      + instance_type                           = "C4.LARGE16"
      + internet_charge_type                    = (known after apply)
      + internet_max_bandwidth_out              = 20
      + key_name                                = (known after apply)
      + private_ip                              = (known after apply)
      + project_id                              = 0
      + public_ip                               = (known after apply)
      + running_flag                            = true
      + security_groups                          = [
          + "sg-krhzolik",
        ]
      + subnet_id                               = (known after apply)
      + system_disk_id                          = (known after apply)
      + system_disk_size                        = 150
      + system_disk_type                        = "CLOUD_PREMIUM"
      + vpc_id                                  = (known after apply)

      + data_disks {
          + data_disk_id           = (known after apply)
          + data_disk_size         = (known after apply)
          + data_disk_snapshot_id  = (known after apply)
          + data_disk_type         = (known after apply)
          + delete_with_instance   = (known after apply)
          + encrypt                = (known after apply)
          + throughput_performance = (known after apply)
        }
    }

  # tencentcloud_instance.lqx-test-group[1] will be created
  + resource "tencentcloud_instance" "lqx-test-group" {
      + allocate_public_ip                      = false
      + availability_zone                       = "ap-shanghai-4"
      + create_time                             = (known after apply)
      + disable_monitor_service                 = false
      + disable_security_service                = false
      + expired_time                            = (known after apply)
      + force_delete                            = false
      + id                                      = (known after apply)
      + image_id                                = "img-d3n1ffcx"
      + instance_charge_type                    = "POSTPAID_BY_HOUR"
      + instance_charge_type_prepaid_renew_flag = (known after apply)
      + instance_count                          = 1
      + instance_name                           = "voyoger-test-lqx-gp"
      + instance_status                         = (known after apply)
      + instance_type                           = "C4.LARGE16"
      + internet_charge_type                    = (known after apply)
      + internet_max_bandwidth_out              = 20
      + key_name                                = (known after apply)
      + private_ip                              = (known after apply)
      + project_id                              = 0
      + public_ip                               = (known after apply)
      + running_flag                            = true
      + security_groups                         = [
          + "sg-krhzolik",
        ]
      + subnet_id                               = (known after apply)
      + system_disk_id                          = (known after apply)
      + system_disk_size                        = 150
      + system_disk_type                        = "CLOUD_PREMIUM"
      + vpc_id                                  = (known after apply)

      + data_disks {
          + data_disk_id           = (known after apply)
          + data_disk_size         = (known after apply)
          + data_disk_snapshot_id  = (known after apply)
          + data_disk_type         = (known after apply)
          + delete_with_instance   = (known after apply)
          + encrypt                = (known after apply)
          + throughput_performance = (known after apply)
        }
    }

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

tencentcloud_instance.lqx-test-group[1]: Creating...
tencentcloud_instance.lqx-test-group[0]: Creating...
tencentcloud_instance.lqx-test-group[0]: Still creating... [10s elapsed]
tencentcloud_instance.lqx-test-group[1]: Still creating... [10s elapsed]
tencentcloud_instance.lqx-test-group[0]: Creation complete after 13s [id=ins-qvn2tscv]
tencentcloud_instance.lqx-test-group[1]: Creation complete after 13s [id=ins-qgcww8tn]

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

和阿里云集成

terraform language

block

<BLOCK TYPE> "<BLOCK LABEL>" "<BLOCK LABEL>" {

<IDENTIFIER> = <EXPRESSION> # Argument }

variable

variable "availability_zones" { description = "A list of availability zones in which to create subnets" type = list(string) }

count

https://www.terraform.io/docs/language/meta-arguments/count.html count可以用在资源需要多次创建情况 获取count的第几次是count.index

for_each

https://www.terraform.io/docs/language/meta-arguments/for_each.html for_each可以是map或者是string list 使用是each.key each.value ${each.value} or each.value

output

toset toset(["a","b"])

map(object({a = b}))

lifecycle

刚开始是要3个,后来改成了2个处理

  • create before destroy

干掉1个

  • prevent destroy

不干掉

packer(镜像管理工具)

https://learn.hashicorp.com/packer https://learn.hashicorp.com/tutorials/packer/hcl2-upgrade?in=packer/configuration-language https://www.packer.io/docs https://www.packer.io/docs/builders/tencentcloud https://www.packer.io/downloads

download

可参考官方文档https://www.packer.io/downloads

1
2
3
4
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
sudo yum -y install packer
如果发现packer卡住,注意/usr/sbin/下面有可能有个packer那个不是我们这里的packer

cli

补全

1
2
3
4
  /usr/bin/packer -autocomplete-install
  /usr/bin/packer init
  /usr/bin/packer build
  /usr/bin/packer version

json to hcl

注意默认json形式是需要转换成pkr.hcl后缀的 ./packer hcl2_upgrade xxx.json ./packer init xxx.json.pcr.hcl ./packer build xxx.json.pcr.hcl 然后就可以进行build build的逻辑是创建一个临时instance并进行额外的操作,这里请参考一个demo的配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
  source "tencentcloud-cvm" "xxx" {
    #associate_public_ip_address = true
    disk_size                   = 150
    disk_type                   = "CLOUD_PREMIUM"
    image_name                  = "xxx"
    instance_type               = "C3.LARGE8"
    packer_debug                = true
    region                      = "ap-shanghai"
    run_tags = {
      op-type = "image"
    }
    host_name = "xxx"
    secret_id       = "${var.secret_id}"
    secret_key      = "${var.secret_key}"
    source_image_id = "xxx"
    security_group_id = "xxx"
    ssh_password    = "xxx"
    ssh_username    = "root"
    subnet_id       = "xxx"
    vpc_id          = "xxx"
    zone            = "ap-shanghai-2"
  }

  build {
    sources = ["source.tencentcloud-cvm.xxx"]

    provisioner "ansible" {
      extra_arguments = ["-e xxx=\"yyy\""]
      playbook_file   = "/root/playbook/test-battle-image.yml"
    }
}

build

注意一点./packer build -machine-readable xxx.pkr.hpcl 这样就不用确认了哈