[Alibaba Cloud] VPC + ECS作成ハンズオン（Terraform編）

2019年5月22日に [【初心者向け】Alibaba Cloud CLIハンズオン](https://alibabacloud.connpass.com/event/130315/) が開催されました。
その際には、[[Alibaba Cloud] VPC + ECS作成ハンズオン](https://qiita.com/nago3/items/3a2908bebb4794810fc7)の資料が使われました。

さて、本ページでは、同じ内容の構築をTerraformを使ってやってみます。
どんな構成を作るかなどの説明は省略していますので、まずは上記のハンズオン資料をざっと読んでいただければと思います。

# [ちょっと前置き] Alibaba CloudとTerraformの関係

ご存知の方も多いと思いますが、Terraformというツールは、HashiCorpという会社が開発しています。Alibabaが開発しているわけではありません。
それなのにAlibaba Cloudのサイトでは、公式ツールであるかのように紹介されています。
[IaC - Terraform ソリューション](https://jp.alibabacloud.com/solutions/devops/terraform)

なぜかというと、TerraformでAlibaba Cloudを操作するための [Alicloud Provider](https://www.terraform.io/docs/providers/alicloud/index.html) プラグインをAlibaba Cloudの中の人がメインで開発しているようなんです。

その証拠にAlicloud Providerの開発は、以前はalibabaの保有するGitHubリポジトリで行われていたようです。

- 以前：https://github.com/alibaba/terraform-provider
- 現在：https://github.com/terraform-providers/terraform-provider-alicloud

ということで、半ば公式ツールと考えていいのでは無いかと思います。

# Terraformのインストール

2019年6月5日の時点で alicloud provider は、Terraformの最新の0.12系に対応してません。
今回はバージョン0.11.14を使いました。

Terraformの導入がまだの方は、下記を参考に入れていただければと思います。

```
# Terraformのバージョン管理ツールをインストール
brew install tfenv

# インストール可能なバージョンを確認
tfenv list-remote

# Terraformの指定バージョンをインストール
tfenv install 0.11.14

# Terraformの使用するバージョンを指定する
tfenv use 0.11.14
```

# 作業ディレクトリの作成

```
# 適当な作業ディレクトリを作成し、移動する
mkdir handson_alibaba
cd handson_alibaba
```

```
# 初期化する
terraform init
```

# 環境変数の設定

クレデンシャルは環境変数で設定します。
毎回入力するのは面倒なので、例えば~/.bash_profileなどに記載するといいと思います。

```~/.bash_profile
export ALICLOUD_ACCESS_KEY="XXXXXXXXXXXXX"
export ALICLOUD_SECRET_KEY="XXXXXXXXXXXXX"
```

# Terraformコードの作成

拡張子がtfのファイルを作成します。今回はmain.tfという名前のファイルを作成します。

```main.tf
provider "alicloud" {
  region     = "ap-northeast-1"
}

# VPCの作成
resource "alicloud_vpc" "vpc" {
  name        = "VPC"
  description = "Aliyun VPC"
  cidr_block  = "172.16.0.0/16"
}

# vSwitchの作成
resource "alicloud_vswitch" "vsw" {
  vpc_id            = "${alicloud_vpc.vpc.id}"
  name              = "VSw"
  description       = "Aliyun VSwitch"
  cidr_block        = "172.16.1.0/24"
  availability_zone = "ap-northeast-1a"
}

# Security Groupの作成
resource "alicloud_security_group" "group" {
  name        = "SG"
  description = "Aliyun SG"
  vpc_id = "${alicloud_vpc.vpc.id}"
}

# Security Group Ruleの作成
resource "alicloud_security_group_rule" "allow_http" {
  security_group_id = "${alicloud_security_group.group.id}"
  type              = "ingress"
  ip_protocol       = "tcp"
  nic_type          = "intranet"
  policy            = "accept"
  port_range        = "80/80"
  cidr_ip           = "0.0.0.0/0"
}

# ECSインスタンスの作成
resource "alicloud_instance" "ecs_instance" {
  description          = "Alicloud CLI INSTANCE"
  instance_name        = "INSTANCE"
  availability_zone    = "ap-northeast-1a"
  security_groups      = ["${alicloud_security_group.group.id}"]
  image_id             = "alinux_17_01_64_20G_cloudinit_20171222.vhd"
  instance_type        = "ecs.n4.small"
  instance_charge_type = "PostPaid"
  vswitch_id           = "${alicloud_vswitch.vsw.id}"
  private_ip           = "172.16.1.10"
  internet_charge_type = "PayByTraffic"
  system_disk_category = "cloud_efficiency"
  system_disk_size     = 40
  user_data            = "${file("provisioning.sh")}"
}

# EIPの作成
resource "alicloud_eip" "eip" {
  bandwidth            = "1"
  internet_charge_type = "PayByTraffic"
  instance_charge_type = "PostPaid"
}

# ECSインスタンスとEIPの関連付け
resource "alicloud_eip_association" "eip_asso" {
  allocation_id = "${alicloud_eip.eip.id}"
  instance_id   = "${alicloud_instance.ecs_instance.id}"
}
```

各リソースの細かい設定はこちらで確認してください。
https://www.terraform.io/docs/providers/alicloud/index.html

# UserData

UserDataは別ファイルで作成します。

```provisioning.sh
#!/bin/sh
yum install -y httpd
systemctl start httpd
systemctl enable httpd
```

# 実行

実行例を記載しておきます。
実際は`Enter a value` というところで停止するので、問題なさそうなら`yes`と入力してください。

```
$ terraform apply
alicloud_eip.eip: Refreshing state... (ID: eip-6wetmlwy3xdor2qyjabo9)
alicloud_vpc.vpc: Refreshing state... (ID: vpc-6wetev6m5kj731bb1nmfj)
alicloud_vswitch.vsw: Refreshing state... (ID: vsw-6wesgu98xpwlfbkesqhci)
alicloud_security_group.group: Refreshing state... (ID: sg-6we9t5mym5czh4v7ubsf)
alicloud_instance.ecs_instance: Refreshing state... (ID: i-6we56uzuhtrowi0fkpdp)
alicloud_security_group_rule.allow_http: Refreshing state... (ID: sg-6we9t5mym5czh4v7ubsf:ingress:tcp:80/80:intranet:0.0.0.0/0:accept:1)
alicloud_eip_association.eip_asso: Refreshing state... (ID: eip-6wetmlwy3xdor2qyjabo9:i-6we56uzuhtrowi0fkpdp)

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
alieaters_code_1$ terraform destroy
alicloud_eip.eip: Refreshing state... (ID: eip-6wetmlwy3xdor2qyjabo9)
alicloud_vpc.vpc: Refreshing state... (ID: vpc-6wetev6m5kj731bb1nmfj)
alicloud_security_group.group: Refreshing state... (ID: sg-6we9t5mym5czh4v7ubsf)
alicloud_vswitch.vsw: Refreshing state... (ID: vsw-6wesgu98xpwlfbkesqhci)
alicloud_security_group_rule.allow_http: Refreshing state... (ID: sg-6we9t5mym5czh4v7ubsf:ingress:tcp:80/80:intranet:0.0.0.0/0:accept:1)
alicloud_instance.ecs_instance: Refreshing state... (ID: i-6we56uzuhtrowi0fkpdp)
alicloud_eip_association.eip_asso: Refreshing state... (ID: eip-6wetmlwy3xdor2qyjabo9:i-6we56uzuhtrowi0fkpdp)

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  - alicloud_eip.eip

  - alicloud_eip_association.eip_asso

  - alicloud_instance.ecs_instance

  - alicloud_security_group.group

  - alicloud_security_group_rule.allow_http

  - alicloud_vpc.vpc

  - alicloud_vswitch.vsw


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

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

alicloud_security_group_rule.allow_http: Destroying... (ID: sg-6we9t5mym5czh4v7ubsf:ingress:tcp:80/80:intranet:0.0.0.0/0:accept:1)
alicloud_eip_association.eip_asso: Destroying... (ID: eip-6wetmlwy3xdor2qyjabo9:i-6we56uzuhtrowi0fkpdp)
alicloud_security_group_rule.allow_http: Destruction complete after 2s
alicloud_eip_association.eip_asso: Destruction complete after 6s
alicloud_instance.ecs_instance: Destroying... (ID: i-6we56uzuhtrowi0fkpdp)
alicloud_eip.eip: Destroying... (ID: eip-6wetmlwy3xdor2qyjabo9)
alicloud_eip.eip: Destruction complete after 1s
alicloud_instance.ecs_instance: Still destroying... (ID: i-6we56uzuhtrowi0fkpdp, 10s elapsed)
alicloud_instance.ecs_instance: Still destroying... (ID: i-6we56uzuhtrowi0fkpdp, 20s elapsed)
alicloud_instance.ecs_instance: Destruction complete after 22s
alicloud_security_group.group: Destroying... (ID: sg-6we9t5mym5czh4v7ubsf)
alicloud_vswitch.vsw: Destroying... (ID: vsw-6wesgu98xpwlfbkesqhci)
alicloud_security_group.group: Still destroying... (ID: sg-6we9t5mym5czh4v7ubsf, 10s elapsed)
alicloud_vswitch.vsw: Still destroying... (ID: vsw-6wesgu98xpwlfbkesqhci, 10s elapsed)
alicloud_vswitch.vsw: Destruction complete after 18s
alicloud_security_group.group: Destruction complete after 19s
alicloud_vpc.vpc: Destroying... (ID: vpc-6wetev6m5kj731bb1nmfj)
alicloud_vpc.vpc: Destruction complete after 1s

Destroy complete! Resources: 7 destroyed.
```

作成されたら、EIPへブラウザでアクセスしてみましょう。
成功していれば、応答があるはずです。

# 削除

ハンズオンが終わったら、下記コマンドで綺麗さっぱり削除しましょう。

```
terraform destroy
```