Terraform初体验:配置腾讯云CVM

首先明确目标:学习Terrafom, 并在腾讯云上成功配置一台CVM

安装Terraform

直接去官网Install页面按照指示安装即可

看看是否安装成功

1
2
3
4
5
terraform  -version

# 我的输出
Terraform v1.13.3
on windows_amd64

获取凭证

前往 云 API 密钥页面 申请安全凭证 SecretId 和 SecretKey。

  1. 登录 访问管理控制台,在左侧导航栏,选择访问密钥 > API 密钥管理。
  2. 在 API 密钥管理页面,单击新建密钥,即可以创建一对 SecretId/SecretKey。

可以新建一个子用户然后再来创建API密钥

使用方式主要有两种, 一种是静态凭证鉴权, 直接在配置文件中写入, 另一种是环境变量鉴权, 通过配置环境变量来获取, 为了演示, 我选择静态凭证鉴权

配置Terraform

基本使用文档可以参考官方文档

虽然说所有配置都是可以写在一个main.tf文件中, 但是这不符合最佳实践, 为了方便管理, 官方建议使用多个文件来管理配置, 所以我们创建一个目录来管理我们的配置文件

官方文档中建议的文件命名结构如下:

  1. backend.tf: 定义 Terraform 存储其状态数据文件的位置, 如果不配置, 默认是本地存储

  2. main.tf: 包含所有资源和数据源块, 这也是我们主要配置的部分

  3. outputs.tf: 包含按字母顺序排列的所有输出块, 其实就是资源配置好后可以将一些重要信息输出到这里, 方便后续查看

  4. providers.tf: 所有 provider 块和配置, 这个一般就是各个提供商的配置, 比如我们这里就是腾讯云的配置

  5. terraform.tf: 包含一个定义 required_version 和 required_providers 单个 terraform 块,

  6. variables.tf: 包含按字母顺序排列的所有变量块, 配置一些参数, 不直接写在main.tf中, 而是通过变量来配置

  7. locals.tf: 包含本地值, 其实通俗来说就是别名, 可以将一个复杂的表达式简化为一个别名, 然后直接使用别名即可

  8. override.tf: 包含配置的覆盖定义, 你可以不用修改原文件, 而是用这个文件来覆盖原文件中的配置

如果配置十分复杂, 还可以进一步拆分, 添加比如说: network.tf, storage.tf, compute.tf等来使得配置更加清晰

具体配置

可以参考Terraform上腾讯云的文档

  1. 先配置provider.tf文件
1
2
3
4
5
provider "tencentcloud" {
region = "ap-guangzhou" # 区域, 可以自己配
secret_id = ""
secret_key = ""
}
  1. 然后是terraform.tf文件, 指定provider相关信息
1
2
3
4
5
6
7
8
9
terraform {
required_providers {
tencentcloud = {
source = "tencentcloudstack/tencentcloud"
# 通过version指定版本, 这里我使用最新版本
version = "1.82.29"
}
}
}
  1. main.tf

下面这个是官方文档中创建普通按小时付费云服务器实例的配置

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
variable "availability_zone" {
default = "ap-guangzhou-4"
}

data "tencentcloud_images" "images" {
image_type = ["PUBLIC_IMAGE"]
image_name_regex = "OpenCloudOS Server"
}

data "tencentcloud_instance_types" "types" {
filter {
name = "instance-family"
values = ["S1", "S2", "S3", "S4", "S5"]
}

cpu_core_count = 2
exclude_sold_out = true
}

// create vpc
resource "tencentcloud_vpc" "vpc" {
cidr_block = "10.0.0.0/16"
name = "vpc"
}

// create subnet
resource "tencentcloud_subnet" "subnet" {
vpc_id = tencentcloud_vpc.vpc.id
availability_zone = var.availability_zone
name = "subnet"
cidr_block = "10.0.1.0/24"
}

