terraform实践

简介

实现基础设施即代码的工具。方便多云环境重复部署。

安装

下载cli https://www.terraform.io/downloads

1
2
3
$ terraform -version
Terraform v1.2.8
on windows_amd64

初始化

配置阿里云Provider

main.tf

1
2
3
4
5
provider "alicloud" {
access_key = var.ali_access_key
secret_key = var.ali_secret_key
region = var.ali_region
}

var.tf

1
2
3
4
5
6
7
8
9
variable "ali_access_key" {
type = string
}
variable "ali_secret_key" {
type = string
}
variable "ali_region" {
type = string
}

可以使用env设置key

set TF_VAR_ali_access_key=xxx

set TF_VAR_ali_secret_key=xxx

set TF_VAR_ali_region=cn-hangzhou

versions.tf

1
2
3
4
5
6
7
8
9
terraform {
required_version = "1.2.8"
required_providers {
alicloud = {
source = "aliyun/alicloud"
version = "1.184.0"
}
}
}
1
2
3
$ terraform init
#这个很考虑网络,win如果开了代理,必须在cmd设置代理
set http_proxy=http://127.0.0.1:20005 & set https_proxy=http://127.0.0.1:20005

image-20220908112340945

离线init设置

https://github.com/aliyun/terraform-provider-alicloud/releases

https://www.terraform.io/cli/config/config-file#implied-local-mirror-directories

https://ghproxy.com/https://github.com/aliyun/terraform-provider-alicloud/releases/download/v1.184.0/terraform-provider-alicloud_1.184.0_windows_amd64.zip

官网有说本地位置,但没有具体目录结构

1
2
3
4
5
6
7
8
9
D:\Github\terraform> terraform init --plugin-dir D:\Github\terraform\cache
D:\Github\terraform> tree /f cache
D:\GITHUB\TERRAFORM\CACHE
└─registry.terraform.io
└─aliyun
└─alicloud
└─1.184.0
└─windows_amd64
terraform-provider-alicloud_v1.184.0.exe

本地cli配置文件https://www.terraform.io/cli/config/environment-variables#tf_cli_config_file

1
2
3
4
set TF_CLI_CONFIG_FILE=./.terraformrc
cat .terraformrc
plugin_cache_dir = "D:/Github/terraform/cache"
disable_checkpoint = true

定义阿里云资源

vpc.tf

1
2
3
4
5
6
7
8
9
10
resource "alicloud_vpc" "vpc_t1" {
vpc_name = "tf_test_foo"
description = "TF测试"
cidr_block = "172.16.0.0/12"
}
resource "alicloud_vswitch" "vsw" {
vpc_id = alicloud_vpc.vpc_t1.id
cidr_block = "172.16.0.0/21"
zone_id = var.ali_region_zone
}

security_group.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
resource "alicloud_security_group" "security_group1" {
name = "terraform-test-group"
description = "新安全组"
vpc_id = alicloud_vpc.vpc_t1.id
}
resource "alicloud_security_group_rule" "allow_8080_tcp" {
type = "ingress"
ip_protocol = "tcp"
nic_type = "intranet"
policy = "accept"
port_range = "8080/8080"
priority = 1
security_group_id = alicloud_security_group.security_group1.id
cidr_ip = "0.0.0.0/0"
description = "测试规则"
}
resource "alicloud_security_group_rule" "allow_9090_tcp" {
type = "ingress"
ip_protocol = "tcp"
nic_type = "intranet"
policy = "accept"
port_range = "9090/9090"
priority = 1
security_group_id = alicloud_security_group.security_group1.id
cidr_ip = "0.0.0.0/0"
description = "测试规则2"
}

申请阿里云资源

格式化配置文件

1
2
3
D:\Github\terraform\ali> terraform fmt
versions.tf
vpc.tf

语法验证

1
2
3
4
5
6
7
8
D:\Github\terraform\ali>terraform validate -json 
{
"format_version": "1.0",
"valid": true,
"error_count": 0,
"warning_count": 0,
"diagnostics": []
}

打印计划和预览(不执行变更)

image-20220908121134079

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
D:\Github\terraform\ali>terraform plan  # -auto-approve

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:

# alicloud_security_group.security_group1 will be created
+ resource "alicloud_security_group" "security_group1" {
+ description = "New security group"
+ id = (known after apply)
+ inner_access = (known after apply)
+ inner_access_policy = (known after apply)
+ name = "terraform-test-group"
+ security_group_type = "normal"
}

# alicloud_security_group_rule.allow_8080_tcp will be created
+ resource "alicloud_security_group_rule" "allow_8080_tcp" {
+ cidr_ip = "0.0.0.0/0"
+ description = "测试规则"
+ id = (known after apply)
+ ip_protocol = "tcp"
+ nic_type = "internet"
+ policy = "accept"
+ port_range = "8080/8080"
+ prefix_list_id = (known after apply)
+ priority = 1
+ security_group_id = (known after apply)
+ type = "ingress"
}

# alicloud_security_group_rule.allow_9090_tcp will be created
+ resource "alicloud_security_group_rule" "allow_9090_tcp" {
+ cidr_ip = "0.0.0.0/0"
+ description = "测试规则2"
+ id = (known after apply)
+ ip_protocol = "tcp"
+ nic_type = "internet"
+ policy = "accept"
+ port_range = "9090/9090"
+ prefix_list_id = (known after apply)
+ priority = 1
+ security_group_id = (known after apply)
+ type = "ingress"
}

# alicloud_vpc.vpc_t1 will be created
+ resource "alicloud_vpc" "vpc_t1" {
+ cidr_block = "172.16.0.0/12"
+ description = "TF测试"
+ id = (known after apply)
+ ipv6_cidr_block = (known after apply)
+ name = (known after apply)
+ resource_group_id = (known after apply)
+ route_table_id = (known after apply)
+ router_id = (known after apply)
+ router_table_id = (known after apply)
+ status = (known after apply)
+ vpc_name = "tf_test_foo"
}

# alicloud_vswitch.vsw will be created
+ resource "alicloud_vswitch" "vsw" {
+ availability_zone = (known after apply)
+ cidr_block = "172.16.0.0/21"
+ id = (known after apply)
+ name = (known after apply)
+ status = (known after apply)
+ vpc_id = (known after apply)
+ vswitch_name = (known after apply)
+ zone_id = "cn-hangzhou-b"
}

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

申请资源

1
2
3
4
5
6
7
8
9
10
11
12
D:\Github\terraform\ali>terraform apply -auto-approve #加参数可以不用输入yes
alicloud_vpc.vpc_t1: Refreshing state... [id=vpc-bp1d0s12fw8tx8wlmydrp]
alicloud_security_group.security_group1: Refreshing state... [id=sg-bp1exvm2rcbjgfao8zmn]
alicloud_vswitch.vsw: Refreshing state... [id=vsw-bp1x3z6zfzwjimuymsxrk]
alicloud_security_group_rule.allow_8080_tcp: Refreshing state... [id=sg-bp1exvm2rcbjgfao8zmn:ingress:tcp:8080/8080:intranet:0.0.0.0/0:accept:1]
alicloud_security_group_rule.allow_9090_tcp: Refreshing state... [id=sg-bp1exvm2rcbjgfao8zmn:ingress:tcp:9090/9090:intranet:0.0.0.0/0:accept:1]

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
D:\Github\terraform\ali>terraform destroy

语法

1
2
3
4
5
6
7
8
9
10
11
terraform {
required_version = "1.2.8"
required_providers {
alicloud = {
# 源
source = "aliyun/alicloud"
# 版本
version = "1.184.0"
}
}
}

provider

1
2
3
4
5
6
7
8
9
10
11
provider "alicloud" { #必须有个默认的
access_key = var.ali_access_key
secret_key = var.ali_secret_key
region = "cn-hangzhou"
}
provider "alicloud" {
alias = "ali_beijin"
access_key = var.ali_access_key
secret_key = var.ali_secret_key
region = "cn-beijing"
}

dns

1
2
3
4
5
6
resource "alicloud_dns_record" "test1" {
name = "xxx.com"
host_record = "test1"
type = "A"
value = "1.1.1.1"
}

DataSource

dns

