本文以Terraform版ECS单机部署Nginx服务为例,由简入难的向您介绍如何编辑Terraform模板。
前提条件
请您提前了解模板语法和结构。更多信息,请参见模板快速入门。
场景示例
在阿里云专有网络VPC中创建ECS实例,并在ECS实例中部署Nginx服务。
使用须知
您可以访问对应的资源类型查看属性详情。具体操作,请参见查看资源类型。
资源类型文档为每个属性定义了Optional(可选)、Required(必须)等信息。如果将属性定义为Required(必须),则要求必须在模板资源中声明该属性;反之,则为非必须。
编辑模板
您可以通过资源类型索引文档查找所需的资源类型。更多信息,请参见资源类型索引。
例如:当前场景中需要创建专有网络VPC(alicloud_vpc)、ECS实例(alicloud_instance)、交换机(alicloud_vswitch)、安全组(alicloud_security_group)和安全组规则(alicloud_security_group_rule),在创建ECS实例的同时会安装Nginx服务。
定义模板多种资源及其依赖关系
定义基础网络资源
您可以通过模板定义基础网络资源vpc
、vsw
、security_group
。
使用
alicloud_vpc.vpc.id
获取资源alicloud_vpc
的输出ID属性值。使用
var.***
获取自定义变量,即variable
中的参数值。例如var.zone_id
获取的是variable
中zone_id
的值。
resource "alicloud_vpc" "vpc" {
cidr_block = "10.1.0.0/21"
}
resource "alicloud_vswitch" "vsw" {
vpc_id = alicloud_vpc.vpc.id
cidr_block = "172.16.0.0/21"
zone_id = var.zone_id
}
resource "alicloud_security_group" "security_group" {
name = "new-group"
vpc_id = alicloud_vpc.vpc.id
}
定义安全组规则
您可以通过模板定义安全组规则allow_ssh
、allow_web
、allow_egress
。
使用alicloud_security_group.security_group.id
获取安全组security_group
资源的输出ID属性值。
# 安全组入口端1
resource "alicloud_security_group_rule" "allow_ssh" {
security_group_id = alicloud_security_group.security_group.id
type = "ingress"
cidr_ip = "0.0.0.0/0"
policy = "accept"
ip_protocol = "tcp"
port_range = "22/22"
priority = 1
}
# 安全组入口端2
resource "alicloud_security_group_rule" "allow_web" {
security_group_id = alicloud_security_group.security_group.id
type = "ingress"
cidr_ip = "0.0.0.0/0"
policy = "accept"
ip_protocol = "tcp"
port_range = "80/443"
priority = 1
}
# 安全组出口端
resource "alicloud_security_group_rule" "allow_egress" {
security_group_id = alicloud_security_group.security_group.id
type = "egress"
cidr_ip = "0.0.0.0/0"
policy = "accept"
ip_protocol = "tcp"
port_range = "1/65535"
priority = 1
}
定义ECS实例
您可以通过模板定义ECS实例instance
。
使用
var.***
获取自定义变量,即variable
中的参数值。例如:var.instance_type
获取的是variable
中instance_type
的值。使用
local.***
获取本地变量,即locals
中的参数值。例如:local.new_host_name
获取的是locals
中new_host_name
的值。使用user_data中的
${path.cwd}
获取当前工作目录。user_data.sh文件中包含云服务器ECS需要执行的初始化脚本。user_data.sh初始化脚本如下所示。
#!/bin/bash -v
# 挂盘到/disk1
cat >> /root/InitDataDisk.sh << "EOF"
#!/bin/bash
echo "p
n
p
w
" | fdisk -u /dev/vdb
EOF
/bin/bash /root/InitDataDisk.sh
rm -f /root/InitDataDisk.sh
mkfs -t ext4 /dev/vdb1
cp /etc/fstab /etc/fstab.bak
mkdir /disk1
echo `blkid /dev/vdb1 | awk '{print $2}' | sed 's/\\\"//g'` /disk1 ext4 defaults 0 0 >> /etc/fstab
mount -a
# 这里配置安装脚本
yum install -y nginx
# 配置启动脚本
/usr/sbin/nginx
定义ECS实例模板如下所示。
resource "alicloud_instance" "instance" {
availability_zone = var.zone_id
security_groups = [alicloud_security_group.security_group.id]
# series III
host_name = local.new_host_name
instance_type = var.instance_type
system_disk_size = 500
system_disk_category = "cloud_essd"
image_id = "centos_7_9_x64_20G_alibase_20210318.vhd"
vswitch_id = alicloud_vswitch.vsw.id
password = var.instance_password
internet_charge_type = "PayByTraffic"
internet_max_bandwidth_out = 30
instance_charge_type = var.pay_type
period = var.pay_period
period_unit = var.pay_period_unit
user_data = file("${path.cwd}/user-data.sh")
data_disks {
size = 100
category = "cloud_essd"
}
}
完整模板示例
variable "pay_type" {
type = string
}
variable "pay_period_unit" {
type = string
}
variable "pay_period" {
type = number
}
variable "zone_id" {
type = string
}
variable "vpc_cidr_block" {
type = string
}
variable "vswitch_cidr_block" {
type = string
}
variable "instance_type" {
type = string
}
variable "system_disk_category" {
type = string
}
variable "system_disk_size" {
type = number
}
variable "data_disk_category" {
type = string
}
variable "data_disk_size" {
type = number
}
variable "instance_password" {
type = string
}
# 默认资源名称
locals {
production_name = "nginx"
new_scg_name = "sg-for-${local.production_name}"
new_host_name = "app-for-${local.production_name}"
}
resource "alicloud_vpc" "vpc" {
cidr_block = var.vpc_cidr_block
}
resource "alicloud_vswitch" "vsw" {
vpc_id = alicloud_vpc.vpc.id
cidr_block = var.vswitch_cidr_block
zone_id = var.zone_id
}
# 安全组基本信息配置
resource "alicloud_security_group" "security_group" {
name = local.new_scg_name
description = "nginx scg"
vpc_id = alicloud_vpc.vpc.id
}
# 安全组入口端1
resource "alicloud_security_group_rule" "allow_ssh" {
security_group_id = alicloud_security_group.security_group.id
type = "ingress"
cidr_ip = "0.0.0.0/0"
policy = "accept"
ip_protocol = "tcp"
port_range = "22/22"
priority = 1
}
# 安全组入口端2
resource "alicloud_security_group_rule" "allow_web" {
security_group_id = alicloud_security_group.security_group.id
type = "ingress"
cidr_ip = "0.0.0.0/0"
policy = "accept"
ip_protocol = "tcp"
port_range = "80/443"
priority = 1
}
# 安全组出口端
resource "alicloud_security_group_rule" "allow_egress" {
security_group_id = alicloud_security_group.security_group.id
type = "egress"
cidr_ip = "0.0.0.0/0"
policy = "accept"
ip_protocol = "tcp"
port_range = "1/65535"
priority = 1
}
# 实例基本配置
resource "alicloud_instance" "instance" {
availability_zone = var.zone_id
security_groups = [alicloud_security_group.security_group.id]
# series III
host_name = local.new_host_name
instance_type = var.instance_type
system_disk_size = var.system_disk_size
system_disk_category = var.system_disk_category
image_id = "centos_7_9_x64_20G_alibase_20210318.vhd"
vswitch_id = alicloud_vswitch.vsw.id
password = var.instance_password
internet_charge_type = "PayByTraffic"
internet_max_bandwidth_out = 30
instance_charge_type = var.pay_type
period = var.pay_period
period_unit = var.pay_period_unit
user_data = file("${path.cwd}/user-data.sh")
data_disks {
size = var.data_disk_size
category = var.data_disk_category
}
}
# 返回Nginx的IP地址
output "nginx_ip" {
value = "http://${alicloud_instance.instance.public_ip}:8080"
}
Terraform模板类型转换
您可以通过资源编排控制台将Terraform模板转换成ROS模板,使用ROS资源实现添加模板参数分组与动态获取参数配置。
登录资源编排控制台。
在左侧导航栏,选择模板>我的模板。
在我的模板页面,单击创建模板。
在编辑模板内容页签的下拉页表中,选择Terraform。
编辑Terraform模板。
新建main.tf文件,输入完整模板示例中创建的Terraform模板。
新建user-data.sh文件,输入user_data.sh初始化脚本内容。
在编辑模板内容页签的下拉页表中,选择ROS。
您已成功将Terraform模板转换为ROS模板,ROS模板示例如下所示。
ROSTemplateFormatVersion: '2015-09-01' Transform: Aliyun::Terraform-v1.2 Workspace: main.tf: |- variable "pay_type" { type = string } variable "pay_period_unit" { type = string } variable "pay_period" { type = number } variable "zone_id" { type = string } variable "instance_type" { type = string } variable "vpc_cidr_block" { type = string } variable "vsw_cidr_block" { type = string } variable "instance_password" { type = string } # 默认资源名称 locals { production_name = "nginx" new_vpc_name = "vpc-for-${local.production_name}" new_vsw_name = "vsw-for-${local.production_name}" new_scg_name = "sg-for-${local.production_name}" new_host_name = "app-for-${local.production_name}" } resource "alicloud_vpc" "vpc" { vpc_name = local.new_vpc_name cidr_block = var.vpc_cidr_block } resource "alicloud_vswitch" "vsw" { vpc_id = alicloud_vpc.vpc.id cidr_block = var.vsw_cidr_block zone_id = var.zone_id } # 安全组基本信息配置 resource "alicloud_security_group" "security_group" { name = local.new_scg_name description = "nginx scg" vpc_id = alicloud_vpc.vpc.id } # 安全组入口端1 resource "alicloud_security_group_rule" "allow_ssh" { security_group_id = alicloud_security_group.security_group.id type = "ingress" cidr_ip = "0.0.0.0/0" policy = "accept" ip_protocol = "tcp" port_range = "22/22" priority = 1 } # 安全组入口端2 resource "alicloud_security_group_rule" "allow_web" { security_group_id = alicloud_security_group.security_group.id type = "ingress" cidr_ip = "0.0.0.0/0" policy = "accept" ip_protocol = "tcp" port_range = "80/443" priority = 1 } # 安全组出口端 resource "alicloud_security_group_rule" "allow_egress" { security_group_id = alicloud_security_group.security_group.id type = "egress" cidr_ip = "0.0.0.0/0" policy = "accept" ip_protocol = "tcp" port_range = "1/65535" priority = 1 } # 实例基本配置 resource "alicloud_instance" "instance" { availability_zone = var.zone_id security_groups = [alicloud_security_group.security_group.id] # series III host_name = local.new_host_name instance_type = var.instance_type system_disk_size = 500 system_disk_category = "cloud_essd" image_id = "centos_7_9_x64_20G_alibase_20210318.vhd" vswitch_id = alicloud_vswitch.vsw.id password = var.instance_password internet_charge_type = "PayByTraffic" internet_max_bandwidth_out = 30 instance_charge_type = var.pay_type period = var.pay_period period_unit = var.pay_period_unit user_data = file("${path.cwd}/user-data.sh") data_disks { size = 100 category = "cloud_essd" } } # 返回Nginx的IP地址 output "nginx_ip" { value = "http://${alicloud_instance.instance.public_ip}:8080" } user-data.sh: |- #!/bin/bash -v # 挂盘到/disk1 cat >> /root/InitDataDisk.sh << "EOF" #!/bin/bash echo "p n p w " | fdisk -u /dev/vdb EOF /bin/bash /root/InitDataDisk.sh rm -f /root/InitDataDisk.sh mkfs -t ext4 /dev/vdb1 cp /etc/fstab /etc/fstab.bak mkdir /disk1 echo `blkid /dev/vdb1 | awk '{print $2}' | sed 's/\\\"//g'` /disk1 ext4 defaults 0 0 >> /etc/fstab mount -a # 这里配置安装脚本 yum install -y nginx # 配置启动脚本 /usr/sbin/nginx
添加模板参数分组与动态获取参数配置
在以上模板中您已经完成对多种资源及其依赖关系的定义。其中instance资源的system_disk_category
属性值为固定值,当您在不同地域创建资源栈时,需要调整模板内容和变更资源属性值以达到部署资源栈的目的。
您可以对模板添加Parameters,从而提高模板的灵活性和可复用性。
添加模板参数分组
您可以在模板中使用元数据(Metadata)对Parameters中定义的参数进行分组,并定义参数分组标签。更多信息,请参见元数据(Metadata)。
您可以根据不同资源与资源对应的参数进行参数分组。以当前模板为例,您可以将资源按照如下结果划分。
资源参数分类 | 资源名称 | 参数名称 |
基础网络配置 |
|
|
ECS实例资源配置 |
|
|
在Terraform标签下,新建.metadata
文件,输入以下内容。
{
"ALIYUN::ROS::Interface": {
"ParameterGroups": [
{
"Parameters": [
"pay_type",
"pay_period_unit",
"pay_period"
],
"Label": {
"default": {
"en": "Payment mode Configuration",
"zh-cn": "付费模式配置"
}
}
},
{
"Parameters": [
"zone_id"
],
"Label": {
"default": {
"zh-cn": "可用区配置",
"en": "Zone Configuration"
}
}
},
{
"Parameters": [
"vpc_cidr_block",
"vswitch_cidr_block"
],
"Label": {
"default": {
"zh-cn": "选择已有基础资源配置",
"en": "Choose existing Infrastructure Configuration"
}
}
},
{
"Parameters": [
"instance_type",
"system_disk_category",
"system_disk_size",
"data_disk_category",
"data_disk_size",
"instance_password"
],
"Label": {
"default": {
"en": "Instance",
"zh-cn": "ECS实例配置"
}
}
}
]
}
}
动态获取参数配置
以instance参数为例,当您需要在ROS控制台上对参数设置筛选条件并动态选择参数配置时,可以按照参数对应的资源类型(ALIYUN::ECS::Instance)在AssociationProperty和AssociationPropertyMetadata文档中查询到该参数支持的AssociationProperty
取值 (ALIYUN::ECS::Instance::InstanceType),然后查看对筛选到的AssociationProperty
设置过滤条件为ZoneId
的AssociationPropertyMetadata
取值。更多信息,请参见AssociationProperty和AssociationPropertyMetadata。
在Terraform标签下的main.tf
文件中输入以下内容。
variable "pay_type" {
type = string
default = "PostPaid"
description = <<EOT
{
"Label": {
"en": "ECS Instance Charge Type",
"zh-cn": "付费类型"
},
"AllowedValues": [
"PostPaid",
"PrePaid"
],
"AssociationProperty": "ChargeType",
"AssociationPropertyMetadata": {
"LocaleKey": "InstanceChargeType"
}
}
EOT
}
variable "pay_period_unit" {
type = string
default = "Month"
description = <<EOT
{
"Label": {
"en": "Pay Period Unit",
"zh-cn": "购买资源时长周期"
},
"AllowedValues": [
"Month",
"Year"
],
"AssociationProperty": "PayPeriodUnit",
"AssociationPropertyMetadata": {
"Visible": {
"Condition": {
"Fn::Not": {
"Fn::Equals": [
"$${pay_type}",
"PostPaid"
]
}
}
}
}
}
EOT
}
variable "pay_period" {
type = number
default = 1
description = <<EOT
{
"Label": {
"en": "Period",
"zh-cn": "购买资源时长"
},
"AllowedValues": [
1,
2,
3,
4,
5,
6,
7,
8,
9
],
"AssociationProperty": "PayPeriod",
"AssociationPropertyMetadata": {
"Visible": {
"Condition": {
"Fn::Or": [
{
"Fn::Equals": [
"$${pay_type}",
"PrePaid"
]
},
{
"Fn::Equals": [
"$${pay_type}",
"undefined"
]
}
]
}
}
}
}
EOT
}
variable "zone_id" {
type = string
description = <<EOT
{
"AssociationProperty": "ALIYUN::ECS::Instance:ZoneId",
"Description": {
"zh-cn": "可用区ID。<br><b>注: <font color='blue'>选择前请确认该可用区是否支持创建ECS资源的规格,建议与其他交换机可用区不同。</font></b>",
"en": "Availability Zone ID.<br><b>notex:<font color='blue'>before selecting, please confirm that the Availability Zone supports the specification of creating ECS resources,which is recommended to be different from other VSwitch Availability Zone.</font></b>"
},
"Label": {
"zh-cn": "交换机可用区",
"en": "VSwitch Availability Zone"
}
}
EOT
}
variable "vpc_cidr_block" {
type = string
default = "192.168.0.0/16"
description = <<EOT
{
"Label": {
"zh-cn": "专有网络网段",
"en": "VPC CIDR Block"
},
"Description": {
"zh-cn": "新建专有网络IP地址段范围,推荐使用以下的IP地址段<br><font color='green'>[10.0.0.0/8]</font><br><font color='green'>[172.16.0.0/12]</font><br><font color='green'>[192.168.0.0/16]。</font>",
"en": "New proprietary network IP address segment range, recommended use of the following IP address segments<br><font color='green'>[10.0.0.0/8]</font><br><font color='green'>[172.16.0.0/12]</font><br><font color='green'>[192.168.0.0/16].</font>"
}
}
EOT
}
variable "vswitch_cidr_block" {
type = string
default = "192.168.0.0/24"
description = <<EOT
{
"Description": {
"zh-cn": "必须是所属专有网络的子网段,并且没有被其他交换机占用。",
"en": "Must be a sub-network segment of the proprietary network and is not occupied by other VSwitches."
},
"Label": {
"zh-cn": "交换机网段",
"en": "VSwitch CIDR Block"
}
}
EOT
}
variable "instance_type" {
type = string
description = <<EOT
{
"Label": {
"zh-cn": "实例规格",
"en": "Instance Type"
},
"AssociationProperty": "ALIYUN::ECS::Instance::InstanceType",
"AssociationPropertyMetadata": {
"InstanceChargeType": "$${pay_type}",
"ZoneId": "$${zone_id}"
}
}
EOT
}
variable "system_disk_category" {
type = string
description = <<EOT
{
"Description": {
"en": "<font color='blue'><b>Optional values:</b></font><br>[cloud_efficiency: <font color='green'>Efficient Cloud Disk</font>]<br>[cloud_ssd: <font color='green'>SSD Cloud Disk</font>]<br>[cloud_essd: <font color='green'>ESSD Cloud Disk</font>]<br>[cloud: <font color='green'>Cloud Disk</font>]<br>[ephemeral_ssd: <font color='green'>Local SSD Cloud Disk</font>]",
"zh-cn": "<font color='blue'><b>可选值:</b></font><br>[cloud_efficiency: <font color='green'>高效云盘</font>]<br>[cloud_ssd: <font color='green'>SSD云盘</font>]<br>[cloud_essd: <font color='green'>ESSD云盘</font>]<br>[cloud: <font color='green'>普通云盘</font>]<br>[ephemeral_ssd: <font color='green'>本地SSD盘</font>]"
},
"AssociationProperty": "ALIYUN::ECS::Disk::SystemDiskCategory",
"AssociationPropertyMetadata": {
"ZoneId": "$${zone_id}",
"InstanceType": "$${instance_type}"
},
"Label": {
"en": "System Disk Type",
"zh-cn": "系统盘类型"
}
}
EOT
}
variable "system_disk_size" {
type = number
default = 40
description = <<EOT
{
"Description": {
"zh-cn": "系统盘大小,取值范围:40~500,单位:GB。",
"en": "System disk size, range of values: 40~500, units: GB."
},
"Label": {
"zh-cn": "系统盘空间",
"en": "System Disk Space"
}
}
EOT
}
variable "data_disk_category" {
type = string
description = <<EOT
{
"Label": {
"zh-cn": "数据盘类型",
"en": "Data Disk Type"
},
"Description": {
"zh-cn": "<font color='blue'><b>可选值:</b></font><br>[cloud_efficiency: <font color='green'>高效云盘</font>]<br>[cloud_ssd: <font color='green'>SSD云盘</font>]<br>[cloud_essd: <font color='green'>ESSD云盘</font>]<br>[cloud: <font color='green'>普通云盘</font>]",
"en": "<font color='blue'><b>Optional values:</b></font><br>[cloud_efficiency: <font color='green'>Efficient Cloud Disk</font>]<br>[cloud_ssd: <font color='green'>SSD Cloud Disk</font>]<br>[cloud_essd: <font color='green'>ESSD Cloud Disk</font>]<br>[cloud: <font color='green'>Cloud Disk</font>]"
},
"AssociationProperty": "ALIYUN::ECS::Disk::DataDiskCategory",
"AssociationPropertyMetadata": {
"ZoneId": "$${zone_id}",
"InstanceType": "$${instance_type}"
}
}
EOT
}
variable "data_disk_size" {
type = number
default = 100
description = <<EOT
{
"Description": {
"zh-cn": "ECS实例数据盘大小,单位为GiB。取值范围:20~32768",
"en": "ECS Instance disk size, range of values: 20~32768, units: GB"
},
"MaxValue": 32768,
"MinValue": 20,
"Label": {
"zh-cn": "数据盘空间",
"en": "Data Disk Space"
}
}
EOT
}
variable "instance_password" {
type = string
sensitive = true
description = <<EOT
{
"Description": {
"en": "Server login password, Length 8~30, must contain three(Capital letters, lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;<>,.?/ Special symbol in).",
"zh-cn": "登录密码,长度8~30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;<>,.?/ 中的特殊符号)。"
},
"Label": {
"en": "Instance Password",
"zh-cn": "登录密码"
},
"ConstraintDescription": {
"en": "Length 8~30, must contain three(Capital letters, lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;<>,.?/ Special symbol in).",
"zh-cn": "长度8~30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;<>,.?/ 中的特殊符号)。"
},
"AssociationProperty": "ALIYUN::ECS::Instance::Password",
"AllowedPattern": "^[a-zA-Z0-9-\\(\\)\\`\\~\\!\\@\\#\\$\\%\\^\\&\\*\\_\\-\\+\\=\\|\\{\\}\\[\\]\\:\\;\\<\\>\\,\\.\\?\\/]*$",
"MinLength": 8,
"MaxLength": 30
}
EOT
}
添加模板参数关联与约束
Terraform模板中定义了ECS实例,其中需要约束的参数(zone_id
、instance_type
、vswitch_id
、system_disk_category
、system_disk_size
、data_disk_category
、data_disk_size
)都与alicloud_instance
有关。
在ResourcesForParameterConstraints字段中只需要定义资源类型ALIYUN::ECS::Instance(alicloud_instance
),并关联image_id
、instance_type
、zone_id
参数就可以实现对instance_type
、zone_id
的约束。
{
"ALIYUN::ROS::Interface": {
"ResourcesForParameterConstraints": {
"instance": {
"Type": "ALIYUN::ECS::Instance",
"Properties": {
"InstanceType": {
"Ref": "instance_type"
},
"ImageId": "centos_7_9_x64_20G_alibase_20210318.vhd",
"VSwitchId": {
"Ref": "vswitch_id"
},
"ZoneId": {
"Ref": "zone_id"
},
"SystemDiskCategory": {
"Ref": "system_disk_category"
},
"SystemDiskSize": {
"Ref": "system_disk_size"
},
"DataDiskCategory": {
"Ref": "data_disk_category"
},
"DataDiskSize": {
"Ref": "data_disk_size"
}
}
}
},
"ParameterGroups": [
{
"Parameters": [
"pay_type",
"pay_period_unit",
"pay_period"
],
"Label": {
"default": {
"en": "Payment mode Configuration",
"zh-cn": "付费模式配置"
}
}
},
{
"Parameters": [
"zone_id"
],
"Label": {
"default": {
"zh-cn": "可用区配置",
"en": "Zone Configuration"
}
}
},
{
"Parameters": [
"vpc_cidr_block",
"vswitch_cidr_block"
],
"Label": {
"default": {
"zh-cn": "选择已有基础资源配置",
"en": "Choose existing Infrastructure Configuration"
}
}
},
{
"Parameters": [
"instance_type",
"system_disk_category",
"system_disk_size",
"data_disk_category",
"data_disk_size",
"instance_password"
],
"Label": {
"default": {
"en": "Instance",
"zh-cn": "ECS实例配置"
}
}
}
]
}
}
完整模板示例
ROSTemplateFormatVersion: '2015-09-01'
Transform: Aliyun::Terraform-v1.2
Workspace:
.metadata: |-
{
"ALIYUN::ROS::Interface": {
"ResourcesForParameterConstraints": {
"instance": {
"Type": "ALIYUN::ECS::Instance",
"Properties": {
"InstanceType": {
"Ref": "instance_type"
},
"ImageId": "centos_7_9_x64_20G_alibase_20210318.vhd",
"VSwitchId": {
"Ref": "vswitch_id"
},
"ZoneId": {
"Ref": "zone_id"
},
"SystemDiskCategory": {
"Ref": "system_disk_category"
},
"SystemDiskSize": {
"Ref": "system_disk_size"
},
"DataDiskCategory": {
"Ref": "data_disk_category"
},
"DataDiskSize": {
"Ref": "data_disk_size"
}
}
}
},
"ParameterGroups": [
{
"Parameters": [
"pay_type",
"pay_period_unit",
"pay_period"
],
"Label": {
"default": {
"en": "Payment mode Configuration",
"zh-cn": "付费模式配置"
}
}
},
{
"Parameters": [
"zone_id"
],
"Label": {
"default": {
"zh-cn": "可用区配置",
"en": "Zone Configuration"
}
}
},
{
"Parameters": [
"vpc_cidr_block",
"vswitch_cidr_block"
],
"Label": {
"default": {
"zh-cn": "选择已有基础资源配置",
"en": "Choose existing Infrastructure Configuration"
}
}
},
{
"Parameters": [
"instance_type",
"system_disk_category",
"system_disk_size",
"data_disk_category",
"data_disk_size",
"instance_password"
],
"Label": {
"default": {
"en": "Instance",
"zh-cn": "ECS实例配置"
}
}
}
]
}
}
main.tf: |-
variable "pay_type" {
type = string
default = "PostPaid"
description = <<EOT
{
"Label": {
"en": "ECS Instance Charge Type",
"zh-cn": "付费类型"
},
"AllowedValues": [
"PostPaid",
"PrePaid"
],
"AssociationProperty": "ChargeType",
"AssociationPropertyMetadata": {
"LocaleKey": "InstanceChargeType"
}
}
EOT
}
variable "pay_period_unit" {
type = string
default = "Month"
description = <<EOT
{
"Label": {
"en": "Pay Period Unit",
"zh-cn": "购买资源时长周期"
},
"AllowedValues": [
"Month",
"Year"
],
"AssociationProperty": "PayPeriodUnit",
"AssociationPropertyMetadata": {
"Visible": {
"Condition": {
"Fn::Not": {
"Fn::Equals": [
"$${pay_type}",
"PostPaid"
]
}
}
}
}
}
EOT
}
variable "pay_period" {
type = number
default = 1
description = <<EOT
{
"Label": {
"en": "Period",
"zh-cn": "购买资源时长"
},
"AllowedValues": [
1,
2,
3,
4,
5,
6,
7,
8,
9
],
"AssociationProperty": "PayPeriod",
"AssociationPropertyMetadata": {
"Visible": {
"Condition": {
"Fn::Or": [
{
"Fn::Equals": [
"$${pay_type}",
"PrePaid"
]
},
{
"Fn::Equals": [
"$${pay_type}",
"undefined"
]
}
]
}
}
}
}
EOT
}
variable "zone_id" {
type = string
description = <<EOT
{
"AssociationProperty": "ALIYUN::ECS::Instance:ZoneId",
"Description": {
"zh-cn": "可用区ID。<br><b>注: <font color='blue'>选择前请确认该可用区是否支持创建ECS资源的规格,建议与其他交换机可用区不同。</font></b>",
"en": "Availability Zone ID.<br><b>notex:<font color='blue'>before selecting, please confirm that the Availability Zone supports the specification of creating ECS resources,which is recommended to be different from other VSwitch Availability Zone.</font></b>"
},
"Label": {
"zh-cn": "交换机可用区",
"en": "VSwitch Availability Zone"
}
}
EOT
}
variable "vpc_cidr_block" {
type = string
default = "192.168.0.0/16"
description = <<EOT
{
"Label": {
"zh-cn": "专有网络网段",
"en": "VPC CIDR Block"
},
"Description": {
"zh-cn": "新建专有网络IP地址段范围,推荐使用以下的IP地址段<br><font color='green'>[10.0.0.0/8]</font><br><font color='green'>[172.16.0.0/12]</font><br><font color='green'>[192.168.0.0/16]。</font>",
"en": "New proprietary network IP address segment range, recommended use of the following IP address segments<br><font color='green'>[10.0.0.0/8]</font><br><font color='green'>[172.16.0.0/12]</font><br><font color='green'>[192.168.0.0/16].</font>"
}
}
EOT
}
variable "vswitch_cidr_block" {
type = string
default = "192.168.0.0/24"
description = <<EOT
{
"Description": {
"zh-cn": "必须是所属专有网络的子网段,并且没有被其他交换机占用。",
"en": "Must be a sub-network segment of the proprietary network and is not occupied by other VSwitches."
},
"Label": {
"zh-cn": "交换机网段",
"en": "VSwitch CIDR Block"
}
}
EOT
}
variable "instance_type" {
type = string
description = <<EOT
{
"Label": {
"zh-cn": "实例规格",
"en": "Instance Type"
},
"AssociationProperty": "ALIYUN::ECS::Instance::InstanceType",
"AssociationPropertyMetadata": {
"InstanceChargeType": "$${pay_type}",
"ZoneId": "$${zone_id}"
}
}
EOT
}
variable "system_disk_category" {
type = string
description = <<EOT
{
"Description": {
"en": "<font color='blue'><b>Optional values:</b></font><br>[cloud_efficiency: <font color='green'>Efficient Cloud Disk</font>]<br>[cloud_ssd: <font color='green'>SSD Cloud Disk</font>]<br>[cloud_essd: <font color='green'>ESSD Cloud Disk</font>]<br>[cloud: <font color='green'>Cloud Disk</font>]<br>[ephemeral_ssd: <font color='green'>Local SSD Cloud Disk</font>]",
"zh-cn": "<font color='blue'><b>可选值:</b></font><br>[cloud_efficiency: <font color='green'>高效云盘</font>]<br>[cloud_ssd: <font color='green'>SSD云盘</font>]<br>[cloud_essd: <font color='green'>ESSD云盘</font>]<br>[cloud: <font color='green'>普通云盘</font>]<br>[ephemeral_ssd: <font color='green'>本地SSD盘</font>]"
},
"AssociationProperty": "ALIYUN::ECS::Disk::SystemDiskCategory",
"AssociationPropertyMetadata": {
"ZoneId": "$${zone_id}",
"InstanceType": "$${instance_type}"
},
"Label": {
"en": "System Disk Type",
"zh-cn": "系统盘类型"
}
}
EOT
}
variable "system_disk_size" {
type = number
default = 40
description = <<EOT
{
"Description": {
"zh-cn": "系统盘大小,取值范围:40~500,单位:GB。",
"en": "System disk size, range of values: 40~500, units: GB."
},
"Label": {
"zh-cn": "系统盘空间",
"en": "System Disk Space"
}
}
EOT
}
variable "data_disk_category" {
type = string
description = <<EOT
{
"Label": {
"zh-cn": "数据盘类型",
"en": "Data Disk Type"
},
"Description": {
"zh-cn": "<font color='blue'><b>可选值:</b></font><br>[cloud_efficiency: <font color='green'>高效云盘</font>]<br>[cloud_ssd: <font color='green'>SSD云盘</font>]<br>[cloud_essd: <font color='green'>ESSD云盘</font>]<br>[cloud: <font color='green'>普通云盘</font>]",
"en": "<font color='blue'><b>Optional values:</b></font><br>[cloud_efficiency: <font color='green'>Efficient Cloud Disk</font>]<br>[cloud_ssd: <font color='green'>SSD Cloud Disk</font>]<br>[cloud_essd: <font color='green'>ESSD Cloud Disk</font>]<br>[cloud: <font color='green'>Cloud Disk</font>]"
},
"AssociationProperty": "ALIYUN::ECS::Disk::DataDiskCategory",
"AssociationPropertyMetadata": {
"ZoneId": "$${zone_id}",
"InstanceType": "$${instance_type}"
}
}
EOT
}
variable "data_disk_size" {
type = number
default = 100
description = <<EOT
{
"Description": {
"zh-cn": "ECS实例数据盘大小,单位为GiB。取值范围:20~32768。",
"en": "ECS Instance disk size, range of values: 20~32768, units: GB."
},
"MaxValue": 32768,
"MinValue": 20,
"Label": {
"zh-cn": "数据盘空间",
"en": "Data Disk Space"
}
}
EOT
}
variable "instance_password" {
type = string
sensitive = true
description = <<EOT
{
"Description": {
"en": "Server login password, Length 8~30, must contain three(Capital letters, lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;<>,.?/ Special symbol in).",
"zh-cn": "登录密码,长度8~30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;<>,.?/ 中的特殊符号)。"
},
"Label": {
"en": "Instance Password",
"zh-cn": "登录密码"
},
"ConstraintDescription": {
"en": "Length 8~30, must contain three(Capital letters, lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;<>,.?/ Special symbol in).",
"zh-cn": "长度8~30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;<>,.?/ 中的特殊符号)。"
},
"AssociationProperty": "ALIYUN::ECS::Instance::Password",
"AllowedPattern": "^[a-zA-Z0-9-\\(\\)\\`\\~\\!\\@\\#\\$\\%\\^\\&\\*\\_\\-\\+\\=\\|\\{\\}\\[\\]\\:\\;\\<\\>\\,\\.\\?\\/]*$",
"MinLength": 8,
"MaxLength": 30
}
EOT
}
# 默认资源名称。
locals {
production_name = "nginx"
new_scg_name = "sg-for-${local.production_name}"
new_host_name = "app-for-${local.production_name}"
}
resource "alicloud_vpc" "vpc" {
cidr_block = var.vpc_cidr_block
}
resource "alicloud_vswitch" "vsw" {
vpc_id = alicloud_vpc.vpc.id
cidr_block = var.vswitch_cidr_block
zone_id = var.zone_id
}
# 安全组基本信息配置
resource "alicloud_security_group" "security_group" {
name = local.new_scg_name
description = "nginx scg"
vpc_id = alicloud_vpc.vpc.id
}
# 安全组入口端1
resource "alicloud_security_group_rule" "allow_ssh" {
security_group_id = alicloud_security_group.security_group.id
type = "ingress"
cidr_ip = "0.0.0.0/0"
policy = "accept"
ip_protocol = "tcp"
port_range = "22/22"
priority = 1
}
# 安全组入口端2
resource "alicloud_security_group_rule" "allow_web" {
security_group_id = alicloud_security_group.security_group.id
type = "ingress"
cidr_ip = "0.0.0.0/0"
policy = "accept"
ip_protocol = "tcp"
port_range = "80/443"
priority = 1
}
# 安全组出口端
resource "alicloud_security_group_rule" "allow_egress" {
security_group_id = alicloud_security_group.security_group.id
type = "egress"
cidr_ip = "0.0.0.0/0"
policy = "accept"
ip_protocol = "tcp"
port_range = "1/65535"
priority = 1
}
# 实例基本配置
resource "alicloud_instance" "instance" {
availability_zone = var.zone_id
security_groups = [alicloud_security_group.security_group.id]
# series III
host_name = local.new_host_name
instance_type = var.instance_type
system_disk_size = var.system_disk_size
system_disk_category = var.system_disk_category
image_id = "centos_7_9_x64_20G_alibase_20210318.vhd"
vswitch_id = alicloud_vswitch.vsw.id
password = var.instance_password
internet_charge_type = "PayByTraffic"
internet_max_bandwidth_out = 30
instance_charge_type = var.pay_type
period = var.pay_period
period_unit = var.pay_period_unit
user_data = file("${path.cwd}/user-data.sh")
data_disks {
size = var.data_disk_size
category = var.data_disk_category
}
}
# 返回Nginx的IP地址
output "nginx_ip" {
value = "http://${alicloud_instance.instance.public_ip}:8080"
}
user-data.sh: |-
#!/bin/bash -v
# 挂盘到/disk1
cat >> /root/InitDataDisk.sh << "EOF"
#!/bin/bash
echo "p
n
p
w
" | fdisk -u /dev/vdb
EOF
/bin/bash /root/InitDataDisk.sh
rm -f /root/InitDataDisk.sh
mkfs -t ext4 /dev/vdb1
cp /etc/fstab /etc/fstab.bak
mkdir /disk1
echo `blkid /dev/vdb1 | awk '{print $2}' | sed 's/\\\"//g'` /disk1 ext4 defaults 0 0 >> /etc/fstab
mount -a
# 这里配置安装脚本
yum install -y nginx
# 配置启动脚本
/usr/sbin/nginx