Terraform文法について

  前章は 簡単なWebサーバを立ち上げるというサンプルプロジェクトを実行しました。うち、Terraformには様々な記載文法がありますので、把握した方がいい部分だけ説明します。


1. Configuration Syntax

  Terraformのコード構成要素、コードの構成文の書き方です。Terraformの利用ガイドラインに沿って記載してみてください。Terraformのバージョンによっては書き方が異なる場合がありますので、注意が必要です。

# project_nameを宣言
variable "project_name" {
}


/* alicloud_vpcを設定
  変数project_nameを呼び出す  */
resource "alicloud_vpc" "vpc" {
  name = "${var.project_name}-vpc"
  cidr_block = "192.168.1.0/24"
}

他、構成文の書き方もありますが、ひとまずは上記のを抑えれば大抵問題ないです。


2. Interpolation Syntax

  変数・関数・属性など、コード補充機能です。

その他、補充機能はTerraformバージョンごとに色々追加されていますので、最新版はこちらを参照してみてください。


3. 外部変数

  上記にも記述しましたが、RAMなどの情報を他ユーザへ渡したくない場合、別途設定ファイル confing.tfvars へ記載します。例えば以下の別途設定ファイル confing.tfvars、および実行ファイル main.tf があるとします。

▼ 別途設定ファイル confing.tfvars の中身

access_key = "xxxxxxxxxxxxxxxxxx"
secret_key = "xxxxxxxxxxxxxxxxxx"
region = "ap-northeast-1"
zone = "ap-northeast-1a"

▼ 実行ファイル main.tf の中身

variable "access_key" {}
variable "secret_key" {}
variable "region" {}
variable "zone" {}

provider "alicloud" {
  access_key = "${var.access_key}"
  secret_key = "${var.secret_key}"
  region = "${var.region}"
}

これをコマンド実行時に「 -var-file=”<ファイル名>“」引数オプションで設定ファイルを外部変数・リンクし実行します。

$ terraform plan -var-file="confing.tfvars"

すると、RAMなどアカウント情報を別ファイルに残したまま、リソース作成されます。


4 ローカル値

  localsを使うとローカル変数が定義できます。localsで囲んだ変数を宣言することで、ローカル変数を使うことができます。

▼ ローカル変数の定義

locals {
   select_instance_type = "ecs.n4.small"
}

resource "alicloud_instance" "ECS_instance" {
  instance_name   = "ECS_instance_for_terraform"
  host_name       = "ECS_instance_for_terraform"
  instance_type   = var.select_instance_type
  image_id        = "centos_7_04_64_20G_alibase_201701015.vhd"
  system_disk_category = "cloud_efficiency"
  security_groups = ["${alicloud_security_group.sg.id}"]
  availability_zone = "${var.zone}"
  vswitch_id = "${alicloud_vswitch.vsw.id}"
}


5. アウトプット

  outputを使うとアウトプットが定義できます。定義すると、apply実行時にターミナルで値を確認したり、リソース・モジュールから値を取得できます。

▼ アウトプット値の定義

resource "alicloud_instance" "ECS_instance" {
  instance_name   = "ECS_instance_for_terraform"
  host_name       = "ECS_instance_for_terraform"
  instance_type   = "ecs.n4.small"
  image_id        = "centos_7_04_64_20G_alibase_201701015.vhd"
  system_disk_category = "cloud_efficiency"
  security_groups = ["${alicloud_security_group.sg.id}"]
  availability_zone = "${var.zone}"
  vswitch_id = "${alicloud_vswitch.vsw.id}"
}

output "ECS_instance_id" {
  value = alicloud_instance.ECS_instance.instance_type
}

applyすると、実行結果の最後に、作成されたインスタンスの type が出力されます。

$ terraform apply
.....
Outputs:
ecs.n4.small


6. 条件分岐

  Terraformは条件分岐が使えます。先にvariable変数を記載したあと、resource構文にてvariable変数を選定します。例えば環境に応じてインスタンスタイプを切り替えたい場合は、以下のように書きます。

▼ 条件分岐の記載方法

variable "instance_pattern" {}