1
2
3
4
5
data "alicloud_alidns_records" "records_ds" {
domain_name = "xxxxxx.com"
output_file = "records.json"
}
#执行plan会生成文件

使用值

1
2
3
4
5
6
7
8
9
10
11
12
output "first_record_id" {
value = data.alicloud_alidns_records.records_ds.records.0.record_id
}
output "record_ids" {
value = data.alicloud_alidns_records.records_ds.records.*.record_id
}
#使用命令获取
D:\Github\terraform\ali>terraform output -json first_record_id
"783933231xxxx72"

D:\Github\terraform\ali>terraform output -json record_ids
["783933231886xxxx","70086148440790xxxxx"]

Variables

变量允许自定义 Terraform 模块,而无需更改模块自己的源代码,这可以实现跨不同的 Terraform 配置共享模块,使模块可以组合和可重用。定以后通过VAR_NAME调用

  • variables.tf 文件中定义变量
  • 在同一个模块的所有变量中必须是唯一的
  • 可以从环境变量或者文本文件中读取
  • Terraform 默认读取 terraform.tfvars
  • 定义
    • terraform.tfvars | terraform.tfvars.json
    • *.auto.tfvars | *.auto.tfvars.json
    • 命令行 -var | -var-file
1
2
3
4
5
6
variable "ali_region" {
type = string
default = "cn-hangzhou"
description = "区域"
sensitive = false
}
image-20220909151249560

使用map定义dns域名

1
2
3
4
5
6
7
8
9
10
11
12
13
variable "dns_record" {
type = map(string)
}
dns_record = {
"dev" = "dev.xyh"
"test" = "test.xyh"
}
resource "alicloud_dns_record" "test2" {
name = "xxx.com"
host_record = var.dns_record["test"]
type = "A"
value = "1.1.1.1"
}

使用list定义环境列表

1
2
3
4
variable "env_list" {
type = list(string)
}
env_list = ["prod", "test", "dev"]

object自定义属性

1
2
3
4
5
6
7
8
9
10
variable "zons" {
type = object({
zonsA = string
zonsB = string
})
}
zons = {
zonsA = "cn-hangzhou-b"
zonsB = "cn-hangzhou-e"
}

本地变量

1
2
3
4
5
6
7
8
9
10
locals {
name = "ecs1"
owner = "xxx"
}
resource "alicloud_vpc" "vpc_t1" {
# provider = alicloud.hangzhou
vpc_name = "tf_test_foo"
description = local.name
cidr_block = "172.16.0.0/12"
}

资源导入

目前只能一个一个导入

1
2
3
4
5
6
#假设没有states文件
#可以用datasource + output获取资源
#使用terraform plan获取资源路径
module.vpc.alicloud_vpc.vpc_t1
# 导入
terraform import module.vpc.alicloud_vpc.vpc_t1 <对应云资源id>

模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
provider "alicloud" {
access_key = var.ali_access_key
secret_key = var.ali_secret_key
region = var.ali_region
}
locals {
region = "cn-hangzhou"
}
module "vpc" { #这里面就光写资源就好
source = "../../modules/vpc"
zons = { # 后面这些是变量
zonsA = "cn-hangzhou-b"
zonsB = "cn-hangzhou-f"
}
}

跨module引用变量module.vpc.vpc_id

1
2
3
4
#变量需使用output在对应模块声明
output "vpc_id" {
value = alicloud_vpc.vpc_t1.id
}

表达式

condition ? true_val : false_val

  • condition 条件(返回true/false)
  • true_val 条件为true的值
  • false_val 条件为false的值
1
2
3
4
5
6
output "test" {
value = module.vpc.vpc_id == "" ? "为空" : "不为空"
}

Outputs:
test = "不为空"

[ for VAR in OBJ : VAR]

[for INDEX,VAR in OBJ : "${INDEX} ${VAR}"]

函数

数值

max()

min()

parseint()将字符串解析为正整数

字符串

format("hello %s!", "qh")格式化

join(",",["name", "age"])字符串拼接

replace("a=b=c", "=", "-")替换

split(",", "name,age,sex")字符串分割

list

image-20220911153312919

map

image-20220911153428891