プログラミング初心者がアーキテクトっぽく語る

見苦しい記事も多数あるとは思いますが訂正しつつブログと共に成長していければと思います

Terraformの基礎

TerraformはInfrastrcuture As Codeを支えるオーケストレーションツールの1つである。

クラウド/非クラウドに関わらずデータセンタ全体のインフラを横断的にコード管理できることから最近、注目度が高まっているようである。抑えておいて損はない。

このような変化を受けて2020年に投稿した簡潔な記事に大幅な加筆を行った。内容は初学者向けに留めてある。


概要

  • Vagrantで有名なHashiCorpが開発したInfrastructure as code (IaC) ソフトウェア
  • クラウド環境の管理に強い
  • 最近、非クラウド(所謂、オンプレミス装置)への対応にも力を入れている

特徴

宣言型

  • Terraformはシステムの期待する状態を設定ファイルに定義する宣言型のツール
  • 宣言型の設定ファイルはGit管理、CI/CD、IaCとの相性もよい

Plan

  • 適用予定の設定を事前に確認できる
terraform plan

Terraform Provider

  • Terraformが管理対象のクラウドやオンプレミス装置とやりとりするためのドライバのようなもの
  • Go言語で記述され、Terraform Registryで多数、公開されている
  • 実行時に管理対象システムに応じたTerraform Providerが自動的にダウンロードされる

構成管理ツールとの連携

  • Orchestrationツールと構成管理ツールは排他的な存在ではない
  • 「Terraformで作ったVMをpuppet/Ansibleで設定する」といった形で連携させることができる

作業の流れ

  1. 運用者はHCLを使って設定ファイルにシステムの期待する状態を定義する
  2. terraform initでworking directoryを初期化する
    • providerはこのタイミングでダウンロードされる
  3. terraform fmtで設定ファイルのフォーマットをチェックする
    • IDEが実施していれば実施不要
  4. terraform validateで設定ファイルの文法をチェックする
  5. terraform planでPlanを確認する
  6. terraform applyで設定を適用する
  7. terraform show / terraform state listで状態を確認する
  8. terafform destoryで作成した全リソースを削除する

設定ファイル

  • 設定ファイルは独自言語 HashiCorp Configuration Language (HCL)で定義する
  • 拡張子は.tfである
  • 「ブロック」という形式で記述する
    • 以下にブロックの基本的な書式を示す
<block type> "<block label>" "<block label>" {
  <identifier> = <expression>
}
  • 設定ファイルには主にterraformブロック、providerブロック、resourceブロックを記述する
    • 詳細後述

terraformブロック

  • 主に利用するTerraform Providerの情報を記述する
  • Terraform CoreやTerraform Providerの版数を指定することもできる
  • 以下の例ではAWS用のTerraform Providerを指定している
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
    }
  }
}

providerブロック

  • 主に管理対象のクラウドやオンプレミス装置へのアクセス情報を定義する
  • 以下にAWSのproviderブロックの記述例を示す。
provider "aws" {
    access_key = "ACCESS_KEY_HERE"
    secret_key = "SECRET_KEY_HERE"
    region = REGION
}

resourceブロック

  • resourceブロックは管理対象システムの状態を定義する
    • わかりやすく言えばシステムに投入する設定
  • 書式は以下の通り。
resource "<リソースタイプ>" "<リソース名>" {
  設定項目 = 設定値
}
  • リソースタイプは予めTerraform Providerで定義されている。
    • AWSのEC2設定ならリソースタイプは「aws_instance」
    • VPC設定ならリソースタイプは「aws_vpc」等
  • リソース名は任意。
  • ブロックの中は「設定項目 = 設定値」という形でリソースのパラメータを定義する。
    • 設定項目もTerraform Providerで定義されている
  • 以下にresourceブロックの記述例を示す。
resource "aws_vpc" "example" {
  cidr_block = "10.0.0.0/16"
}

variableブロック

  • 変数を定義する
  • 書式は以下の通り。
variable "変数名" {
  type = 型
}
  • ${変数名}で参照する
  • 変数の値の指定は、以下の3つの方法がある
    • terraform apply時に引数で指定する
    • 環境変数で渡す
    • tfvarsファイルに記述する
  • Validationルールを定義することもできる

outputブロック

  • 処理結果を変数に格納する
  • 以降の処理で参照することができる
  • 汎用プログラミング言語の関数のreturn文に近いイメージ
  • 書式は以下の通り。
output "任意の変数名" {
 value = 処理結果
}

ファイル構成

  • 設定は1つのファイルにすべてを記述することも、複数に分割して記述することもできる
  • Best Practiceでは可読性の観点から以下のように分割することが推奨されている
example
├── main.tf
├── outputs.tf
├── variables.tf
├── providers.tf
└── versions.tf

main.tf

  • resourceブロックを記述

variables.tf

  • variableブロックを記述

outputs.tf

  • outputブロックを記述

providers.tf

  • providerブロックを記述

versions.tf

  • terraformブロックを記述

Module

  • resourceを組み合わせてmoduleを作成することができる
  • 汎用プログラミング言語の自作関数に近いイメージ
  • 可読性、再利用性の観点からmoduleを作成して利用することが推奨されている

実行順序

  • resourceブロックはmain.tfに記載された順に上から実行されるわけではない
  • resource間の依存関係をTerraformが計算して順序を決定する
    • terraform graphで計算結果を確認できる
  • 例えばresource Aのoutuputをresource Bが利用していた場合、resource Aは記載場所に関係なくresource Bより先に実行される

State

  • terraformは自分が投入した設定をStateファイルに記録している
  • StateファイルはTerraformが宣言的に振る舞う上で重要な役割を果たす
    • main.tfにある + Stateにない = 設定新規作成
    • main.tfにある + Stateにある = なにもしない
    • main.tfにない + Stateにある = 設定削除
    • main.tfとStateで設定が違う = 設定変更
  • Stateと実際の状態がズレると面倒なのでTerraform導入後はTerraform以外の手段で設定を変更しないことが推奨される
  • Stateの管理が必要な点が純粋な宣言型ではないAnsibleと大きく異なる

Backend

  • Stateファイルの場所場所
  • ローカル、S3、Terraform Cloudなど様々な選択肢があり、backendブロックで指定する
  • なにも指定しなければデフォルトのローカル(作業フォルダ)が選択される
  • Backendの種類によってはStateファイルのロック機能やバージョン管理機能が利用できる
  • Terraformをチームで利用する場合はローカル以外の、共有空間(S3やTerraform Cloud)を利用すること

企業向けソリューション

  • AnsibleのAnsible Automation Platform(旧Ansible Tower)に相当するのがTerraform Cloud
  • 有償版はTerraform Enterprise