このトピックでは、Terraform テンプレートを使用して Elastic Compute Service (ECS) インスタンスに NGINX をデプロイする方法について説明します。
前提条件
ROS テンプレートの構文と構造について理解している必要があります。 詳細については、「テンプレートの概要」をご参照ください。
サンプルシナリオ
Alibaba Cloud 管理コンソールで VPC (Virtual Private Cloud) ネットワークタイプの ECS インスタンスを作成して、NGINX をデプロイします。

使用上の注意
上記のリソースのリソースタイプを表示して、各リソースプロパティの詳細を取得できます。 詳細については、「リソースタイプを表示する」をご参照ください。
各リソースタイプのトピックでは、必須およびオプションのリソースプロパティに関する情報を提供しています。 Terraform テンプレートの Resources セクションでは、使用するリソースタイプの必須リソースプロパティを宣言する必要があります。
テンプレートを作成する
ビジネスに必要なリソースタイプを見つけるには、「サービス別リソースタイプ一覧」をご参照ください。
この例では、次のリソースタイプが使用されています: alicloud_vpc、alicloud_instance、alicloud_vswitch、alicloud_security_group、および alicloud_security_group_rule。 NGINX は、ECS インスタンスの作成と同時にデプロイされます。
テンプレートでリソースとリソースの依存関係を定義する
基本的なネットワークリソースを定義する
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 インスタンスを定義できます。
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 インスタンスで実行する必要がある初期化スクリプトを提供します。 初期化スクリプトの例:
#!/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]
# シリーズ 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]
# シリーズ 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 テンプレートを変換する
ROS コンソールで Terraform テンプレートを ROS テンプレートに変換できます。 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] # シリーズ 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
パラメータグループを追加し、パラメータ設定を動的に取得する
上記のテンプレートには、ビジネスに必要なリソースとリソースの依存関係が含まれています。 テンプレートでは、system_disk_category の値は静的です。 別のリージョンでこのテンプレートを使用してスタックを作成およびデプロイする場合、テンプレートの内容を変更し、リソースプロパティを変更する必要があります。
この場合、テンプレートに Parameters セクションを追加して、テンプレートの柔軟性と再利用性を向上させることができます。
パラメータグループを追加する
メタデータを使用して、Parameters セクションで定義されているパラメータをグループ化し、各グループのラベルを定義できます。 詳細については、「メタデータ」をご参照ください。
パラメータに対応するリソースに基づいてパラメータをグループ化できます。 次の表では、上記のテンプレートを例として使用して、パラメータをグループ化する方法について説明します。
グループ | リソース | パラメータ |
基本的なネットワーク構成 |
|
|
ECS インスタンス構成 |
|
|
Terraform タブで、.metadata ファイルを作成し、次の内容を入力します。
{
"ALIYUN::ROS::Interface": {
"ParameterGroups": [
{
"Parameters": [
"pay_type",
"pay_period_unit",
"pay_period"
],
"Label": {
"default": {
"en": "Payment mode Configuration",
"ja": "支払いモード構成"
}
}
},
{
"Parameters": [
"zone_id"
],
"Label": {
"default": {
"ja": "ゾーン構成",
"en": "Zone Configuration"
}
}
},
{
"Parameters": [
"vpc_cidr_block",
"vswitch_cidr_block"
],
"Label": {
"default": {
"ja": "既存のインフラストラクチャ構成を選択",
"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",
"ja": "インスタンス"
}
}
}
]
}
}パラメータ設定を動的に取得する
次のセクションでは、instance パラメータを例として使用して、パラメータ設定を動的に取得する方法について説明します。 ROS コンソールで instance パラメータのフィルタ条件を設定し、さまざまなフィルタ条件に基づいてパラメータの設定を動的に取得する場合、instance パラメータに対応する ALIYUN::ECS::Instance リソースタイプを使用して、ROS ドキュメントの「AssociationProperty and AssociationPropertyMetadata」トピックで instance パラメータでサポートされている AssociationProperty の値をクエリできます。 次に、ZoneId が AssociationProperty のフィルタ条件として使用される場合、instance パラメータでサポートされている AssociationPropertyMetadata の値をクエリできます。 この例では、instance パラメータでサポートされている AssociationProperty の値は ALIYUN::ECS::Instance::InstanceType です。 詳細については、「AssociationProperty and AssociationPropertyMetadata」をご参照ください。
Terraform タブで、main.tf ファイルに次の内容を入力します。
variable "pay_type" {
type = string
default = "PostPaid"
description = <<EOT
{
"Label": {
"en": "ECS Instance Charge Type",
"ja": "ECS インスタンス料金タイプ"
},
"AllowedValues": [
"PostPaid",
"PrePaid"
],
"AssociationProperty": "ChargeType",
"AssociationPropertyMetadata": {
"LocaleKey": "InstanceChargeType"
}
}
EOT
}
variable "pay_period_unit" {
type = string
default = "Month"
description = <<EOT
{
"Label": {
"en": "Pay Period Unit",
"ja": "支払い期間単位"
},
"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",
"ja": "期間"
},
"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": {
</font></b>",
"en": "Availability Zone ID.テンプレートパラメータの依存関係と制約を追加する
上記のテンプレートは 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 に関連付けて制約を追加する必要があります。
{
"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",
"ja": "支払いモード構成"
}
}
},
{
"Parameters": [
"zone_id"
],
"Label": {
"default": {
"ja": "ゾーン構成",
"en": "Zone Configuration"
}
}
},
{
"Parameters": [
"vpc_cidr_block",
"vswitch_cidr_block"
],
"Label": {
"default": {
"ja": "既存のインフラストラクチャ構成を選択",
"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",
"ja": "インスタンス"
}
}
}
]
}
}完全なテンプレートの例
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",
"ja": "支払いモード構成"
}
}
},
{
"Parameters": [
"zone_id"
],
"Label": {
"default": {
"ja": "ゾーン構成",
"en": "Zone Configuration"
}
}
},
{
"Parameters": [
"vpc_cidr_block",
"vswitch_cidr_block"
],
"Label": {
"default": {
"ja": "既存のインフラストラクチャ構成を選択",
"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",
"ja": "インスタンス"
}
}
}
]
}
}
main.tf: |-
variable "pay_type" {
type = string
default = "PostPaid"
description = <<EOT
{
"Label": {
"en": "ECS Instance Charge Type",
"ja": "ECS インスタンス料金タイプ"
},
"AllowedValues": [
"PostPaid",
"PrePaid"
],
"AssociationProperty": "ChargeType",
"AssociationPropertyMetadata": {
"LocaleKey": "InstanceChargeType"
}
}
EOT
}
variable "pay_period_unit" {
type = string
default = "Month"
description = <<EOT
{
"Label": {
"en": "Pay Period Unit",
"ja": "支払い期間単位"
},
"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",
"ja": "期間"
},
"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": {
</font></b>",
"en": "Availability Zone ID.