🔰

Terraformを触ってみる

2022/05/22に公開

対象の OS は Mac です。

Terraform のインストール

Homebrew

公式サイトでは Homebrew を利用したインストールが案内されている。

$ brew tap hashicorp/tap
$ brew install hashicorp/tap/terraform

tfenv

tfenv というバージョンマネージャを利用してインストールすることもできる。
https://github.com/tfutils/tfenv

$ brew install tfenv

$ tfenv --version
=> tfenvのバージョン番号出力

$ tfenv list-remote
=> インストール可能なterraformのバージョン番号が一覧表示

$ tfenv install バージョン番号

# どのバージョンのterraformを利用するか指定する
$ tfenv use バージョン番号

$ terraform --vesion
=> terraformのバージョン番号出力

ディレクトリ配下に置いた.terrafrom-versionにバージョン番号を書いておけば、tfenv でインストール済みのバージョンに切り替わる。

エディタの拡張機能

terraform は HCL(HashiCorp Configuration Language)という DSL を利用して記述する。拡張機能を入れると、シンタックスハイライトやコード保管してくれる。

VSCode
https://marketplace.visualstudio.com/items?itemName=HashiCorp.terraform

Jet Brains IDE
https://plugins.jetbrains.com/plugin/7808-terraform-and-hcl

AWS に EC2 インスタンスを作成してみる

※ 事前に AWS の IAM ユーザを準備、アクセスキー、シークレットアクセスキーを設定して、aws コマンドが実行できるようにしておく必要がある。

# テスト用ディレクトリの作成
$ mkdir sample
$ cd sample

# terratermはmain.tfファイルに定義を記述する
$ touch main.tf

main.tfファイルに以下の定義を記述し保存。

# AWSのEC2でAmazon Linux2のt2.microインスタンスを作成する
resource "aws_instance" "example" {
  ami = "ami-02c3627b04781eada"
  instance_type = "t2.micro"
}
# terraformの初期化を行うコマンド
# 行に必要なproviderやmoduleのダウンロードが実行される。
$ terraform init

# 実行計画を表示するコマンド
# 追加や変更は実際には実行されない
$ terraform plan

# main.tfファイルで定義した内容を反映するコマンド
$ terraform apply

AWS の EC2 コンソールを確認すると、インスタンスが一つ作成されていることが確認できる。

# 作成したEC2インスタンスは削除しておく
$ terraform destroy

Provider

Terraform では AWS, GCP, Azure など複数のサービスに対応しており Provider を介して、main.tf で定義した内容が反映される。

Provider は main.tf ファイルに以下のように定義できる。

# AWSの例
provider "aws" {
  region = "us-east-1"
}

# GCPの例
provider "google" {
  project     = "my-project-id"
  region      = "us-central1"
}

Provider の記述を省略した場合は、定義の内容から必要な Provider を判定して、Provider をダウンロードする。

以下から各 Provider のドキュメントが確認可能。
https://registry.terraform.io/namespaces/hashicorp

HCL(HashiCorp Configuration Language)

tf ファイルは HCL という設定記述言語で記述する。

# "aws_instance" => resource_type
# "example"      => resource_name
# 以下の定義で作成したリソースはaws_insatance.exampleで参照できる
resource "aws_instance" "example" {
  ami           = "ami-02c3627b04781eada"
  instance_type = "t2.micro"
}

# outputは指定した内容をコマンドに出力する
# 以下は作成したEC2インスタンスのIDを出力する
output "instance_id" {
  value = aws_instance.example.id
}
# 実行結果に作成されたインスタンスのIDが出力される。
Outputs:

instance_id = "i-xxxxxxxxxx"

tfstate ファイル

一度 apply を実行すれば、terraform.tfstateファイルが作成される。
terraform はterraform.tfstateと、.tf ファイルを比較して、差分を抽出。差分のみを apply で実行するように振る舞う。

変数

利用方法

# variableを利用して変数を定義する
# default値を指定することができ、コマンド実行時に上書きも可能。
variable "instance_type" {
    default = "t3.micro"
}

# 利用するときはvar.変数名
resource "aws_instance" "example" {
    ami           = "ami-02c3627b04781eada"
    instance_type = var.instance_type
}

default 値を利用して実行

# defaultで指定しているt3.microでインスタンスが作成される
$ terraform plan

コマンド実行時に上書き

# 引数で渡したt2.microでインスタンスが作成される
$ terraform plan -var 'instance_type=t2.micro'

環境変数に設定

# 環境変数にTF_VAR_{変数名}で設定する
$ export TF_VAR_instance_type=t1.micro

# 環境変数に設定したt1.microでインスタンスが作成される
$ terraform plan

モジュール化(ファイルの分割)

記述量が多くなってくると一つのファイルに全部記述するのがきつくなる。terraform にはモジュールの仕組みがありファイルを分割することができる。

以下のようなファイル構成で、ec2 用の定義を./ec2/main.tfに記述し、./main.tfから呼び出して利用する。

$ tree
.
├── ec2
│   └── main.tf
└── main.tf

# ./main.tf

# moduleの呼び出し
module "ec2" {
  source  = "./ec2"
  # モジュール側の変数を上書き
  instance_type = "t3.micro"
}

output "example_instance_id" {
  # moduleのoutputで出力された値を参照している
  value = module.ec2.example_instance_id
}
# ./ec2/main.tf

variable "instance_type" {
  default = "t2.micro"
}

resource "aws_instance" "example" {
  ami           = "ami-02c3627b04781eada"
  instance_type = var.instance_type
}

# 呼び出し元でmodule名.example_instance_idで参照可能
output "example_instance_id" {
  value = aws_instance.example.id
}
# apply前にgetコマンドでモジュールの取得を行う
$ terraform get

$ terrafomr apply

Discussion