terraform 命令学习

暗香疏影 创作者

基础命令

1
2
3
4
5
6
7
8
9
10
11
#################### Basic ####################
# 在terraform所在文件夹添加provider.tf 例如aliyun后需初始化
terraform init
terraform validate
terraform plan
terraform apply


#################### Import tfstate ####################
# tfstate 是将目前基础设施保存的位置,这样之后再次修改tf文件,会根据tfstate来决定新增,还是修改,或是删除。
terraform import alicloud_instance.example123 i-example-ecs-id

import之前需要确保tf文件已有该实例,例如

1
2
3
4
5
resource "alicloud_instance" "example123" {
availability_zone = "ap-southeast-1b"
deletion_protection = "false"
host_name = "example"
...

你可以多次import多台实例,他们都会保存。如果大量或者全部,需要用terraformer反向将示例生成为tf文件和tfstate。但是反向生成的文件不一定准确,可能需要手动删除一些不需要的。这个可以在terraform validate的时候发现。

terraform TF示例文件

新建实例 - 新VPC 新VSwitch 新安全组

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
# prodiver.tf
provider "alicloud" {
access_key = "xxx"
secret_key = "xxx"
# If not set, cn-beijing will be used.
region = "ap-southeast-1"
}

# main.tf

data "alicloud_zones" "zone_foo" {
available_resource_creation = "Instance"
# get zone and auto availability_zone creation
}

resource "alicloud_vpc" "newvpc" {
vpc_name = "vpc-example"
cidr_block = "172.16.0.0/12"
}

resource "alicloud_vswitch" "newvsw" {
vswitch_name = "vsw-example4"
cidr_block = "172.16.0.0/21"
vpc_id = alicloud_vpc.newvpc.id
zone_id = data.alicloud_zones.zone_foo.zones.0.id
}

resource "alicloud_security_group" "autogengroup" {
name = "example_security_group"
description = "Security group description"
vpc_id = alicloud_vpc.newvpc.id # Replace with your actual VPC ID if needed
}

resource "alicloud_security_group_rule" "allow_3389" {
type = "ingress"
ip_protocol = "tcp"
nic_type = "intranet"
policy = "accept"
port_range = "3389/3389"
priority = 1
security_group_id = alicloud_security_group.autogengroup.id
cidr_ip = "40.25.20.0/24"
}

resource "alicloud_instance" "instance" {
######## availability_zone VPC VSW and Security Group ########
# i.e availability_zone = ap-southeast-1a
availability_zone = data.alicloud_zones.zone_foo.zones.0.id

# vswitch_id = "vsw-xxxx"
vswitch_id = alicloud_vswitch.newvsw.id

# Security group - i.e security_groups = ["sg-xxxx"]
security_groups = alicloud_security_group.autogengroup.*.id

######## Instance Detail ########
instance_type = "ecs.c6.xlarge"
instance_name = "launch-advisor-20240327"

# image_id Example:
# aliyun_3_x64_20G_qboot_alibase_20230727.vhd
# win2016_1607_x64_dtc_en-us_40G_alibase_20240313.vhd
# win2022_21H2_x64_dtc_en-us_40G_alibase_20240313.vhd
# rockylinux_9_3_x64_20G_alibase_20240228.vhd
image_id = "win2022_21H2_x64_dtc_en-us_40G_alibase_20240313.vhd"

# System disk
system_disk_category = "cloud_efficiency"
system_disk_size = 40

# Optional: Data disks
# data_disks {
# name = "data-disk1"
# category = "cloud_efficiency"
# size = 50
# encrypted = false
# delete_with_instance = true
# }

# Internet access configuration
# internet_charge_type = "PayByTraffic"
# internet_charge_type = "PayByBandwidth"
internet_charge_type = "PayByTraffic"
internet_max_bandwidth_out = 100

######### Password or SSH KEY #########
# key_name = "sshkey-name"
password = "GoodJob123" # Using the variable for the password i.e - password = var.windows_password
}

新建实例 - 加入到已有安全组和VSwitch

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

resource "alicloud_instance" "instance" {
######## availability_zone VPC VSW and Security Group ########
# i.e availability_zone = ap-southeast-1a
# availability_zone = "ap-southeast-1a"
# 当vsw存在的情况下,会忽略availability zone
# vswitch_id = "vsw-xxxx"
vswitch_id = "vsw-xxx"

# Security group - i.e security_groups = ["sg-xxxx"]
security_groups = ["sg-xxxx"]

######## Instance Detail ########
instance_type = "ecs.c6.xlarge"
instance_name = "launch-advisor-20240415"

# image_id Example:
# aliyun_3_x64_20G_qboot_alibase_20230727.vhd
# win2016_1607_x64_dtc_en-us_40G_alibase_20240313.vhd
# win2022_21H2_x64_dtc_en-us_40G_alibase_20240313.vhd
# rockylinux_9_3_x64_20G_alibase_20240228.vhd
# Custom Image: m-xxxxxxxxxx
image_id = "win2022_21H2_x64_dtc_en-us_40G_alibase_20240223.vhd"

# System disk
system_disk_category = "cloud_essd"
system_disk_size = 40



# Internet access configuration
# internet_charge_type = "PayByTraffic"
# internet_charge_type = "PayByBandwidth"
internet_charge_type = "PayByTraffic"
internet_max_bandwidth_out = 100

######### Password or SSH KEY #########
# key_name = "sshkey"
password = "examplepw" # Using the variable for the password i.e - password = var.windows_password
}

新建实例 - 从镜像image批量新建实例

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

variable "csvfilename" {
description = "Path to the CSV file"
type = string
default = "ecs-data.csv"
}


locals {
ecs_instances = csvdecode(file(var.csvfilename))
}

resource "alicloud_instance" "ecs" {
for_each = { for ins in local.ecs_instances : ins.uid => ins }

image_id = each.value.imageid
instance_name = each.value.instance_name
instance_type = each.value.spec
vswitch_id = each.value.vswid
security_groups = [each.value.sgid]
description = each.value.description
host_name = each.value.hostname
private_ip = each.value.ip
system_disk_size = each.value.size

# Other configurations like security groups, disks, etc.
system_disk_category = "cloud_essd"

tags = {
Environment = each.value.environment
App = each.value.app
}
# 以下虽然可以加data disk,但是只限于添加image后挂载,不支持image本身带data disk
# add data disk if exist
#data_disks {
# name = "${each.value.hostname}-data-disk"
# category = "cloud_essd"
# size = each.value.data_disk_size # Assuming you have a 'data_disk_size' field in your CSV file
# delete_with_instance = true
#}
}

output "ecs_instance_ids" {
value = { for ins in alicloud_instance.ecs : ins.id => ins.description }
}

ecs-data.csv内容如下:
为什么加uid, 这是为了不使用imageid作为唯一识别符,否则,如果在该tfstate中imageid不存在,则会新建。如果tfstate中imageid存在但csv中不存在则会删除。
如果使用uid的话,则可以直接修改。

uid imageid imageName_no-suffix ip spec vswid instance_name desciption size hostname
1 m-l3vh2q4tz17erf5g1ncd erp-staging-db-10.10.2.1_CYCLE 10.10.2.1 ecs.g6.2xlarge vsw-l3vcaostwue5ovboyyt94 ERP-Staging-DB ERP-Staging-DB 40 erp-staging-db
2 m-l3vh2q4tz17erl5jdt6r erp-staging-web-10.10.1.1_CYCLE 10.10.1.1 ecs.c6.2xlarge vsw-l3vcaostwue5ovboyyt94 ERP-Staging-Web ERP-Staging-Web 40 erp-staging-web
3 m-l3v2t8u8rhdvft6oz2ot erp-prod-db-10.20.2.1_CYCLE 10.20.2.1 ecs.c6.4xlarge vsw-l3vcaostwue5ovboyyt55 ERP-Prod-DB ERP-Prod-DB 40 erp-prod-db
4 m-l3v2sy2o315d0pmgdjm5 erp-prod-web-10.20.1.1_CYCLE 10.20.1.1 ecs.g6.4xlarge vsw-l3vcaostwue5ovboyyt55 ERP-Prod-Web ERP-Prod-Web 50 erp-prod-web

读取CSV并将内容String变成列表(List of String)

我们有的时候遇到他要求是List of String([“aa”,”bb”])
那么我们如何做呢?

我们以修改云防火墙IP拒绝策略为目的,通过将IP加入到Address Book实现。Address Book本身这是一个键,而他的值是一个列表(list)

CSV文件内容就单独一个列即可

1
2
3
4
5
column_name: iplist
10.0.0.1/32
10.0.1.0/24
172.16.5.221/32
...

以下是添加地址簿的方式:

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
variable "csvfilename" {
description = "Path to the CSV file"
type = string
default = "iplist.csv"
}


locals {
iplist = csvdecode(file(var.csvfilename))
}

locals {
listaddress = [ for row in local.iplist : row.iplist]
# row.iplist is the csv file column named "iplist" and we will read each row
}

resource "alicloud_cloud_firewall_address_book" "example" {

description = "IP_Blacklist_Created_by_terraform"
group_name = "Blacklisted IP - terraform"
group_type = "ip"
address_list = local.listaddress
}


想要实现添加互联网防护策略,也就是将地址簿列入拒绝策略可以在下一行添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
resource "alicloud_cloud_firewall_control_policy" "addressbookdeny" {
application_name = "ANY"
acl_action = "drop"
description = "IP_Blacklist_Created_by_terraform"
destination_type = "net"
destination = "0.0.0.0/0"
direction = "in"
proto = "ANY"
source = "Blacklisted IP - terraform"
source_type = "group"

}

output "iplistdisplay" {
value = local.listaddress
}

如果我是直接添加策略使用IP,而非策略里使用地址簿(一系列IP地址),那么应该如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
resource "alicloud_cloud_firewall_control_policy" "iplistdeny" {
for_each = { for policyid in local.iplist : policyid.policyruleid => policyid }
# in csv file create the first column as policyruleid
# 将csv列名为policyruleid作为tfstate的唯一值(policyid), 基于这个进行修改。

application_name = each.value.application_name
acl_action = each.value.acl_action
description = "IP_Blacklist_Created_by_terraform"
destination_type = "net"
destination = "0.0.0.0/0"
direction = "in"
proto = "ANY"
source = each.value.source
source_type = "net"
}

output "iplistdisplay" {
value = { for policyid in local.iplist : policyid.policyruleid => policyid.source }
}

如果我的IP列表本身不包含CIDR,没有/32的话,如何添加呢?
直接在locals 添加结尾为/32

1
2
3
4
5
6
7
8
locals {
listaddress = [ for each_row_in_col in local.iplist : each_row_in_col.iplist ]
# row.iplist is the csv file column named "iplist" and we will read each row

# Add "/32" suffix to each IP address
ip_addresses_with_cidr = [for ip in local.listaddress : "${ip}/32"]

}

Terraformer

https://github.com/GoogleCloudPlatform/terraformer/
将现有基础设施,制作成tf文件以及tfstate
制作之后,请使用terraform validate验证以下语法是否有问题(一般来说有太多多余的参数), 然后将多余不需要的行数批量替换为空即可。

1
2
3
4
terraformer import alicloud --resources=ecs --regions=ap-southeast-1 --profile=default

Note: --profile的值取自aliyun cli
C:\Users\<username>\.aliyun\config.json
  • 标题: terraform 命令学习
  • 作者: 暗香疏影
  • 创建于 : 2024-04-18 00:00:00
  • 更新于 : 2024-07-25 00:00:00
  • 链接: https://blog.23ikr.com/2024/04/18/Wiki-Guide/2024-04-18-terraform/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论