// create CVM instance
resource "tencentcloud_instance" "example" {
instance_name = "tf-example"
availability_zone = var.availability_zone
image_id = data.tencentcloud_images.images.images.0.image_id
instance_type = data.tencentcloud_instance_types.types.instance_types.0.instance_type
system_disk_type = "CLOUD_PREMIUM"
system_disk_size = 50
hostname = "user"
project_id = 0
vpc_id = tencentcloud_vpc.vpc.id
subnet_id = tencentcloud_subnet.subnet.id

data_disks {
data_disk_type = "CLOUD_PREMIUM"
data_disk_size = 50
encrypt = false
}

tags = {
tagKey = "tagValue"
}
}

我们可以根据这个配置根据最佳实践来进行修改, 下面是我的配置:

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
128
129
130
131
132
133
134
135
136
137
138
139
140

data "tencentcloud_images" "ubuntu_image" {
image_type = ["PUBLIC_IMAGE"]
image_name_regex = "Ubuntu Server 22.04"
}

data "tencentcloud_instance_types" "instance_type_s5" {
filter {
name = "instance-family"
values = ["S5"]
}
cpu_core_count = var.instance_cpu_cores # 引用变量
memory_size = var.instance_memory_size # 引用变量
exclude_sold_out = true
}


# --- 网络资源 ---
resource "tencentcloud_vpc" "vpc" {
name = "${local.project_prefix}-vpc" # 使用 local 变量
cidr_block = "10.0.0.0/16"
tags = local.common_tags # 使用 local 变量
}

resource "tencentcloud_subnet" "subnet" {
vpc_id = tencentcloud_vpc.vpc.id
name = "${local.project_prefix}-subnet" # 使用 local 变量
cidr_block = "10.0.1.0/24"
availability_zone = var.availability_zone
tags = local.common_tags # 使用 local 变量
}


# --- 安全组资源
resource "tencentcloud_security_group" "base" {
name = "${local.project_prefix}-sg" # Using local for consistency
description = "Primary Security Group for VM"
tags = local.common_tags
}

resource "tencentcloud_security_group" "relative" {
name = "${local.project_prefix}-sg-relative" # Using local for consistency
description = "Used for attach security policy"
tags = local.common_tags
}

resource "tencentcloud_address_template" "foo" {
name = "${local.project_prefix}-address-template" # Using local for consistency
addresses = ["10.0.0.1", "10.0.1.0/24", "10.0.0.1-10.0.0.100"]
}

resource "tencentcloud_address_template_group" "foo" {
name = "${local.project_prefix}-address-template-group" # Using local for consistency
template_ids = [tencentcloud_address_template.foo.id]
}

resource "tencentcloud_security_group_rule_set" "base_rules" {
security_group_id = tencentcloud_security_group.base.id

ingress {
action = "ACCEPT"
cidr_block = "10.0.0.0/22"
protocol = "TCP"
port = "80-90"
description = "A:Allow Ips and 80-90"
}

ingress {
action = "ACCEPT"
cidr_block = "10.0.2.1"
protocol = "UDP"
port = "8080"
description = "B:Allow UDP 8080"
}

ingress {
action = "ACCEPT"
cidr_block = "10.0.2.1"
protocol = "UDP"
port = "8080"
description = "C:Allow UDP 8080"
}

ingress {
action = "ACCEPT"
cidr_block = "172.18.1.2"
protocol = "ALL"
port = "ALL"
description = "D:Allow ALL"
}

ingress {
action = "DROP"
protocol = "TCP"
port = "80"
source_security_id = tencentcloud_security_group.relative.id
description = "E:Block relative"
}

egress {
action = "DROP"
cidr_block = "10.0.0.0/16"
protocol = "ICMP"
description = "A:Block ping3"
}

egress {
action = "DROP"
address_template_id = tencentcloud_address_template.foo.id
description = "B:Allow template"
}

egress {
action = "DROP"
address_template_group = tencentcloud_address_template_group.foo.id
description = "C:DROP template group"
}
}


