Terraformの基本構文

TerraformではHCL2というTerraformの独自構文が用いられる。

その基本構文についてまとめていく

jsonに似ているが、

  • 簡単にプログラム(繰り返し、変数、定数などが使用できる)を作成できる
  • コメントが書ける
  • keyとvalueがコロンではなくイコールで指定
  • ヒアドキュメントが利用できる

基本的な構成は下記の通りである

Terraform言語について

<block_type> "<label_1>" "<label_2>" {
  key = value
  nested_block {
    ...
  }
}

早速、構成要素を見ていく

HCLの構成

HCL言語はブロックという単位から構成される

下記の定義ある場合はproviderやresourceという単位がブロックである(ブロックの入れ子も存在する)

provider "aws" {
  region  = "ap-northeast-1"
  profile = "admin" # SSOでログインしたプロファイル名
}
 
resource "aws_instance" "hello-world" {
  ami = "ami-0c1638aa346a43fe8"
  instance_type = "t2.micro"
 
  subnet_id = "subnet-0d6271c9f83a42751"
}

ブロックタイプとラベル

先ほどのproviderやresourceなどのブロックの先頭に記載してあるものをブロックタイプという

またブロックタイプごとに決まったラベルを与えることができる

下記は代表的なブロックタイプをまとめたものである

ブロック形式 構文例 ラベルの意味 用途
provider provider "aws" { ... } "aws": プロバイダ名(ラベル1) クラウドプロバイダの設定(AWS、GCPなど)
resource resource "aws_instance" "web" { ... } "aws_instance": リソースタイプ(ラベル1)
"web": インスタンス名(ラベル2)
実際のリソース(EC2、S3など)の作成
module module "vpc" { ... } "vpc": モジュールインスタンス名(ラベル1) 再利用可能な構成の呼び出し
data data "aws_ami" "latest" { ... } "aws_ami": データソース名(ラベル1)
"latest": インスタンス名(ラベル2)
既存の読み取り専用データの参照
variable variable "region" { ... } "region": 変数名(ラベル1) 変数の定義(外部から値を受け取る)
output output "instance_id" { ... } "instance_id": 出力名(ラベル1) 実行後に表示する出力値の定義
locals locals { name = "web" } (ラベルなし) ローカルスコープでの再利用変数の定義
terraform terraform { required_providers { ... } } (ラベルなし) Terraformの全体設定(バージョン、プロバイダ)
backend backend "s3" { ... }(terraform内) "s3": バックエンド種別(ラベル1) ステートファイルの保存先設定(S3、localなど)
provisioner provisioner "remote-exec" { ... } "remote-exec": プロビジョナータイプ(ラベル1) EC2などでのコマンド実行
lifecycle lifecycle { prevent_destroy = true } (ラベルなし) リソースの挙動制御(削除防止など)
dynamic dynamic "ingress" { ... } "ingress": 動的に生成するブロック名(ラベル1) 動的に繰り返しブロックを生成

ブロックにおける引数

ブロックタイプに対して引数を渡すことができる

下記の形式で引数を渡していく

key = value
 
# 例
resource "aws_instance" "hello-world" {
  ami = "ami-0c1638aa346a43fe8" # 引数
  instance_type = "t2.micro" # 引数
 
  subnet_id = "subnet-0d6271c9f83a42751" 引数
  tag = { # マップ型の引数
    name = "test"
  }
}

基本的には引数のキーは

  • スネークケース
  • 英小文字、数字、アンダースコアを使用
  • 引用符で囲まない

これらが推奨されている

記述があったかあやふやだが下記にスタイルガイドのリンクを置いておく

スタイルガイド

値の型

下記が値の方となる

Terraformの型

型(Type) 書き方例 説明 使用例
string "example" 文字列型。ダブルクオート(シングルでもOK)で囲む ami = "ami-12345678"
number 123, 3.14 数値型(整数・小数) instance_count = 2
bool true, false 真偽値型 enable_dns = true
list ["a", "b", "c"] 同じ型の値の順序付きリスト cidr_blocks = ["0.0.0.0/0"]
tuple ["a", 1, true] 型が異なる値の順序付きリスト(型順序を固定) output = ["abc", 123, false]
map { key1 = "val1", key2 = "val2" } キーと値のペアのコレクション(値の型は同じでなくても可) tags = { Name = "web", Env = "dev" }
object { name = string, port = number } 特定の構造をもつマップ型、フィールド名・型を定義 変数や出力の型指定に使用
set toSet(["a", "b", "c"]) 重複のない値の集合。順序は保証されない allowed_ips = toSet(["1.1.1.1"])
null null 明示的に値なしとする description = null