resource "alicloud_instance" "ECS_instance" {
  instance_name   = "ECS_instance_for_terraform"
  host_name       = "ECS_instance_for_terraform"
  instance_type   = var.instance_pattern == "dev" ? "ecs.n4.small" : "ecs.n4.2xlarge"
  image_id        = "centos_7_04_64_20G_alibase_201701015.vhd"
  system_disk_category = "cloud_efficiency"
  security_groups = ["${alicloud_security_group.sg.id}"]
  availability_zone = "${var.zone}"
  vswitch_id = "${alicloud_vswitch.vsw.id}"
}

そのあと、実行するときは引数でenv変数を指定することで、条件分岐してくれます。

$ terraform plan -var-file="confing.tfvars" -var 'instance_pattern=dev'
$ terraform apply -var-file="confing.tfvars" -var 'instance_pattern=production'


7. 組み込み関数

  Terraformからリソースを作成するときに、例えばApacheによるWebサーバを立ち上げたい場合、ECS起動後、Apacheのインストール、Webサーバ立ち上げ(httpd.service start)をする必要があります。 これらの処理を組み込み関数として、user_dataにて外部ファイル(shell)を読み取りユーザデータとして設定することができます。

▼ Webサーバのインストールスクリプトinstall.sh

#!/bin/bash -ex
wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm
rpm -ivh mysql-community-release-el7-5.noarch.rpm
yum -y install mysql-server httpd php php-mysql unzip
systemctl enable httpd
systemctl enable mysqld
systemctl start httpd
systemctl start mysqld
USER="root"
DATABASE="wordpress"
mysql -u $USER << EOF 
CREATE DATABASE $DATABASE; 
GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress'@'localhost' IDENTIFIED BY 'qweqwe123!';
EOF
if [ ! -f /var/www/html/latest.tar.gz ]; then
cd /var/www/html
wget -c http://wordpress.org/latest.tar.gz
tar -xzvf latest.tar.gz
mv wordpress/* /var/www/html/
chown -R apache.apache /var/www/html/
chmod -R 755 /var/www/html/
fi

これをuser_dataに入れて実行すると、install.shファイルを読み込み、Apacheをインストール、Webサーバを立ち上げてくれます。

▼ Webサーバのインストールスクリプトを読み込み、Webサーバを立ち上げてくれます

resource "alicloud_instance" "ECS_instance" {
  instance_name   = "ECS_instance_for_terraform"
  host_name       = "ECS_instance_for_terraform"
  instance_type   = var.instance_pattern == "dev" ? "ecs.n4.small" : "ecs.n4.2xlarge"
  image_id        = "centos_7_04_64_20G_alibase_201701015.vhd"
  system_disk_category = "cloud_efficiency"
  security_groups = ["${alicloud_security_group.sg.id}"]
  availability_zone = "${var.zone}"
  vswitch_id = "${alicloud_vswitch.vsw.id}"
  user_data     = file("./install.sh")
}


8. Countによる複数のリソース作成

  Terraformからリソースを作成するときに、同じ構成を複数台作成したい場合は、Countメタ変数を使うことで複数台作成することができます。

resource "alicloud_instance" "ECS_instance" {
  instance_name   = "ECS_instance_for_terraform"
  host_name       = "ECS_instance_for_terraform"
  instance_type   = var.instance_pattern == "dev" ? "ecs.n4.small" : "ecs.n4.2xlarge"
  image_id        = "centos_7_04_64_20G_alibase_201701015.vhd"
  system_disk_category = "cloud_efficiency"
  security_groups = ["${alicloud_security_group.sg.id}"]
  availability_zone = "${var.zone}"
  vswitch_id = "${alicloud_vswitch.vsw.id}"
  user_data     = file("./install.sh")
}


またCountを使えば、Map形式で複数宣言してる変数からkeyを指定して処理することもできます。

variable "cidr_block_ips" {
  default = {
    "0" = "192.168.1.0/24"
    "1" = "192.168.2.0/24"
    "2" = "192.168.3.0/24"
  }
}

resource "alicloud_vpc" "vpc" {
  count = "3"
  cidr_block = "${lookup(var.cidr_block_ips, count.index)}"
  ・・・
}


配列もCountを使って処理することもできます。

variable "ecs_name" {
  default = ["Web", "App", "Log"]
}

resource "alicloud_instance" "ECS_instance" {
  count = "3"
  instance_name   = "ECS_instance-${var.ecs_name[count.index]}"
  ・・・
}