# --- CVM 实例资源 ---
resource "tencentcloud_instance" "my-vm" {
instance_name = "${local.project_prefix}-vm" # 使用 local 变量
availability_zone = var.availability_zone
image_id = data.tencentcloud_images.ubuntu_image.images.0.image_id
instance_type = data.tencentcloud_instance_types.instance_type_s5.instance_types.0.instance_type
system_disk_type = "CLOUD_PREMIUM"
system_disk_size = 50

password = var.instance_password # 引用变量
allocate_public_ip = true
orderly_security_groups = [tencentcloud_security_group.base.id]

vpc_id = tencentcloud_vpc.vpc.id
subnet_id = tencentcloud_subnet.subnet.id
instance_charge_type = "POSTPAID_BY_HOUR"

tags = local.common_tags # 使用 local 变量
}

  1. variables.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
variable "availability_zone" {
type = string
description = "创建资源的目标可用区"
default = "ap-guangzhou-4"
}

variable "instance_password" {
type = string
description = "设置云服务器的登录密码"
sensitive = true # Terraform 在输出 plan 或 apply 结果时会隐藏具体的值
default = "TencentCloud123!"
}

variable "instance_cpu_cores" {
type = number
description = "服务器的 CPU 核心数"
default = 2
}

variable "instance_memory_size" {
type = number
description = "服务器的内存大小 (GB)"
default = 2
}
  1. outputs.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
output "instance_public_ip" {
description = "云服务器的公网 IP 地址"
value = tencentcloud_instance.my-vm.public_ip
}

output "vpc_id" {
description = "创建的 VPC 的 ID"
value = tencentcloud_vpc.vpc.id
}

output "security_group_id" {
description = "为服务器创建的安全组 ID"
value = tencentcloud_security_group.base.id
}
  1. locals.tf
1
2
3
4
5
6
7
8
9
10
locals {
# 统一的资源名前缀,方便识别和管理
project_prefix = "tf-txy-demo"

# 统一的标签,会自动应用到所有支持标签的资源上
common_tags = {
Owner = "Levitate Gu"
CreatedBy = "Terraform"
}
}

创建

  1. 初始化 Terraform

在配置文件的目录下执行以下命令来初始化 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
terraform init