localsとvariablesブロック

HCLで利用可能な変数である

種類 説明
locals ローカル変数であり、プライベートな変数で外部から変更できない
variables 外部から変更可能な変数であり、コマンドラインのオプションやファイル指定で上書き可能

locals定義方法

localsブロックで宣言を行い、${local.<NAME>}で参照できる(外部から変更は不可)

locals {
  env = "dev"
}
 
<block_type> "<label_1>" "<label_2>" {
  tags {
    env = "${local.env}"
  }
}

variables定義方法

variableブロックで宣言を行い、${var.<NAME>}で参照できる(外部からの変更は可能)

宣言にはラベルを必要とし、ラベルには変数名を用いる

内部では型(値の型を参照してください)とデフォルト値を設定可能

variables "env" {
  type = string
  default = "dev"
}
 
<block_type> "<label_1>" "<label_2>" {
  tags {
    env = "${var.env}"
  }
}

変数の上書き方法

  1. 環境変数を使って上書きする
  2. 変数ファイルを使って上書きする
  3. コマンド引数を使って上書きする

この3種類の変更方法がある

上書き順は環境変数<変数ファイル<コマンド引数(同種の値であれば後勝ち)という形で右に行くほど、優先される

使い分けは?

環境変数

・実行ログに残らないため、鍵情報や環境依存情報などを設定する際に使用する。(tfstateに残ってしまう可能性はあるため注意)

変数ファイル

・git管理できるため、記録に残せる。プロビジョンとデータを切り離して管理することで変更しやすいソース管理ができる

コマンド引数

・実行ログに残るため、テストやデバッグで一時的に変更したい場合に利用

環境変数を使用した場合

variables "hoge" {
  type = string
  default = "None"
}

環境変数を設定し実行=>この際に変数が環境変数によって上書きされる。TF_VAR_変数名=値で上書き可能

export TF_VAR_hoge="hoge_hoge"
 
terraform apply

変数ファイルを使用した場合

variables "hoge" {
  type = string
  default = "None"
}
 

変数ファイルを用意する

terraform.tfvars

tfvars拡張子のファイルを用紙する

hoge = "hoge_hoge"

コマンド実行

terrafrom apply

コマンド引数を使用した場合

コマンドにvarオプションを指定して実行する

terraform apply -var hoge="hoge_hoge"

Terraformブロック

Terraformの設定に関わるブロックである

Terraformの構成は大きく分けて、

  • Terraform本体機能
  • プロバイダー(AWSやAzure,GCPなどに対応した機能)

に分かれる。

これらは個別にバージョンを持っており、それぞれのバージョン管理や制限が必要になる

主にTerraformブロックではバージョン管理を主として記載することとなる

Terraformのバージョン固定 => required_version

プロバイダのバージョン固定 => required_providers

を用いる

terraform {
    required_version = "x.x.x" # terraform のバージョンを設定 
  
    required_providers {
        aws = {
        source ="hashicorp/aws" # プロバイダー設定
        version = "x.x.x" # バージョン設定
        }
    }
}

プロバイダーブロック

プロバイダを使用する際に、リージョンや認証情報の設定などを行う

provider "aws" {
    region ="ap-northeast-1"
    profile = "admin" # AWSならCLIに設定したプロファイル名を指定できる
}

データブロック

Terraformで管理対象外となっているリソースの参照が可能

リソースによって記載方法が異なるので注意

outputブロックで設定してあるリソースの参照も可能

もっと詳しめな記事

data {}

Outputブロック

作成したリソースの情報を外部から参照できるようにするためのブロック

resource "aws_instance" "hello-world" {
  ami = "ami-0c1638aa346a43fe8"
  instance_type = "t2.micro"
}
 
outpur "ec2_instance_id" { # 呼び出し名=>ec2_instance_id
  value = aws_instance.hello_world.id # 出力する値
}

リソース間の参照

HCLでリソースを参照するための記述

<BLOCK_TYPE>.<LABEL_1>.<LABEL_2>
 
# ブロックタイプは省略可能なので、通常は下記で呼び出しすることが多そう
<LABEL_1>.<LABEL_2>
# 例えば、vpcのリソースを呼び出したいときは
resource "aws_vpc" "vpc" {
 ...
}
 
# 必要なブロック内で取得可能
aws_vpc.vpc.id

終わりに

すごくざっくりと記載しました。

今後はより実践向けの記事を書きたいなと思います。