Terraform申请云主机资源
目录:
Terraform介绍
Terraform是一种开源工具,用于安全高效地预配和管理云基础结构。
- 用代码维护资源,通过CLI的方式将配置文件部署到云上,并对其进行版本控制。
- 编写了描述云资源拓扑的配置文件中的基础结构,例如虚拟机,存储账户和网络接口
优势
- 将基础结构部署到多个云 适用于多云的方案,将类似结构部署到云上,或者本地数据中心,可以使用相同的工具和类似的配置文件管理不同的云提供商的资源
- 自动化管理基础结构 可以创建配置文件模板,可以多次部署相同的模板,构建相同的开发,测试和生产环境
- 基础架构即代码 用代码维护资源,允许保存基础设施状态,允许跟踪对系统中不同组件的更改,并与其他人共享这些配置
- 降低成本 按需构建环境的成本
Terraform安装
$ wget https://releases.hashicorp.com/terraform/0.12.2/terraform_0.12.2_linux_amd64.zip
$ unzip terraform_0.12.2_linux_amd64.zip
$ mv terraform /usr/local/bin/
$ terraform
Usage: terraform [-version] [-help] <command> [args]
The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.
Common commands:
apply Builds or changes infrastructure
console Interactive console for Terraform interpolations
destroy Destroy Terraform-managed infrastructure
env Workspace management
fmt Rewrites config files to canonical format
get Download and install modules for the configuration
graph Create a visual graph of Terraform resources
import Import existing infrastructure into Terraform
init Initialize a Terraform working directory
output Read an output from a state file
plan Generate and show an execution plan
providers Prints a tree of the providers used in the configuration
refresh Update local state file against real resources
show Inspect Terraform state or plan
taint Manually mark a resource for recreation
untaint Manually unmark a resource as tainted
validate Validates the Terraform files
version Prints the Terraform version
workspace Workspace management
All other commands:
0.12upgrade Rewrites pre-0.12 module source code for v0.12
debug Debug output management (experimental)
force-unlock Manually unlock the terraform state
push Obsolete command for Terraform Enterprise legacy (v1)
state Advanced state management
可以在云上创建Terraform的账户,并创建AccessKey,通过环境变量存放认证信息
常用操作
terraform init # 初始化工作目录,也是我们第一个要执行的命令
terraform plan # 生成计划
terraform appy # 提交请求
terraform state # 查看资源状态
terraform graph # 生成执行计划图
Terraform的资源概念
Terraform管理的是云资源
基础设施和服务统称为资源,如私有网络、子网、物理机、虚拟机、镜像、专线、NAT网关等等都可以称之为资源,也是开发和运维人员经常要打交道要维护的东西。
资源分为两种resource和data
resource
这类资源一般是抽象的真正的云服务资源,支持增删改,如私有网络、NAT网关、虚拟机实例
resource "资源类名" "映射到本地的唯一资源名" {
参数 = 值
...
}
data
这类资源一般是固定的一些可读资源,如可用区列表、镜像列表。大部分情况下,resource资源也会封装一个data source方法,用于资源查询
data "资源类名" "映射到本地的唯一资源名" {
参数 = 值
...
}
Terraform配置
以下以腾讯云为示例
创建用户
腾讯云 访问管理->用户->用户列表
png01
进行新建用户,自定义创建
png02
对用户进行授权
png03
在这个页面创建秘钥
公共配置
### 公共配置
provider "tencentcloud" {
secret_id = "AKIDpUyFXke12slT6nNGyWxGSXSHvqeM7Fbo"
secret_key = "PCQSJzURK3mHqlFanvCMQuEbsytOHKFz"
region = "ap-guangzhou"
}
也可以直接通过环境变量方式
export TENCENTCLOUD_SECRET_ID="AKIDpUyFXke12slT6nNGyWxGSXSHvqeM7Fbo"
export TENCENTCLOUD_SECRET_KEY="PCQSJzURK3mHqlFanvCMQuEbsytOHKFz"
export TENCENTCLOUD_REGION="ap-guangzhou"
查询资源
把资源依赖的上游资源,先查询出来,便宜后面引用
# 查询可用区信息
data "tencentcloud_availability_zones" "favorate_zones" {}
# 查询镜像
data "tencentcloud_image" "my_favorate_image" {
filter {
name = "image-type"
values = ["PUBLIC_IMAGE"]
}
}
后面我们创建的子网和虚拟机,需要用到可用区和镜像,所以这里先用data查询
创建资源
创建一个私有网络
resource "tencentcloud_vpc" "main" {
name = "979137_test_vpc"
cidr_block = "10.6.0.0/16"
}
创建私有网络,在Terraform中name为main
创建子网
子网在私网下
resource "tencentcloud_subnet" "main_subnet" {
vpc_id = "${tencentcloud_vpc.main.id}"
name = "979137_test_subnet"
cidr_block = "10.6.7.0/24"
availability_zone = "${data.tencentcloud_availability_zones.favorate_zones.zones.0.name}"
}
这边创建使用的可用区是data搜索到的name,是随机的,可以加过滤条件
创建弹性IP用于关联到NAT网关
resource "tencentcloud_eip" "eip_dev_dnat" {
name = "979137_test_eip"
}
resource "tencentcloud_eip" "eip_test_dnat" {
name = "979137_test_eip"
}
被依赖资源要优先创建
创建NAT网关,用于给CVM提供外网能力
resource "tencentcloud_nat_gateway" "my_nat" {
vpc_id = "${tencentcloud_vpc.main.id}"
name = "979137_test_nat"
max_concurrent = 3000000
bandwidth = 500
assigned_eip_set = [
"${tencentcloud_eip.eip_dev_dnat.public_ip}",
"${tencentcloud_eip.eip_test_dnat.public_ip}",
]
}
创建安全组并配置安全组规则
resource "tencentcloud_security_group" "my_sg" {
name = "979137_test_sg"
description = "979137_test_sg"
}
# 放通80,443端口
resource "tencentcloud_security_group_rule" "web" {
security_group_id = "${tencentcloud_security_group.my_sg.id}"
type = "ingress"
cidr_ip = "0.0.0.0/0"
ip_protocol = "tcp"
port_range = "80,443"
policy = "accept"
}
# 放通常用web端口
resource "tencentcloud_security_group_rule" "sg_web" {
security_group_id = "${tencentcloud_security_group.my_sg.id}"
type = "ingress"
cidr_ip = "0.0.0.0/0"
ip_protocol = "tcp"
port_range = "80,443,8080"
policy = "accept"
}
# 放通内网ssh登录
resource "tencentcloud_security_group_rule" "sg_ssh" {
security_group_id = "${tencentcloud_security_group.my_sg.id}"
type = "ingress"
cidr_ip = "10.65.0.0/16"
ip_protocol = "tcp"
port_range = "22"
policy = "accept"
}
# 拒绝所有访问
resource "tencentcloud_security_group_rule" "sg_drop" {
security_group_id = "${tencentcloud_security_group.my_sg.id}"
type = "ingress"
cidr_ip = "0.0.0.0/0"
ip_protocol = "tcp"
port_range = "ALL"
policy = "drop"
}
内容整合
# 公共资源
provider "tencentcloud" {
secret_id = "AKIDpUyFXke12slT6nNGyWxGSXSHvqeM7Fbo"
secret_key = "PCQSJzURK3mHqlFanvCMQuEbsytOHKFz"
region = "ap-guangzhou"
}
# 查询可用区信息
data "tencentcloud_availability_zones" "favorate_zones" {}
# 查询镜像
data "tencentcloud_image" "my_favorate_image" {
filter {
name = "image-type"
values = ["PUBLIC_IMAGE"]
}
}
# 查询机型
data "tencentcloud_instance_types" "my_favorate_instance_types" {
filter {
name = "instance-family"
values = ["S1"]
}
cpu_core_count = 1
memory_size = 1
}
resource "tencentcloud_vpc" "main" {
name = "979137_test_vpc"
cidr_block = "10.6.0.0/16"
}
resource "tencentcloud_subnet" "main_subnet" {
vpc_id = "${tencentcloud_vpc.main.id}"
name = "979137_test_subnet"
cidr_block = "10.6.7.0/24"
availability_zone = "${data.tencentcloud_availability_zones.favorate_zones.zones.0.name}"
}
resource "tencentcloud_eip" "eip_dev_dnat" {
name = "979137_test_eip"
}
resource "tencentcloud_eip" "eip_test_dnat" {
name = "979137_test_eip"
}
resource "tencentcloud_nat_gateway" "my_nat" {
vpc_id = "${tencentcloud_vpc.main.id}"
name = "979137_test_nat"
max_concurrent = 3000000
bandwidth = 500
assigned_eip_set = [
"${tencentcloud_eip.eip_dev_dnat.public_ip}",
"${tencentcloud_eip.eip_test_dnat.public_ip}",
]
}
resource "tencentcloud_security_group" "my_sg" {
name = "979137_test_sg"
description = "979137_test_sg"
}
# 放通80,443端口
resource "tencentcloud_security_group_rule" "web" {
security_group_id = "${tencentcloud_security_group.my_sg.id}"
type = "ingress"
cidr_ip = "0.0.0.0/0"
ip_protocol = "tcp"
port_range = "80,443"
policy = "accept"
}
# 放通常用web端口
resource "tencentcloud_security_group_rule" "sg_web" {
security_group_id = "${tencentcloud_security_group.my_sg.id}"
type = "ingress"
cidr_ip = "0.0.0.0/0"
ip_protocol = "tcp"
port_range = "80,443,8080"
policy = "accept"
}
# 放通内网ssh登录
resource "tencentcloud_security_group_rule" "sg_ssh" {
security_group_id = "${tencentcloud_security_group.my_sg.id}"
type = "ingress"
cidr_ip = "10.65.0.0/16"
ip_protocol = "tcp"
port_range = "22"
policy = "accept"
}
# 拒绝所有访问
resource "tencentcloud_security_group_rule" "sg_drop" {
security_group_id = "${tencentcloud_security_group.my_sg.id}"
type = "ingress"
cidr_ip = "0.0.0.0/0"
ip_protocol = "tcp"
policy = "drop"
}
resource "tencentcloud_instance" "foo" {
availability_zone = "${data.tencentcloud_availability_zones.favorate_zones.zones.0.name}"
image_id = "${data.tencentcloud_image.my_favorate_image.image_id}"
vpc_id = "${tencentcloud_vpc.main.id}"
instance_type = "${data.tencentcloud_instance_types.my_favorate_instance_types.instance_types.0.instance_type}"
system_disk_type = "CLOUD_PREMIUM"
subnet_id = "${tencentcloud_subnet.main_subnet.id}"
security_groups = [
"${tencentcloud_security_group.my_sg.id}",
]
}
resource "tencentcloud_dnat" "dev_dnat" {
vpc_id = "${tencentcloud_nat_gateway.my_nat.vpc_id}"
nat_id = "${tencentcloud_nat_gateway.my_nat.id}"
protocol = "tcp"
elastic_ip = "${tencentcloud_eip.eip_dev_dnat.public_ip}"
elastic_port = "80"
private_ip = "${tencentcloud_instance.foo.private_ip}"
private_port = "9001"
}
resource "tencentcloud_dnat" "test_dnat" {
vpc_id = "${tencentcloud_nat_gateway.my_nat.vpc_id}"
nat_id = "${tencentcloud_nat_gateway.my_nat.id}"
protocol = "udp"
elastic_ip = "${tencentcloud_eip.eip_test_dnat.public_ip}"
elastic_port = "8080"
private_ip = "${tencentcloud_instance.foo.private_ip}"
private_port = "9002"
}
创建虚拟机
resource "tencentcloud_instance" "foo" {
availability_zone = "${data.tencentcloud_availability_zones.favorate_zones.zones.0.name}"
image_id = "${data.tencentcloud_image.my_favorate_image.image_id}"
vpc_id = "${tencentcloud_vpc.main.id}"
subnet_id = "${tencentcloud_subnet.main_subnet.id}"
security_groups = [
"${tencentcloud_security_group.my_sg.id}",
]
# 付费类型(默认也是POSTPAID_BY_HOUR)
instance_charge_type = "POSTPAID_BY_HOUR"
}
指定虚拟机的NAT网关
resource "tencentcloud_dnat" "dev_dnat" {
vpc_id = "${tencentcloud_nat_gateway.my_nat.vpc_id}"
nat_id = "${tencentcloud_nat_gateway.my_nat.id}"
protocol = "tcp"
elastic_ip = "${tencentcloud_eip.eip_dev_dnat.public_ip}"
elastic_port = "80"
private_ip = "${tencentcloud_instance.foo.private_ip}"
private_port = "9001"
}
resource "tencentcloud_dnat" "test_dnat" {
vpc_id = "${tencentcloud_nat_gateway.my_nat.vpc_id}"
nat_id = "${tencentcloud_nat_gateway.my_nat.id}"
protocol = "udp"
elastic_ip = "${tencentcloud_eip.eip_test_dnat.public_ip}"
elastic_port = "8080"
private_ip = "${tencentcloud_instance.foo.private_ip}"
private_port = "9002"
}
加载插件
$ terraform init
Initializing the backend...
Initializing provider plugins...
- Checking for available provider plugins...
- Downloading plugin for provider "tencentcloud" (terraform-providers/tencentcloud) 1.9.1...
The following providers do not have any version constraints in configuration,
so the latest version was installed.
To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.
* provider.tencentcloud: version = "~> 1.9"
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.
生成计划
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
data.tencentcloud_availability_zones.favorate_zones: Refreshing state...
data.tencentcloud_image.my_favorate_image: Refreshing state...
------------------------------------------------------------------------
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# tencentcloud_dnat.dev_dnat will be created
+ resource "tencentcloud_dnat" "dev_dnat" {
+ elastic_ip = (known after apply)
+ elastic_port = "80"
+ id = (known after apply)
+ nat_id = (known after apply)
+ private_ip = (known after apply)
+ private_port = "9001"
+ protocol = "tcp"
+ vpc_id = (known after apply)
}
# tencentcloud_dnat.test_dnat will be created
+ resource "tencentcloud_dnat" "test_dnat" {
+ elastic_ip = (known after apply)
+ elastic_port = "8080"
+ id = (known after apply)
+ nat_id = (known after apply)
+ private_ip = (known after apply)
+ private_port = "9002"
+ protocol = "udp"
+ vpc_id = (known after apply)
}
# tencentcloud_eip.eip_dev_dnat will be created
+ resource "tencentcloud_eip" "eip_dev_dnat" {
+ id = (known after apply)
+ name = "979137_test_eip"
+ public_ip = (known after apply)
+ status = (known after apply)
}
# tencentcloud_eip.eip_test_dnat will be created
+ resource "tencentcloud_eip" "eip_test_dnat" {
+ id = (known after apply)
+ name = "979137_test_eip"
+ public_ip = (known after apply)
+ status = (known after apply)
}
# tencentcloud_instance.foo will be created
+ resource "tencentcloud_instance" "foo" {
+ availability_zone = "ap-guangzhou-3"
+ id = (known after apply)
+ image_id = "img-9qabwvbn"
+ instance_name = "Terrafrom-CVM-Instance"
+ instance_status = (known after apply)
+ key_name = (known after apply)
+ private_ip = (known after apply)
+ public_ip = (known after apply)
+ security_groups = (known after apply)
+ subnet_id = (known after apply)
+ system_disk_size = (known after apply)
+ system_disk_type = (known after apply)
+ vpc_id = (known after apply)
+ data_disks {
+ data_disk_size = (known after apply)
+ data_disk_type = (known after apply)
+ delete_with_instance = (known after apply)
}
}
# tencentcloud_nat_gateway.my_nat will be created
+ resource "tencentcloud_nat_gateway" "my_nat" {
+ assigned_eip_set = (known after apply)
+ bandwidth = 500
+ id = (known after apply)
+ max_concurrent = 3000000
+ name = "979137_test_nat"
+ vpc_id = (known after apply)
}
# tencentcloud_security_group.my_sg will be created
+ resource "tencentcloud_security_group" "my_sg" {
+ description = "979137_test_sg"
+ id = (known after apply)
+ name = "979137_test_sg"
}
# tencentcloud_security_group_rule.sg_drop will be created
+ resource "tencentcloud_security_group_rule" "sg_drop" {
+ cidr_ip = "0.0.0.0/0"
+ id = (known after apply)
+ ip_protocol = "tcp"
+ policy = "drop"
+ security_group_id = (known after apply)
+ type = "ingress"
}
# tencentcloud_security_group_rule.sg_ssh will be created
+ resource "tencentcloud_security_group_rule" "sg_ssh" {
+ cidr_ip = "10.65.0.0/16"
+ id = (known after apply)
+ ip_protocol = "tcp"
+ policy = "accept"
+ port_range = "22"
+ security_group_id = (known after apply)
+ type = "ingress"
}
# tencentcloud_security_group_rule.sg_web will be created
+ resource "tencentcloud_security_group_rule" "sg_web" {
+ cidr_ip = "0.0.0.0/0"
+ id = (known after apply)
+ ip_protocol = "tcp"
+ policy = "accept"
+ port_range = "80,443,8080"
+ security_group_id = (known after apply)
+ type = "ingress"
}
# tencentcloud_security_group_rule.web will be created
+ resource "tencentcloud_security_group_rule" "web" {
+ cidr_ip = "0.0.0.0/0"
+ id = (known after apply)
+ ip_protocol = "tcp"
+ policy = "accept"
+ port_range = "80,443"
+ security_group_id = (known after apply)
+ type = "ingress"
}
# tencentcloud_subnet.main_subnet will be created
+ resource "tencentcloud_subnet" "main_subnet" {
+ availability_zone = "ap-guangzhou-3"
+ cidr_block = "10.6.7.0/24"
+ id = (known after apply)
+ name = "979137_test_subnet"
+ vpc_id = (known after apply)
}
# tencentcloud_vpc.main will be created
+ resource "tencentcloud_vpc" "main" {
+ cidr_block = "10.6.0.0/16"
+ id = (known after apply)
+ is_default = (known after apply)
+ is_multicast = (known after apply)
+ name = "979137_test_vpc"
}
Plan: 13 to add, 0 to change, 0 to destroy.
------------------------------------------------------------------------
Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
执行计划
$ terraform 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
完整示例
terraform_tx/main.tf
# 公共资源
provider "tencentcloud" {
secret_id = "AKIDpUyFXke12slT6nNGyWxG************"
secret_key = "PCQSJzURK3mHqlFanvC************"
region = "ap-guangzhou"
}
# 查询可用区信息
data "tencentcloud_availability_zones" "favorate_zones" {}
# 查询镜像
data "tencentcloud_image" "my_favorate_image" {
filter {
name = "image-type"
values = ["PUBLIC_IMAGE"]
}
}
# 查询机型
data "tencentcloud_instance_types" "my_favorate_instance_types" {
filter {
name = "instance-family"
values = ["S1"]
}
cpu_core_count = 1
memory_size = 1
}
resource "tencentcloud_vpc" "main" {
name = "979137_test_vpc"
cidr_block = "10.6.0.0/16"
}
resource "tencentcloud_subnet" "main_subnet" {
vpc_id = "${tencentcloud_vpc.main.id}"
name = "979137_test_subnet"
cidr_block = "10.6.7.0/24"
availability_zone = "${data.tencentcloud_availability_zones.favorate_zones.zones.0.name}"
}
resource "tencentcloud_eip" "eip_dev_dnat" {
name = "979137_test_eip"
}
resource "tencentcloud_eip" "eip_test_dnat" {
name = "979137_test_eip"
}
resource "tencentcloud_nat_gateway" "my_nat" {
vpc_id = "${tencentcloud_vpc.main.id}"
name = "979137_test_nat"
max_concurrent = 3000000
bandwidth = 500
assigned_eip_set = [
"${tencentcloud_eip.eip_dev_dnat.public_ip}",
"${tencentcloud_eip.eip_test_dnat.public_ip}",
]
}
resource "tencentcloud_security_group" "my_sg" {
name = "979137_test_sg"
description = "979137_test_sg"
}
# 放通80,443端口
resource "tencentcloud_security_group_rule" "web" {
security_group_id = "${tencentcloud_security_group.my_sg.id}"
type = "ingress"
cidr_ip = "0.0.0.0/0"
ip_protocol = "tcp"
port_range = "80,443"
policy = "accept"
}
# 放通常用web端口
resource "tencentcloud_security_group_rule" "sg_web" {
security_group_id = "${tencentcloud_security_group.my_sg.id}"
type = "ingress"
cidr_ip = "0.0.0.0/0"
ip_protocol = "tcp"
port_range = "80,443,8080"
policy = "accept"
}
# 放通内网ssh登录
resource "tencentcloud_security_group_rule" "sg_ssh" {
security_group_id = "${tencentcloud_security_group.my_sg.id}"
type = "ingress"
cidr_ip = "10.65.0.0/16"
ip_protocol = "tcp"
port_range = "22"
policy = "accept"
}
# 拒绝所有访问
resource "tencentcloud_security_group_rule" "sg_drop" {
security_group_id = "${tencentcloud_security_group.my_sg.id}"
type = "ingress"
cidr_ip = "0.0.0.0/0"
ip_protocol = "tcp"
policy = "drop"
}
resource "tencentcloud_instance" "foo" {
availability_zone = "${data.tencentcloud_availability_zones.favorate_zones.zones.0.name}"
image_id = "${data.tencentcloud_image.my_favorate_image.image_id}"
vpc_id = "${tencentcloud_vpc.main.id}"
instance_type = "${data.tencentcloud_instance_types.my_favorate_instance_types.instance_types.0.instance_type}"
system_disk_type = "CLOUD_PREMIUM"
subnet_id = "${tencentcloud_subnet.main_subnet.id}"
security_groups = [
"${tencentcloud_security_group.my_sg.id}",
]
}
resource "tencentcloud_dnat" "dev_dnat" {
vpc_id = "${tencentcloud_nat_gateway.my_nat.vpc_id}"
nat_id = "${tencentcloud_nat_gateway.my_nat.id}"
protocol = "tcp"
elastic_ip = "${tencentcloud_eip.eip_dev_dnat.public_ip}"
elastic_port = "80"
private_ip = "${tencentcloud_instance.foo.private_ip}"
private_port = "9001"
}
resource "tencentcloud_dnat" "test_dnat" {
vpc_id = "${tencentcloud_nat_gateway.my_nat.vpc_id}"
nat_id = "${tencentcloud_nat_gateway.my_nat.id}"
protocol = "udp"
elastic_ip = "${tencentcloud_eip.eip_test_dnat.public_ip}"
elastic_port = "8080"
private_ip = "${tencentcloud_instance.foo.private_ip}"
private_port = "9002"
}