# 输出为:
Initializing the backend...
Initializing provider plugins...
- Finding tencentcloudstack/tencentcloud versions matching "1.82.29"...
- Installing tencentcloudstack/tencentcloud v1.82.29...
- Installed tencentcloudstack/tencentcloud v1.82.29 (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://developer.hashicorp.com/terraform/cli/plugins/signing
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. 查看执行计划
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
terraform plan

# 输出为:
data.tencentcloud_images.ubuntu_image: Reading...
data.tencentcloud_instance_types.instance_type_s5: Reading...
data.tencentcloud_images.ubuntu_image: Read complete after 1s [id=2198502367]
data.tencentcloud_instance_types.instance_type_s5: Read complete after 1s [id=3046689892]

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_address_template.foo will be created
+ resource "tencentcloud_address_template" "foo" {
+ addresses = [
+ "10.0.0.1",
+ "10.0.0.1-10.0.0.100",
+ "10.0.1.0/24",
]
+ id = (known after apply)
+ name = "tf-txy-demo-address-template"
}

# tencentcloud_address_template_group.foo will be created
+ resource "tencentcloud_address_template_group" "foo" {
+ id = (known after apply)
+ name = "tf-txy-demo-address-template-group"
+ template_ids = (known after apply)
}

# tencentcloud_instance.my-vm will be created
+ resource "tencentcloud_instance" "my-vm" {
+ allocate_public_ip = true
+ anti_ddos_package_id = (known after apply)
+ availability_zone = "ap-guangzhou-4"
+ cam_role_name = (known after apply)
+ cdh_host_id = (known after apply)
+ cdh_instance_type = (known after apply)
+ cpu = (known after apply)
+ create_time = (known after apply)
+ disable_api_termination = (known after apply)
+ disable_automation_service = false
+ disable_monitor_service = false
+ disable_security_service = false
+ expired_time = (known after apply)
+ force_delete = false
+ hostname = (known after apply)
+ hpc_cluster_id = (known after apply)
+ id = (known after apply)
+ image_id = "img-487zeit5"
+ instance_charge_type = "POSTPAID_BY_HOUR"
+ instance_charge_type_prepaid_renew_flag = (known after apply)
+ instance_name = "tf-txy-demo-vm"
+ instance_status = (known after apply)
+ instance_type = "S5.MEDIUM2"
+ internet_charge_type = (known after apply)
+ internet_max_bandwidth_out = (known after apply)
+ ipv4_address_type = (known after apply)
+ ipv6_address_count = (known after apply)
+ ipv6_address_type = (known after apply)
+ ipv6_addresses = (known after apply)
+ keep_image_login = (known after apply)
+ key_ids = (known after apply)
+ key_name = (known after apply)
+ memory = (known after apply)
+ orderly_security_groups = (known after apply)
+ os_name = (known after apply)
+ password = (sensitive value)
+ placement_group_id = (known after apply)
+ private_ip = (known after apply)
+ project_id = (known after apply)
+ public_ip = (known after apply)
+ public_ipv6_addresses = (known after apply)
+ running_flag = (known after apply)
+ security_groups = (known after apply)
+ subnet_id = (known after apply)
+ system_disk_id = (known after apply)
+ system_disk_name = (known after apply)
+ system_disk_size = 50
+ system_disk_type = "CLOUD_PREMIUM"
+ tags = {
+ "CreatedBy" = "Terraform"
+ "Owner" = "Levitate Gu"
}
+ user_data = (known after apply)
+ user_data_raw = (known after apply)
+ user_data_replace_on_change = false
+ uuid = (known after apply)
+ vpc_id = (known after apply)

+ data_disks (known after apply)
}

# tencentcloud_security_group.base will be created
+ resource "tencentcloud_security_group" "base" {
+ description = "Primary Security Group for VM"
+ id = (known after apply)
+ name = "tf-txy-demo-sg"
+ project_id = (known after apply)
+ tags = {
+ "CreatedBy" = "Terraform"
+ "Owner" = "Levitate Gu"
}
}

# tencentcloud_security_group.relative will be created
+ resource "tencentcloud_security_group" "relative" {
+ description = "Used for attach security policy"
+ id = (known after apply)
+ name = "tf-txy-demo-sg-relative"
+ project_id = (known after apply)
+ tags = {
+ "CreatedBy" = "Terraform"
+ "Owner" = "Levitate Gu"
}
}

# tencentcloud_security_group_rule_set.base_rules will be created
+ resource "tencentcloud_security_group_rule_set" "base_rules" {
+ id = (known after apply)
+ security_group_id = (known after apply)
+ version = (known after apply)

+ egress {
+ action = "DROP"
+ cidr_block = "10.0.0.0/16"
+ description = "A:Block ping3"
+ policy_index = (known after apply)
+ port = (known after apply)
+ protocol = "ICMP"
}
+ egress {
+ action = "DROP"
+ address_template_id = (known after apply)
+ description = "B:Allow template"
+ policy_index = (known after apply)
+ port = (known after apply)
+ protocol = (known after apply)
}
+ egress {
+ action = "DROP"
+ address_template_group = (known after apply)
+ description = "C:DROP template group"
+ policy_index = (known after apply)
+ port = (known after apply)
+ protocol = (known after apply)
}

+ ingress {
+ action = "ACCEPT"
+ cidr_block = "10.0.0.0/22"
+ description = "A:Allow Ips and 80-90"
+ policy_index = (known after apply)
+ port = "80-90"
+ protocol = "TCP"
}
+ ingress {
+ action = "ACCEPT"
+ cidr_block = "10.0.2.1"
+ description = "B:Allow UDP 8080"
+ policy_index = (known after apply)
+ port = "8080"
+ protocol = "UDP"
}
+ ingress {
+ action = "ACCEPT"
+ cidr_block = "10.0.2.1"
+ description = "C:Allow UDP 8080"
+ policy_index = (known after apply)
+ port = "8080"
+ protocol = "UDP"
}
+ ingress {
+ action = "ACCEPT"
+ cidr_block = "172.18.1.2"
+ description = "D:Allow ALL"
+ policy_index = (known after apply)
+ port = "ALL"
+ protocol = "ALL"
}
+ ingress {
+ action = "DROP"
+ description = "E:Block relative"
+ policy_index = (known after apply)
+ port = "80"
+ protocol = "TCP"
+ source_security_id = (known after apply)
}
}

# tencentcloud_subnet.subnet will be created
+ resource "tencentcloud_subnet" "subnet" {
+ availability_zone = "ap-guangzhou-4"
+ available_ip_count = (known after apply)
+ cidr_block = "10.0.1.0/24"
+ create_time = (known after apply)
+ id = (known after apply)
+ is_default = (known after apply)
+ is_multicast = true
+ name = "tf-txy-demo-subnet"
+ route_table_id = (known after apply)
+ tags = {
+ "CreatedBy" = "Terraform"
+ "Owner" = "Levitate Gu"
}
+ vpc_id = (known after apply)
}

# tencentcloud_vpc.vpc will be created
+ resource "tencentcloud_vpc" "vpc" {
+ assistant_cidrs = (known after apply)
+ cidr_block = "10.0.0.0/16"
+ create_time = (known after apply)
+ default_route_table_id = (known after apply)
+ dns_servers = (known after apply)
+ docker_assistant_cidrs = (known after apply)
+ id = (known after apply)
+ is_default = (known after apply)
+ is_multicast = true
+ name = "tf-txy-demo-vpc"
+ tags = {
+ "CreatedBy" = "Terraform"
+ "Owner" = "Levitate Gu"
}
}

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

Changes to Outputs:
+ instance_public_ip = (known after apply)
+ security_group_id = (known after apply)
+ vpc_id = (known after apply)

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

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if
you run "terraform apply" now.
  1. 创建资源
1
terraform apply

遇到问题了:

1
2
3
4
5
6
7
8

│ Error: [TencentCloudSDKError] Code=InvalidZone.MismatchRegion, Message=The specified zone ID `ap-guangzhou-4` does not match the region `ap-guangzhou`, RequestId=2a9433d0-a4c4-45cb-ac5a-161108dba7e6

│ with tencentcloud_instance.my-vm,
│ on main.tf line 121, in resource "tencentcloud_instance" "my-vm":
│ 121: resource "tencentcloud_instance" "my-vm" {


很诡异,我指定的zone是ap-guangzhou-4,但是报错说region和zone不匹配,我明明指定了region是ap-guangzhou啊,这是怎么回事呢? 我去腾讯云看了看, 应该是指定的zone没有我要的配置, 我们将zone改为ap-guangzhou-6,配置改为2c4g再尝试一下

1
2
3
terraform init
terraform plan
terraform apply

再次遇到问题了:

1
2
3
4
5
6
7
8

│ Error: [TencentCloudSDKError] Code=InvalidParameterCombination, Message=The combination of parameters between .InternetAccessible.PublicIpAssigned and InternetMaxBandwidthOut is incorrect, RequestId=878c5e48-57db-4991-849f-3fe2a5be502d

│ with tencentcloud_instance.my-vm,
│ on main.tf line 121, in resource "tencentcloud_instance" "my-vm":
│ 121: resource "tencentcloud_instance" "my-vm" {


小问题, 没有配置带宽, 配个3M, 再试一次

1
2
3
terraform init
terraform plan
terraform apply

终于成功了, 如图:

avatar

看看输出:

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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
data.tencentcloud_images.ubuntu_image: Reading...
data.tencentcloud_instance_types.instance_type_s5: Reading...
data.tencentcloud_images.ubuntu_image: Read complete after 1s [id=2198502367]
data.tencentcloud_instance_types.instance_type_s5: Read complete after 1s [id=3086429807]

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_address_template.foo will be created
+ resource "tencentcloud_address_template" "foo" {
+ addresses = [
+ "10.0.0.1",
+ "10.0.0.1-10.0.0.100",
+ "10.0.1.0/24",
]
+ id = (known after apply)
+ name = "tf-txy-demo-address-template"
}

# tencentcloud_address_template_group.foo will be created
+ resource "tencentcloud_address_template_group" "foo" {
+ id = (known after apply)
+ name = "tf-txy-demo-address-template-group"
+ template_ids = (known after apply)
}

# tencentcloud_instance.my-vm will be created
+ resource "tencentcloud_instance" "my-vm" {
+ allocate_public_ip = true
+ anti_ddos_package_id = (known after apply)
+ availability_zone = "ap-guangzhou-6"
+ cam_role_name = (known after apply)
+ cdh_host_id = (known after apply)
+ cdh_instance_type = (known after apply)
+ cpu = (known after apply)
+ create_time = (known after apply)
+ disable_api_termination = (known after apply)
+ disable_automation_service = false
+ disable_monitor_service = false
+ disable_security_service = false
+ expired_time = (known after apply)
+ force_delete = false
+ hostname = (known after apply)
+ hpc_cluster_id = (known after apply)
+ id = (known after apply)
+ image_id = "img-487zeit5"
+ instance_charge_type = "POSTPAID_BY_HOUR"
+ instance_charge_type_prepaid_renew_flag = (known after apply)
+ instance_name = "tf-txy-demo-vm"
+ instance_status = (known after apply)
+ instance_type = "S5.MEDIUM4"
+ internet_charge_type = (known after apply)
+ internet_max_bandwidth_out = 3
+ ipv4_address_type = (known after apply)
+ ipv6_address_count = (known after apply)
+ ipv6_address_type = (known after apply)
+ ipv6_addresses = (known after apply)
+ keep_image_login = (known after apply)
+ key_ids = (known after apply)
+ key_name = (known after apply)
+ memory = (known after apply)
+ orderly_security_groups = (known after apply)
+ os_name = (known after apply)
+ password = (sensitive value)
+ placement_group_id = (known after apply)
+ private_ip = (known after apply)
+ project_id = (known after apply)
+ public_ip = (known after apply)
+ public_ipv6_addresses = (known after apply)
+ running_flag = (known after apply)
+ security_groups = (known after apply)
+ subnet_id = (known after apply)
+ system_disk_id = (known after apply)
+ system_disk_name = (known after apply)
+ system_disk_size = 50
+ system_disk_type = "CLOUD_PREMIUM"
+ tags = {
+ "CreatedBy" = "Terraform"
+ "Owner" = "Levitate Gu"
}
+ user_data = (known after apply)
+ user_data_raw = (known after apply)
+ user_data_replace_on_change = false
+ uuid = (known after apply)
+ vpc_id = (known after apply)

+ data_disks (known after apply)
}

# tencentcloud_security_group.base will be created
+ resource "tencentcloud_security_group" "base" {
+ description = "Primary Security Group for VM"
+ id = (known after apply)
+ name = "tf-txy-demo-sg"
+ project_id = (known after apply)
+ tags = {
+ "CreatedBy" = "Terraform"
+ "Owner" = "Levitate Gu"
}
}

# tencentcloud_security_group.relative will be created
+ resource "tencentcloud_security_group" "relative" {
+ description = "Used for attach security policy"
+ id = (known after apply)
+ name = "tf-txy-demo-sg-relative"
+ project_id = (known after apply)
+ tags = {
+ "CreatedBy" = "Terraform"
+ "Owner" = "Levitate Gu"
}
}

# tencentcloud_security_group_rule_set.base_rules will be created
+ resource "tencentcloud_security_group_rule_set" "base_rules" {
+ id = (known after apply)
+ security_group_id = (known after apply)
+ version = (known after apply)

+ egress {
+ action = "DROP"
+ cidr_block = "10.0.0.0/16"
+ description = "A:Block ping3"
+ policy_index = (known after apply)
+ port = (known after apply)
+ protocol = "ICMP"
}
+ egress {
+ action = "DROP"
+ address_template_id = (known after apply)
+ description = "B:Allow template"
+ policy_index = (known after apply)
+ port = (known after apply)
+ protocol = (known after apply)
}
+ egress {
+ action = "DROP"
+ address_template_group = (known after apply)
+ description = "C:DROP template group"
+ policy_index = (known after apply)
+ port = (known after apply)
+ protocol = (known after apply)
}

+ ingress {
+ action = "ACCEPT"
+ cidr_block = "10.0.0.0/22"
+ description = "A:Allow Ips and 80-90"
+ policy_index = (known after apply)
+ port = "80-90"
+ protocol = "TCP"
}
+ ingress {
+ action = "ACCEPT"
+ cidr_block = "10.0.2.1"
+ description = "B:Allow UDP 8080"
+ policy_index = (known after apply)
+ port = "8080"
+ protocol = "UDP"
}
+ ingress {
+ action = "ACCEPT"
+ cidr_block = "10.0.2.1"
+ description = "C:Allow UDP 8080"
+ policy_index = (known after apply)
+ port = "8080"
+ protocol = "UDP"
}
+ ingress {
+ action = "ACCEPT"
+ cidr_block = "172.18.1.2"
+ description = "D:Allow ALL"
+ policy_index = (known after apply)
+ port = "ALL"
+ protocol = "ALL"
}
+ ingress {
+ action = "DROP"
+ description = "E:Block relative"
+ policy_index = (known after apply)
+ port = "80"
+ protocol = "TCP"
+ source_security_id = (known after apply)
}
}

# tencentcloud_subnet.subnet will be created
+ resource "tencentcloud_subnet" "subnet" {
+ availability_zone = "ap-guangzhou-6"
+ available_ip_count = (known after apply)
+ cidr_block = "10.0.1.0/24"
+ create_time = (known after apply)
+ id = (known after apply)
+ is_default = (known after apply)
+ is_multicast = true
+ name = "tf-txy-demo-subnet"
+ route_table_id = (known after apply)
+ tags = {
+ "CreatedBy" = "Terraform"
+ "Owner" = "Levitate Gu"
}
+ vpc_id = (known after apply)
}

# tencentcloud_vpc.vpc will be created
+ resource "tencentcloud_vpc" "vpc" {
+ assistant_cidrs = (known after apply)
+ cidr_block = "10.0.0.0/16"
+ create_time = (known after apply)
+ default_route_table_id = (known after apply)
+ dns_servers = (known after apply)
+ docker_assistant_cidrs = (known after apply)
+ id = (known after apply)
+ is_default = (known after apply)
+ is_multicast = true
+ name = "tf-txy-demo-vpc"
+ tags = {
+ "CreatedBy" = "Terraform"
+ "Owner" = "Levitate Gu"
}
}

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

Changes to Outputs:
+ instance_public_ip = (known after apply)
+ security_group_id = (known after apply)
+ vpc_id = (known after 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

tencentcloud_address_template.foo: Creating...
tencentcloud_security_group.base: Creating...
tencentcloud_security_group.relative: Creating...
tencentcloud_vpc.vpc: Creating...
tencentcloud_address_template.foo: Creation complete after 1s [id=ipm-6p8sfzfi]
tencentcloud_address_template_group.foo: Creating...
tencentcloud_security_group.relative: Creation complete after 1s [id=sg-e1teftjb]
tencentcloud_security_group.base: Creation complete after 2s [id=sg-ndwv7fgr]
tencentcloud_address_template_group.foo: Creation complete after 1s [id=ipmg-qcb8g30y]
tencentcloud_security_group_rule_set.base_rules: Creating...
tencentcloud_security_group_rule_set.base_rules: Creation complete after 1s [id=sg-ndwv7fgr]
tencentcloud_vpc.vpc: Creation complete after 6s [id=vpc-5gizonzh]
tencentcloud_subnet.subnet: Creating...
tencentcloud_subnet.subnet: Creation complete after 2s [id=subnet-ccj458ri]
tencentcloud_instance.my-vm: Creating...
tencentcloud_instance.my-vm: Still creating... [00m10s elapsed]
tencentcloud_instance.my-vm: Still creating... [00m20s elapsed]
tencentcloud_instance.my-vm: Still creating... [00m30s elapsed]
tencentcloud_instance.my-vm: Creation complete after 36s [id=ins-acqkdsjw]

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

Outputs:

instance_public_ip = "119.29.93.145"
security_group_id = "sg-ndwv7fgr"
vpc_id = "vpc-5gizonzh"

修改后的main.tf文件如下:

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
128
129
130
131
132
133
134
135
136
137
138
139
data "tencentcloud_images" "ubuntu_image" {
image_type = ["PUBLIC_IMAGE"]
image_name_regex = "Ubuntu Server 22.04"
}

data "tencentcloud_instance_types" "instance_type_s5" {
filter {
name = "instance-family"
values = ["S5"]
}
cpu_core_count = var.instance_cpu_cores # 引用变量
memory_size = var.instance_memory_size # 引用变量
exclude_sold_out = true
}


# --- 网络资源 ---
resource "tencentcloud_vpc" "vpc" {
name = "${local.project_prefix}-vpc" # 使用 local 变量
cidr_block = "10.0.0.0/16"
tags = local.common_tags # 使用 local 变量
}

resource "tencentcloud_subnet" "subnet" {
vpc_id = tencentcloud_vpc.vpc.id
name = "${local.project_prefix}-subnet" # 使用 local 变量
cidr_block = "10.0.1.0/24"
availability_zone = var.availability_zone
tags = local.common_tags # 使用 local 变量
}


# --- 安全组资源
resource "tencentcloud_security_group" "base" {
name = "${local.project_prefix}-sg" # Using local for consistency
description = "Primary Security Group for VM"
tags = local.common_tags
}

resource "tencentcloud_security_group" "relative" {
name = "${local.project_prefix}-sg-relative" # Using local for consistency
description = "Used for attach security policy"
tags = local.common_tags
}

resource "tencentcloud_address_template" "foo" {
name = "${local.project_prefix}-address-template" # Using local for consistency
addresses = ["10.0.0.1", "10.0.1.0/24", "10.0.0.1-10.0.0.100"]
}

resource "tencentcloud_address_template_group" "foo" {
name = "${local.project_prefix}-address-template-group" # Using local for consistency
template_ids = [tencentcloud_address_template.foo.id]
}

resource "tencentcloud_security_group_rule_set" "base_rules" {
security_group_id = tencentcloud_security_group.base.id

ingress {
action = "ACCEPT"
cidr_block = "10.0.0.0/22"
protocol = "TCP"
port = "80-90"
description = "A:Allow Ips and 80-90"
}

ingress {
action = "ACCEPT"
cidr_block = "10.0.2.1"
protocol = "UDP"
port = "8080"
description = "B:Allow UDP 8080"
}

ingress {
action = "ACCEPT"
cidr_block = "10.0.2.1"
protocol = "UDP"
port = "8080"
description = "C:Allow UDP 8080"
}

ingress {
action = "ACCEPT"
cidr_block = "172.18.1.2"
protocol = "ALL"
port = "ALL"
description = "D:Allow ALL"
}

ingress {
action = "DROP"
protocol = "TCP"
port = "80"
source_security_id = tencentcloud_security_group.relative.id
description = "E:Block relative"
}

egress {
action = "DROP"
cidr_block = "10.0.0.0/16"
protocol = "ICMP"
description = "A:Block ping3"
}

egress {
action = "DROP"
address_template_id = tencentcloud_address_template.foo.id
description = "B:Allow template"
}

egress {
action = "DROP"
address_template_group = tencentcloud_address_template_group.foo.id
description = "C:DROP template group"
}
}


# --- CVM 实例资源 ---
resource "tencentcloud_instance" "my-vm" {
instance_name = "${local.project_prefix}-vm" # 使用 local 变量
availability_zone = var.availability_zone
image_id = data.tencentcloud_images.ubuntu_image.images.0.image_id
instance_type = data.tencentcloud_instance_types.instance_type_s5.instance_types.0.instance_type
system_disk_type = "CLOUD_PREMIUM"
system_disk_size = 50

password = var.instance_password # 引用变量
allocate_public_ip = true
internet_max_bandwidth_out = 3 # 带宽大小
orderly_security_groups = [tencentcloud_security_group.base.id]

vpc_id = tencentcloud_vpc.vpc.id
subnet_id = tencentcloud_subnet.subnet.id
instance_charge_type = "POSTPAID_BY_HOUR"

tags = local.common_tags # 使用 local 变量
}
  1. 销毁
1
terraform destroy

最后花费0元🥰

avatar

总结一下, 其实配置这个最重要的是想清楚你需要什么配置, 然后去官网找到对应配置的文档, 在根据具体需求去修改即可