概要
職場でTerraform勉強会を開催することになったので、勉強会の資料のベースとなる内容を記事にしました。
これからTerraformを触りはじめる方が最低限知っておけば良さそうだと思った内容をまとめています。この記事では、構築対象のリソースはAWSを想定しています。
対象読者
- Terraformを使ったことがなく、これから触ってみたい方
- AWSを手動で構築したことがあるけれど、コードで管理したことがない方
この記事のゴール
- Terraformの概要を把握する
- 基本的な文法を覚える
- 必要なドキュメントから自力で情報を探せるようになる
この記事では、0からTerraformプロジェクトを構築できるようになることは目指していません。
(ディレクトリ構成の話などは長くなってしまうので、それはまた別の記事にまとめたい)
導入
Terraformとは
HashiCorpが開発しているインフラ構成をコードを使って管理するためのツールです。
HCLという記法でコードを記述し、インフラの状態を管理することができます。
この記事で取り上げるAWSだけでなく、複数のプロバイダーに対応しているのが特徴です。
Providers - Terraform by HashiCorp
- AWS
- Azure
- GCP
- Datadogなど
また、Terraform以外にもAWSリソースをコードで管理するためのツールとしてAWS公式が出しているものもあります。
-
AWS CloudFormation
- AWS専用のツール
- JSONまたはYAML形式でテンプレートを作成
-
AWS Cloud Development Kit (AWS CDK)
- AWS専用のツール
- プログラミング言語でリソースを定義(TypeScript, JavaScript, Python, Java, C#)
- コードからCloudFormationのテンプレートが作成され実行される
Terraformを使うと何が嬉しいのか
- インフラの構築や変更を自動化できる
- 操作ミスを防ぐことができる
- 複数環境に構築する場合など、作業を減らすことができる
- インフラの状態をコードで管理できる
- Gitなどでバーション管理されている場合、過去の変更内容まで管理できる
- リモートワークしていてもレビューしやすい
Terraform 実行環境の構築
Terraformを使ってAWSリソースを構築するために必要な環境構築です。
- AWS CLIのインストール
AWS CLI のインストールを参考にインストールしてください。
v1とv2が存在しますが、プロジェクトに合わせて選択してください。
- AWS クレデンシャルの登録
今回は、名前付きプロファイルとして設定してください。Terraformでprofileを指定することで複数環境への構築が簡単にできます。
設定ファイルと認証情報ファイルの設定を参考に登録します。
sample-dev
,sample-prod
というprofileを設定した例です。
[sample-dev]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
[sample-prod]
aws_access_key_id=AKIAI44QH8DHBEXAMPLE
aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY
- tfenvを使ってterraformをインストール
tfenvはTerraformの複数のバージョン管理することができるツールです。
使用方法は、下記の記事にまとまっていたので参考に載せさせて頂きます。
tfenvでTerraformのバージョン管理をする
tfenvを使わずにDockerを使用してもいいです。Terraformはマイナーバージョンでも破壊的な変更を行う事があるのでバージョンを気軽に切り替えられるようになっていればOKです。
ここまでで導入はおしまいです。
Terraform 入門
tfstateファイルの管理
最初に、tfstateファイルという重要なファイルについて理解しましょう。
tfstateファイルはTerraformで管理しているインフラの状態を記録するためのファイルです。
Terraformによってインフラを構築すると、自動的にインフラの状態がtfstateファイルに記録されます。インフラに変更を加える場合などは、このtfstateファイルを見てリソースの追加・変更があるかどうかを判断されます。
この自動で生成されるtfstateファイルですが、保存する場所を指定しない場合はTerraformを実行したディレクトリに保存されます。
ローカル環境にtfstateファイルがあると、メンバーが最新のtfstateファイルからリソースの状況を参照することができなくなってしまうため、通常はS3バケットなどで管理します。こうすることで、メンバー間でtfstateファイルを共有することが可能になります。
注意点:S3バケットにバージョニングを設定しておくことをお勧めします。tfstateファイルを間違って変更、削除してしまった場合に復旧することができます。
ディレクトリ構成について
Terraformの解説を進めるあたってサンプルとなるディレクトリ構造を定義し、これに沿って説明を進めたいと思います。
プロダクトでTerraformを利用する場合、複数環境にAWSリソースを構築するケースはよくあるパターンだと思います。
複数環境に対応するための構成として下記のディレクトリ構成を紹介します。
├ modules/
│ ├ vpc/
│ └ api/
│
└ environments/
├ dev/
│ ├ network/ <- 作業ディレクトリ
│ └ api/ <- 作業ディレクトリ
└ prod/
├ network/ <- 作業ディレクトリ
└ api/ <- 作業ディレクトリ
このディレクトリ構成のポイントは下記の通りです。
-
/module
ディレクトリに複数の環境で使用されるmodule
を作成する - 環境ごとのディレクトリを用意する
- tfstateファイルを作業ディレクトリ毎に作成する
環境ごとの作業ディレクトリ配下でTerraformのコマンド(terraform init
やterraform apply
)を実行します。
このディレクトリ構造のメリット・デメリット
-
メリット
- 複数環境に対応している
- 環境差分を許容できる(dev環境だけに必要なコードは、
/dev
ディレクトリ配下にのみ追加する) -
module
を使用することで共通のコードで定義できる(同じようなコードを何度も書くことが減る) - tfstateファイルを分割することで、問題があった場合の影響範囲が小さくなる
- tfstateファイルを分割することで、
terraform plan/apply
の実行時間が短くなる
-
デメリット
- 子モジュールの設計が難しい
- 環境分に同じようなコードを書く必要がある(
/dev
と/prod
ディレクトリ配下に同じようなコードが追加される)
このディレクトリ構成以外にも、複数環境に対応する方法があります。下記がわかりやすかったので参考にしてみてください。
Terraformのベストなプラクティスってなんだろうか | フューチャー技術ブログ
Moduleについて
ディレクトリ構成の解説の中で出てきたmodule
について説明します。
module
は、複数のリソースをまとまった単位で定義することができます。module
を使用することでリソースを簡潔に定義し、複数回呼び出して再利用性を高めることができます。ディレクトリ構成の解説では、複数環境に構築するためにmodule
を利用していました。
また、このmodule
は子モジュールと呼ばれます。
作業ディレクトリの.tf
ファイルはすべてルートモジュールとなり、このルートモジュールから子モジュールを呼び出すことができます。
module
をどのように設計するのかはチームによって異なると思いますが、ここではmodule
の設計については触れません。
基本的なコマンド
Terraformの具体的なコードの書き方を学ぶ前に、基本的なコマンドを見ていきましょう。
Terraformをどのように実行し、AWSリソースが構築されるまでの流れが把握できれば良いです。
まず基本のコマンドとして、下記の5つを理解しましょう。
これらを扱うことができれば、AWSにリソースを構築、変更、削除ができます。
また、これらのコマンドはディレクトリ構成の解説の中で出てきた、作業ディレクトリで実行します。
terraform init
初めに必ず実行する必要があります。
ワークスペースの初期化やプラグインがダウンロードされます。
terraform plan
変更内容が表示されます。
コードを作成、変更した場合は、terraform plan
することで実行内容に問題ないかを確認します。
terraform apply
変更を実行します。ここで完了すると、実際にAWSにリソースが構築されます。
変更内容が表示されるので、問題なければyes
を入力します。
terraform destroy
リソースを破棄します。
破棄対象のリソースが表示されるので、問題なければyes
を入力します。
terraform fmt
インデントなどのスタイルをフォーマットするためのコマンドです。
terraform fmt -recursive
で再帰的にフォーマットできます。
Gitにコミットする前は実行するようにしましょう。
基本的構文(1)
ここまででTerraformを実行する流れをイメージできたのではないかと思います。
ここからは、Terraformのコードを書くために必要となる構文を理解していきましょう。
ここで紹介する構文はルートモジュールで使用します。
terraform
Terraformに関する設定を定義します。
- Backend
tfstateファイルをS3バケットで管理するための設定です。
今回のサンプルでは、profile
も指定します。
terraform {
backend "s3" {
bucket = "dev-tfstate"
key = "ecr/terraform.tfstate"
region = "ap-northeast-1"
profile = "sample-dev"
}
}
- Versions
Terraformとプロバイダーのバージョンを指定します。
インストールされているTerraformのバージョンとここで定義されているバージョンが合っていないと、terraform init
した際にエラーとなります。
プロバイダーはここで指定したバージョンがインストールされます。
terraform {
required_version = "0.12.24"
required_providers {
aws = "2.57.0"
}
}
provider
AWSを利用するための定義をします。
今回のサンプルでは、profile
も指定します。
provider "aws" {
region = "ap-northeast-1"
profile = "sample-dev"
}
AWS以外も定義できます。Datadogの例。
provider "datadog" {
api_key = var.datadog_api_key
app_key = var.app_key
}
基本的構文(2)
最低限知っていると良さそうなものを紹介します。
Input Variables
変数を定義します。
ルートモジュールで変数を宣言すると、CLIオプションと環境変数を使用してそれらの値を設定できます。
子モジュールで宣言すると、呼び出し元のモジュールのmodule
ブロックで値を渡す必要があります。
variable "image_id" {
type = string
}
resource "aws_instance" "api" {
instance_type = "t2.micro"
ami = var.image_id
}
Local Values
モジュール内に閉じて使える変数です。
locals {
service_name = "forum"
owner = "Community Team"
}
Resources
インフラのリソースのことです。
CloudWathLogsを構築するリソースの例。
resource "aws_cloudwatch_log_group" "api" {
name = local.cloudwatch_log_name
retention_in_days = local.cloudwatch_log_retention_in_days
}
参考:AWS: aws_cloudwatch_log_group - Terraform by HashiCorp
Data Sources
Terraformの外部で定義された情報を利用する際に使います。
Terrafromの外部で作成されたsample-vpc
という名前のVPCのIDを取得する例。
data "aws_vpc" "vpc" {
filter {
name = "tag:Name"
values = ["sample-vpc"]
}
}
locals {
vpc_id = data.aws_vpc.vpc.id
}
参考:AWS: aws_vpc - Terraform by HashiCorp
Output
指定したリソースの情報を出力できます。
terraform apply
した際に、ターミナルに出力されます。ここで出力した値は、別のtfstateから参照できます。
remote_state
異なるtfstateファイルに記録されているリソースの情報を参照することができます。
ディレクトリ構成のサンプルだと、vpcのIDをapiのモジュールから参照したいケースなどで使用できます。
Terraformバージョンについての注意
Terraform 0.12で構文に変更がありました。
記述が大きく変更されているので、注意が必要です。
詳細は下記を参考にしてください。
ドキュメント
公式ドキュメント
各Resourcesのパラメータ等はここで確認します。
新しくリソースを追加する時は、まずここを見ます。
Terraform Recommended Practices
公式が公開しているベストプラクティス。
設計方針を決める前に一通り見ておく事を推奨します。
Terraform Module Registry
Terraformの開発元である、HashiCorp社が作成したmodule等を見る事が出来ます。
リソースを追加する際は、ここを参考にすると良いです。
terraform-providers/terraform-provider-aws
AWSプロバイダーのGitHubのリポジトリです。
CHANGELOG.md を見ると、バージョンアップにより対応された機能を確認することができます。
使用しているAWSプロバイダーのバージョンが古くてTerrafrom実行時にエラーになることがたまにあり、その際に見に行ったりします。