Terraform扩展
# 一、Terrform元参数
# Meta-Arguments 元参数
- count 创建相似的资源
- for_each 创建相似的资源
- depends_on 定义资源或者模块的依赖
- provider 定义provider选项
- lifecycle 资源的生命周期行为
# 二、Count创建资源副本
- count = num数值类型,可以通过length()计算数量
- count.index 索引
count
适合没有区别的资源创建时候使用
# 示例: 创建三条DNS记录
- server1.chsaos.com
- server2.chsaos.com
- server3.chsaos.com
locals {
zone = "chsaos.com"
records = ["server1","server2","server3"]
}
resource "alicloud_dns_record" "record" {
count = length{local.records}
name = local.zone
host_record = local.records[count.index]
type = "A"
value = "192.168.1.1"
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
项目目录"terraform-extend/count"
$ cd terraform-extend/count
$ tree ./
./
├── main.tf
└── versions.tf
0 directories, 2 files
# 声明环境变量
export ALICLOUD_ACCESS_KEY="xxxxxx"
export ALICLOUD_SECRET_KEY="xxxxxx"
export ALICLOUD_REGION="cn-shanghai"
export TF_CLI_CONFIG_FILE=/home/terraform/youdianzhishi-terraform/terraform-extend/.terraformrc
# 执行terraform命令
$ terraform init
$ terraform fmt 或 terraform init -recursive
$ terraform validate
$ terraform plan
$ terraform apply 或 terraform apply -auto-approve
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 会发生事项?
- 此时移除一条记录
- 移除
server2.chsaos.com
server2.chsaos.com
销毁?
$ vim main.tf
locals {
zone = "chsaos.com"
# records = ["server1", "server2", "server3"]
records = ["server1", "server3"]
}
resource "alicloud_dns_record" "record" {
count = length(local.records)
name = local.zone
host_record = local.records[count.index]
type = "A"
value = "192.168.1.1"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 更新后发生的问题
$ terraform plan
alicloud_dns_record.record[2]: Refreshing state... [id=786406789912754176]
alicloud_dns_record.record[0]: Refreshing state... [id=786406789925343232]
alicloud_dns_record.record[1]: Refreshing state... [id=786406789923228672]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
~ update in-place
- destroy
Terraform will perform the following actions:
# alicloud_dns_record.record[1] will be updated in-place
~ resource "alicloud_dns_record" "record" {
~ host_record = "server2" -> "server3"
id = "786406789923228672"
name = "chsaos.com"
# (7 unchanged attributes hidden)
}
# alicloud_dns_record.record[2] will be destroyed
# (because index [2] is out of range for count)
- resource "alicloud_dns_record" "record" {
- host_record = "server3" -> null
- id = "786406789912754176" -> null
- locked = false -> null
- name = "chsaos.com" -> null
- priority = 0 -> null
- routing = "default" -> null
- status = "ENABLE" -> null
- ttl = 600 -> null
- type = "A" -> null
- value = "192.168.1.1" -> null
}
Plan: 0 to add, 1 to change, 1 to 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
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
# 三、for_each出国念资源副本
可以过滤set类型和map类型
for_each = set(string) map(string)
它能用于set(string) 或者map(string)
set(string)
each.key = each.value
map(string)
each.key = key
each.value = value
$ vim main.tf
locals {
zone = "chsaos.com"
records = ["server1", "server2", "server3"]
}
resource "alicloud_dns_record" "record" {
for_each = toset(local.records)
name = local.zone
host_record = each.value
type = "A"
value = "192.168.1.1"
}
# 列表发生变化
$ vim main.tf
locals {
zone = "chsaos.com"
# records = ["server1", "server2", "server3"]
records = ["server1", "server3"]
}
resource "alicloud_dns_record" "record" {
for_each = toset(local.records)
name = local.zone
host_record = each.value
type = "A"
value = "192.168.1.1"
}
# 声明环境变量
export ALICLOUD_ACCESS_KEY="xxxxxx"
export ALICLOUD_SECRET_KEY="xxxxxx"
export ALICLOUD_REGION="cn-shanghai"
export TF_CLI_CONFIG_FILE=/home/terraform/youdianzhishi-terraform/terraform-extend/.terraformrc
# 执行terraform命令
$ terraform init
$ terraform fmt 或 terraform init -recursive
$ terraform validate
$ terraform plan
$ terraform apply 或 terraform apply -auto-approve
# 变更的结果(这里只是destroy了server2)
$ terraform apply -auto-approve
alicloud_dns_record.record["server2"]: Refreshing state... [id=786408864035945472]
alicloud_dns_record.record["server1"]: Refreshing state... [id=786408864033819648]
alicloud_dns_record.record["server3"]: Refreshing state... [id=786408864042206208]
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:
# alicloud_dns_record.record["server2"] will be destroyed
# (because key ["server2"] is not in for_each map)
- resource "alicloud_dns_record" "record" {
- host_record = "server2" -> null
- id = "786408864035945472" -> null
- locked = false -> null
- name = "chsaos.com" -> null
- priority = 0 -> null
- routing = "default" -> null
- status = "ENABLE" -> null
- ttl = 600 -> null
- type = "A" -> null
- value = "192.168.1.1" -> null
}
Plan: 0 to add, 0 to change, 1 to destroy.
alicloud_dns_record.record["server2"]: Destroying... [id=786408864035945472]
alicloud_dns_record.record["server2"]: Destruction complete after 0s
Apply complete! Resources: 0 added, 0 changed, 1 destroyed.
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
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
for_each
适用于创建不相同的资源
# 四、dynamic动态内联块
- dynamic: 定义动态资源块,后面是label,默认为生成的语句块名称
- for_each: 要进行迭代循环的对象(map、set、list)
- iterator(迭代器): 临时的变量名称,如果未定义则使用
label
即"ports" - content: 要生成的语句块的内容部分
示例:
- terraform调用docker api创建container
$ cd terraform-extend/dynamic
$ vim main.tf
provider "docker" {
host = "tcp://172.31.228.152:2375"
}
resource "docker_image" "jenkins" {
name = "jenkins/jenkins:2.332.2-centos7-jdk8"
keep_locally = true //销毁时不删除本地镜像
}
locals {
jenkins_ports = [
{
internal = 8080
external = 8080
},
{
internal = 50000
external = 50000
}
]
}
resource "docker_container" "jenkins" {
image = docker_image.jenkins.name
name = "jenkins123"
dynamic "ports" {
for_each = local.jenkins_ports
content {
internal = ports.value.internal
external = ports.value.external
ip = "0.0.0.0"
protocol = "tcp"
}
}
# ports {
# internal = 8080
# external = 8080
# ip = "0.0.0.0"
# protocol = "tcp"
# }
# ports {
# internal = 50000
# external = 50000
# ip = "0.0.0.0"
# protocol = "tcp"
# }
user = "root"
volumes {
container_path = "/var/jenkins_home"
host_path = "/data/jenkins/jenkins_home"
}
}
$ vim versions.tf
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~> 2.13.0"
}
}
}
# 执行terraform命令
$ terraform init
$ terraform fmt 或 terraform init -recursive
$ terraform validate
$ terraform plan
$ terraform apply 或 terraform apply -auto-approve
$ terraform destroy 或 terraform destroy -auto-approve
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
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
# 五、depends_on依赖关系
处理 资源或模块之间的依赖关系
这里还是以上面使用的docker 创建container示例
$ cd terraform-extend/dynamic
$ vim main.tf
# 在docker本机的话下面的docker API连接可以不用配置
provider "docker" {
host = "tcp://172.31.228.152:2375"
}
resource "docker_image" "jenkins" {
name = "jenkins/jenkins:2.332.2-centos7-jdk8"
keep_locally = true //销毁时不删除本地镜像
}
locals {
jenkins_ports = [
{
internal = 8080
external = 8080
},
{
internal = 50000
external = 50000
}
]
}
resource "docker_container" "jenkins" {
image = docker_image.jenkins.name
name = "jenkins123"
dynamic "ports" {
for_each = local.jenkins_ports
content {
internal = ports.value.internal
external = ports.value.external
ip = "0.0.0.0"
protocol = "tcp"
}
}
# ports {
# internal = 8080
# external = 8080
# ip = "0.0.0.0"
# protocol = "tcp"
# }
# ports {
# internal = 50000
# external = 50000
# ip = "0.0.0.0"
# protocol = "tcp"
# }
user = "root"
volumes {
container_path = "/var/jenkins_home"
host_path = "/data/jenkins/jenkins_home"
}
# 这里添加当前container依赖的资源为docker_image
depends_on = [
docker_image.jenkins
]
}
# 执行terraform命令
$ terraform init
$ terraform fmt 或 terraform init -recursive
$ terraform validate
$ terraform plan
$ terraform apply 或 terraform apply -auto-approve
$ terraform destroy 或 terraform destroy -auto-approve
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
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
# 六、provider自定义供应商
# resource
- 覆盖资源中的provider
- 例如: 分别在
cn-beijing
和cn-shanghai
区域分别创建1个实例
provider "alicloud" {
alias = "north"
region = "cn-beijing"
access_key = "xxxxxx"
secret_key = "xxxxxx"
}
provider "alicloud" {
region = "cn-shanghai"
access_key = "xxxxxx"
secret_key = "xxxxxx"
}
resource "alicloud_instance" "ecs_demo_north" {
provider = alicloud north
......
}
resource "alicloud_instance" "ecs_demo" {
......
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
示例
$ cd terraform-extend/provider
$ tree .
.
├── main.tf
└── versions.tf
0 directories, 2 files
# 声明环境变量
export ALICLOUD_ACCESS_KEY="xxxxxx"
export ALICLOUD_SECRET_KEY="xxxxxx"
export ALICLOUD_REGION="cn-shanghai"
export TF_CLI_CONFIG_FILE=/home/terraform/youdianzhishi-terraform/terraform-extend/.terraformrc
# 执行terraform命令
$ terraform init
$ terraform fmt 或 terraform init -recursive
$ terraform validate
$ terraform plan
$ terraform apply 或 terraform apply -auto-approve
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- 控制台查看VPC创建结果
# module
- 默认子模块继承根模块provider
- provider = map()
- key: provider名称
- value:
.
provider "alicloud" {
alias = "north"
region = "cn-beijing"
}
provider "alicloud" {
region = "cn-shanghai"
}
module "example" {
source = "./example"
provider = {
alicloud = alicloud north
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
示例
这里依赖modules下面的vpc模块调用"terraform-extend/modules/vpc"
$ cd terraform-extend/provider-module
tree ./
./
├── main.tf
└── versions.tf
0 directories, 2 files
# 声明环境变量
export ALICLOUD_ACCESS_KEY="xxxxxx"
export ALICLOUD_SECRET_KEY="xxxxxx"
export ALICLOUD_REGION="cn-shanghai"
export TF_CLI_CONFIG_FILE=/home/terraform/youdianzhishi-terraform/terraform-extend/.terraformrc
# 执行terraform命令
$ terraform init
$ terraform fmt 或 terraform init -recursive
$ terraform validate
$ terraform plan
$ terraform apply 或 terraform apply -auto-approve
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 七、生命周期
# lifecycle
- 标记资源不被删除或者销毁前创建新的资源
- create_before_destroy 先创建新的对象,再销毁旧的对象
- prevent_destroy 防止资源被销毁
- ignore_changes 忽略资源的差异
- replace_triggered_by 当指定的资源修改后替换当前资源
- precondition postcondition 条件检查
# 生命周期之销毁之前创建新资源
示例
$ cd terraform-extend/lifecycle/create_before_destroy
$ tree ./
./
├── main.tf
└── versions.tf
0 directories, 4 files
$ cat main.tf
provider "alicloud" {
region = "cn-shanghai"
}
locals {
region = "cn-shanghai-a"
# 这里的vsw所在区域为`cn-shanghai-a`
vsw_id = "vsw-uf6ct0jpe5ujmgh7my7np"
secgroup_id = "sg-uf6fy0y9i7j1t4dif549"
instance_name = "myecsserver1"
instance_type = "ecs.sn2ne.large"
}
data "alicloud_images" "images_ds" {
owners = "system"
name_regex = "^centos_7_9"
architecture = "x86_64"
status = "Available"
os_type = "linux"
# output_file = "./outputs.json"
}
# output "image_id" {
# value = data.alicloud_images.images_ds.images[2].id
# }
resource "alicloud_instance" "myecs2" {
availability_zone = local.region
security_groups = [local.secgroup_id]
instance_type = local.instance_type
system_disk_category = "cloud_efficiency"
system_disk_name = "tf_system_disk_name"
system_disk_description = "tf_system_disk_description"
image_id = data.alicloud_images.images_ds.images[2].id
instance_name = local.instance_name
vswitch_id = local.vsw_id
internet_max_bandwidth_out = 0
internet_charge_type = "PayByTraffic"
password = "root@1234"
# 开启先创建替换的资源,再去销毁需要被删除的资源
lifecycle {
create_before_destroy = true
}
}
# 声明环境变量
export ALICLOUD_ACCESS_KEY="xxxxxx"
export ALICLOUD_SECRET_KEY="xxxxxx"
export ALICLOUD_REGION="cn-shanghai"
export TF_CLI_CONFIG_FILE=/home/terraform/youdianzhishi-terraform/terraform-extend/.terraformrc
# 执行terraform命令
$ terraform init
$ terraform fmt 或 terraform init -recursive
$ terraform validate
$ terraform plan
$ terraform apply 或 terraform apply -auto-approve
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
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
注意
- terraform默认的行为是,先销毁一个资源再去创建一个资源
$ terraform plan
......
# alicloud_instance.myecs4 will be destroyed
# (because alicloud_instance.myecs4 is not in configuration)
- resource "alicloud_instance" "myecs4" {
......
- spot_price_limit = 0 -> null
- spot_strategy = "NoSpot" -> null
- status = "Running" -> null
- subnet_id = "vsw-uf6ct0jpe5ujmgh7my7np" -> null
- system_disk_category = "cloud_efficiency" -> null
- system_disk_description = "tf_system_disk_description" -> null
- system_disk_name = "tf_system_disk_name" -> null
- system_disk_size = 40 -> null
- tags = {
- "env" = "dev"
- "owner" = "bruce"
} -> null
- volume_tags = {
- "env" = "dev"
- "owner" = "bruce"
} -> null
- vswitch_id = "vsw-uf6ct0jpe5ujmgh7my7np" -> null
}
Plan: 1 to add, 0 to change, 1 to 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
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
- 加上"lifecycle"之后控制台查看目前正在创建一个新的资源来替换原有资源
# 生命周期之销毁之避免销毁
示例
$ cd terraform-extend/lifecycle/create_before_destroy
$ tree ./
./
├── main.tf
└── versions.tf
0 directories, 4 files
$ cat main.tf
provider "alicloud" {
region = "cn-shanghai"
}
locals {
region = "cn-shanghai-a"
# 这里的vsw所在区域为`cn-shanghai-a`
vsw_id = "vsw-uf6ct0jpe5ujmgh7my7np"
secgroup_id = "sg-uf6fy0y9i7j1t4dif549"
instance_name = "myecsserver1"
instance_type = "ecs.sn2ne.large"
}
data "alicloud_images" "images_ds" {
owners = "system"
name_regex = "^centos_7_9"
architecture = "x86_64"
status = "Available"
os_type = "linux"
# output_file = "./outputs.json"
}
# output "image_id" {
# value = data.alicloud_images.images_ds.images[2].id
# }
resource "alicloud_instance" "myecs2" {
availability_zone = local.region
security_groups = [local.secgroup_id]
instance_type = local.instance_type
system_disk_category = "cloud_efficiency"
system_disk_name = "tf_system_disk_name"
system_disk_description = "tf_system_disk_description"
image_id = data.alicloud_images.images_ds.images[2].id
instance_name = local.instance_name
vswitch_id = local.vsw_id
internet_max_bandwidth_out = 0
internet_charge_type = "PayByTraffic"
password = "root@1234"
# 开启先创建替换的资源,再去销毁需要被删除的资源
lifecycle {
create_before_destroy = true
# 开启防止销毁保护
prevent_destroy = true
}
}
# 声明环境变量
export ALICLOUD_ACCESS_KEY="xxxxxx"
export ALICLOUD_SECRET_KEY="xxxxxx"
export ALICLOUD_REGION="cn-shanghai"
export TF_CLI_CONFIG_FILE=/home/terraform/youdianzhishi-terraform/terraform-extend/.terraformrc
# 执行terraform命令
$ terraform init
$ terraform fmt 或 terraform init -recursive
$ terraform validate
$ terraform plan
$ terraform apply 或 terraform apply -auto-approve
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
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
注意:
- 销毁时候的错误提示
$ terraform destroy -auto-approve
data.alicloud_images.images_ds: Reading...
data.alicloud_images.images_ds: Read complete after 3s [id=1253956010]
alicloud_instance.myecs2: Refreshing state... [id=i-uf6gx7hn08wwq8v5vfeu]
╷
│ Error: Instance cannot be destroyed
│
│ on main.tf line 34:
│ 34: resource "alicloud_instance" "myecs2" {
│
│ Resource alicloud_instance.myecs2 has lifecycle.prevent_destroy set, but the plan calls for this resource to be destroyed. To
│ avoid this error and continue with the plan, either disable lifecycle.prevent_destroy or reduce the scope of the plan using the
│ -target flag.
╵
# 销毁提示生命周期中添加了防止销毁参数`lifecycle.prevent_destroy`
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 生命周期之忽略远程变更
示例
$ cd terraform-extend/lifecycle/create_before_destroy
$ tree ./
./
├── main.tf
└── versions.tf
0 directories, 4 files
$ cat main.tf
provider "alicloud" {
region = "cn-shanghai"
}
locals {
region = "cn-shanghai-a"
# 这里的vsw所在区域为`cn-shanghai-a`
vsw_id = "vsw-uf6ct0jpe5ujmgh7my7np"
secgroup_id = "sg-uf6fy0y9i7j1t4dif549"
instance_name = "myecsserver1"
instance_type = "ecs.sn2ne.large"
}
data "alicloud_images" "images_ds" {
owners = "system"
name_regex = "^centos_7_9"
architecture = "x86_64"
status = "Available"
os_type = "linux"
# output_file = "./outputs.json"
}
# output "image_id" {
# value = data.alicloud_images.images_ds.images[2].id
# }
resource "alicloud_instance" "myecs2" {
availability_zone = local.region
security_groups = [local.secgroup_id]
instance_type = local.instance_type
system_disk_category = "cloud_efficiency"
system_disk_name = "tf_system_disk_name"
system_disk_description = "tf_system_disk_description"
image_id = data.alicloud_images.images_ds.images[2].id
instance_name = local.instance_name
vswitch_id = local.vsw_id
internet_max_bandwidth_out = 0
internet_charge_type = "PayByTraffic"
password = "root@1234"
# 这里新增加了tags
tags = {
env = "dev"
owner = "bruce"
}
# 开启先创建替换的资源,再去销毁需要被删除的资源
lifecycle {
create_before_destroy = true
# 开启防止销毁保护
prevent_destroy = true
}
}
# 声明环境变量
export ALICLOUD_ACCESS_KEY="xxxxxx"
export ALICLOUD_SECRET_KEY="xxxxxx"
export ALICLOUD_REGION="cn-shanghai"
export TF_CLI_CONFIG_FILE=/home/terraform/youdianzhishi-terraform/terraform-extend/.terraformrc
# 执行terraform命令
$ terraform init
$ terraform fmt 或 terraform init -recursive
$ terraform validate
$ terraform plan
$ terraform apply 或 terraform apply -auto-approve
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
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
注意:
- 远程信息变更
$ terraform apply -auto-approve
data.alicloud_images.images_ds: Reading...
data.alicloud_images.images_ds: Read complete after 2s [id=1253956010]
alicloud_instance.myecs2: Refreshing state... [id=i-uf6gx7hn08wwq8v5vfeu]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
~ update in-place
Terraform will perform the following actions:
# alicloud_instance.myecs2 will be updated in-place
~ resource "alicloud_instance" "myecs2" {
id = "i-uf6gx7hn08wwq8v5vfeu"
~ tags = {
+ "env" = "dev"
+ "owner" = "bruce"
}
# (26 unchanged attributes hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
alicloud_instance.myecs2: Modifying... [id=i-uf6gx7hn08wwq8v5vfeu]
alicloud_instance.myecs2: Modifications complete after 1s [id=i-uf6gx7hn08wwq8v5vfeu]
Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
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
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
控制台编辑了tags,导致tags发生了表更
解决方法
1.在terraform文件中注释被修改的地方
2.在
lifecycle
中添加ignore_changes
,在ignore_changes
中如果有多个值的话用","做隔离
$ rraform plan
data.alicloud_images.images_ds: Reading...
data.alicloud_images.images_ds: Read complete after 2s [id=1253956010]
alicloud_instance.myecs2: Refreshing state... [id=i-uf6gx7hn08wwq8v5vfeu]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
~ update in-place
Terraform will perform the following actions:
# alicloud_instance.myecs2 will be updated in-place
~ resource "alicloud_instance" "myecs2" {
id = "i-uf6gx7hn08wwq8v5vfeu"
~ tags = {
+ "owner" = "bruce"
# (1 unchanged element hidden)
}
# (26 unchanged attributes hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
$ vim main.tf
......
lifecycle {
ignore_changes = [
tags,
instance_name
]
}
# 这里再次查看没有任何变更信息
$ terraform plan
data.alicloud_images.images_ds: Reading...
data.alicloud_images.images_ds: Read complete after 1s [id=1253956010]
alicloud_instance.myecs2: Refreshing state... [id=i-uf6gx7hn08wwq8v5vfeu]
No changes. Your infrastructure matches the configuration.
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
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
# 生命周期之触发资源替换
- replace_triggered_by 当指定的资源修改后替换当前资源(此功能是在terraform 1.2.0后新增的)
示例
$ cd terraform-extend/lifecycle/create_before_destroy
$ tree ./
./
├── main.tf
└── versions.tf
0 directories, 4 files
$ cat main.tf
provider "alicloud" {
region = "cn-shanghai"
}
locals {
region = "cn-shanghai-a"
# 这里的vsw所在区域为`cn-shanghai-a`
vsw_id = "vsw-uf6ct0jpe5ujmgh7my7np"
secgroup_id = "sg-uf6fy0y9i7j1t4dif549"
instance_name = "myecsserver1"
instance_type = "ecs.sn2ne.large"
}
data "alicloud_images" "images_ds" {
owners = "system"
name_regex = "^centos_7_9"
architecture = "x86_64"
status = "Available"
os_type = "linux"
# output_file = "./outputs.json"
}
# output "image_id" {
# value = data.alicloud_images.images_ds.images[2].id
# }
# 这里新增加了VPC
resource "alicloud_vpc" "vpc" {
vpc_name = "myvpc"
cidr_block = "172.20.0.0/16"
}
resource "alicloud_instance" "myecs2" {
availability_zone = local.region
security_groups = [local.secgroup_id]
instance_type = local.instance_type
system_disk_category = "cloud_efficiency"
system_disk_name = "tf_system_disk_name"
system_disk_description = "tf_system_disk_description"
image_id = data.alicloud_images.images_ds.images[2].id
instance_name = local.instance_name
vswitch_id = local.vsw_id
internet_max_bandwidth_out = 0
internet_charge_type = "PayByTraffic"
password = "root@1234"
lifecycle {
# 这里增加了替换的VPC资源
replace_triggered_by = [
alicloud_vpc.vpc.vpc_name
]
}
}
# 声明环境变量
export ALICLOUD_ACCESS_KEY="xxxxxx"
export ALICLOUD_SECRET_KEY="xxxxxx"
export ALICLOUD_REGION="cn-shanghai"
export TF_CLI_CONFIG_FILE=/home/terraform/youdianzhishi-terraform/terraform-extend/.terraformrc
# 执行terraform命令
$ terraform init
$ terraform fmt 或 terraform init -recursive
$ terraform validate
$ terraform plan
$ terraform apply 或 terraform apply -auto-approve
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
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
- 新增加VPC资源
$ vim main.tf
provider "alicloud" {
region = "cn-shanghai"
}
locals {
region = "cn-shanghai-a"
# 这里的vsw所在区域为`cn-shanghai-a`
vsw_id = "vsw-uf6ct0jpe5ujmgh7my7np"
secgroup_id = "sg-uf6fy0y9i7j1t4dif549"
instance_name = "myecsserver1"
instance_type = "ecs.sn2ne.large"
}
data "alicloud_images" "images_ds" {
owners = "system"
name_regex = "^centos_7_9"
architecture = "x86_64"
status = "Available"
os_type = "linux"
# output_file = "./outputs.json"
}
......
lifecycle {
create_before_destroy = true
# 这里增加了替换的VPC资源
replace_triggered_by = [
alicloud_vpc.vpc.vpc_name
]
}
}
# 查看terraform执行计划
$ terraform plan
data.alicloud_images.images_ds: Reading...
alicloud_vpc.vpc: Refreshing state... [id=vpc-uf62ypar80mrwhfoxuqw6]
data.alicloud_images.images_ds: Read complete after 1s [id=1253956010]
alicloud_instance.myecs2: Refreshing state... [id=i-uf6hcv5xjlfqccjdbjqy]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
~ update in-place
+/- create replacement and then destroy
Terraform will perform the following actions:
# alicloud_instance.myecs2 will be replaced due to changes in replace_triggered_by # 这里被触发的替换提示
+/- resource "alicloud_instance" "myecs2" {
+ credit_specification = (known after apply)
+ deployment_set_group_no = (known after apply)
~ host_name = "iZuf6hcv5xjlfqccjdbjqyZ" -> (known after apply)
~ id = "i-uf6hcv5xjlfqccjdbjqy" -> (known after apply)
- internet_charge_type = "PayByTraffic" -> null
~ internet_max_bandwidth_in = -1 -> (known after apply)
+ key_name = (known after apply)
~ private_ip = "172.19.17.55" -> (known after apply)
+ public_ip = (known after apply)
+ role_name = (known after apply)
~ secondary_private_ip_address_count = 0 -> (known after apply)
~ secondary_private_ips = [] -> (known after apply)
- spot_price_limit = 0 -> null
~ subnet_id = "vsw-uf6ct0jpe5ujmgh7my7np" -> (known after apply)
+ system_disk_performance_level = (known after apply)
tags = {
"env" = "dev"
"owner" = "bruce"
}
~ volume_tags = {
- "env" = "dev"
- "owner" = "bruce"
} -> (known after apply)
# (17 unchanged attributes hidden)
}
# alicloud_vpc.vpc will be updated in-place
~ resource "alicloud_vpc" "vpc" {
id = "vpc-uf62ypar80mrwhfoxuqw6"
name = "myvpc"
~ vpc_name = "myvpc" -> "myvpc1"
# (8 unchanged attributes hidden)
}
Plan: 1 to add, 1 to change, 1 to 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
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
# 生命周期之条件检查
- precondition postcondition 条件检查
https://www.terraform.io/language/expressions/custom-conditions
示例
$ cd terraform-extend/lifecycle/create_before_destroy
$ tree ./
./
├── main.tf
└── versions.tf
0 directories, 4 files
$ cat main.tf
provider "alicloud" {
region = "cn-shanghai"
}
locals {
region = "cn-shanghai-a"
# 这里的vsw所在区域为`cn-shanghai-a`
vsw_id = "vsw-uf6ct0jpe5ujmgh7my7np"
secgroup_id = "sg-uf6fy0y9i7j1t4dif549"
instance_name = "myecsserver1"
instance_type = "ecs.sn2ne.large"
}
data "alicloud_images" "images_ds" {
owners = "system"
name_regex = "^centos_7_9"
architecture = "x86_64"
status = "Available"
os_type = "linux"
# output_file = "./outputs.json"
}
# output "image_id" {
# value = data.alicloud_images.images_ds.images[2].id
# }
# 这里新增加了VPC
resource "alicloud_vpc" "vpc" {
vpc_name = "myvpc"
cidr_block = "172.20.0.0/16"
}
resource "alicloud_instance" "myecs2" {
availability_zone = local.region
security_groups = [local.secgroup_id]
instance_type = local.instance_type
system_disk_category = "cloud_efficiency"
system_disk_name = "tf_system_disk_name"
system_disk_description = "tf_system_disk_description"
image_id = data.alicloud_images.images_ds.images[2].id
instance_name = local.instance_name
vswitch_id = local.vsw_id
internet_max_bandwidth_out = 0
internet_charge_type = "PayByTraffic"
password = "root@1234"
lifecycle {
create_before_destroy = true
# prevent_destroy = true
# 检测系统的ami必须包含"x86_64"
precondition {
condition = data.alicloud_images.images_ds.architecture == "x86_64"
error_message = "The selected AMI must be for the x86_64 architecture."
}
# 检测tags中的"env"必须等于"dev"
postcondition {
condition = self.tags["env"] == "dev"
error_message = "tags error!"
}
}
}
# 声明环境变量
export ALICLOUD_ACCESS_KEY="xxxxxx"
export ALICLOUD_SECRET_KEY="xxxxxx"
export ALICLOUD_REGION="cn-shanghai"
export TF_CLI_CONFIG_FILE=/home/terraform/youdianzhishi-terraform/terraform-extend/.terraformrc
# 执行terraform命令
$ terraform init
$ terraform fmt 或 terraform init -recursive
$ terraform validate
$ terraform plan
$ terraform apply 或 terraform apply -auto-approve
# 查看参数是否有问题
$ terraform validate
Success! The configuration is valid.
$ terraform apply
data.alicloud_images.images_ds: Reading...
alicloud_vpc.vpc: Refreshing state... [id=vpc-uf62ypar80mrwhfoxuqw6]
data.alicloud_images.images_ds: Read complete after 1s [id=1253956010]
alicloud_instance.myecs2: Refreshing state... [id=i-uf6c2xw8vbvz167ze6dm]
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
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
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
上次更新: 2024/04/09, 16:48:42
- 01
- AWS NAT-NetWork-Firwalld配置(一)04-09
- 02
- AWS NAT-NetWork-Firwalld配置(二)04-09
- 03
- kubernetes部署minio对象存储01-18