Open5

「詳解 Terraform 第3版」のつまみ食いメモ

hassaku63hassaku63

https://www.oreilly.co.jp/books/9784814400522/

terraform よくわかんないので、実務で必要そうな知識を吸収することをここのスクラップの目標にする。

  • state の理解
  • ディレクトリ構成
  • module のような、ソースコードを分割管理するための技法
hassaku63hassaku63

第3章より

tfstate の話

デプロイ済みの状態を持つやつ。

リソースのタイプと名前が、実際にどの AWS リソースに対応しているかを保持してる。

例えば aws_instance タイプの example という EC2 インスタンスを構築した場合、tfstate は例えばこんな感じになる

{
  "version": 4,
  "terraform_version": "1.2.3",
   ...
  "resources": [
    {
      ...
      "type": "aws_instance",
      "name": "example",
      "provider": "...",
      "instances": [...]
    }
}

複数人で開発するなら、ステートファイルはチームで同じものを見れている必要がある。バージョン管理するのは非推奨。

ステートファイルを置いておく場所として、terraform としては "backend" という仕組みを提供している。
ローカルバックエンド、リモートバックエンドが使える。リモートバックエンドには Amazon S3, Azure Blob Storage, Google Cloud Storage や、Terraform Cloud, Terraform Enterprise などが使える。AWS リソースのデプロイに terraform を使うのなら、S3 を使うのがおそらく最適。

バックエンドは terraform のテンプレートで明示的に指定できる。

terraform {
  backend "<BACKEND_NAME>" {
    [CONFIG...]
  }
}

バックエンドにまつわる制限や落とし穴がある。

1つは、ステートファイルの保存先(例えば S3 バケット)をどうやって作るのか問題。

もう1つは、backend ブロックでは変数や参照が使えないこと。加えて、この値はモジュールごとに一意な key を指定する必要がある。

terraform module ごとに毎回上記のような値を手でコピペする必要が出てくる。これは、 -backend-config というコマンドライン引数によって行える部分設定 (partial configuration) という仕組みを使うことで軽減できるようになる。バックエンドだけを別ファイルに切り離しておいて、そのファイルを -backend-config で指定する。

# backend.hcl
bucket = "terraform-up-and-running-state"
region = "us-east-2"
dynamodb_table = "terraform-up-and-running-locks"
encrypt = true

# hoge.tf
terraform {
  backend "s3" {
    key = "example/terraform.tfstate" # このパラメータだけでは動作しない
  }
}
$ terraform init -backend-config=backend.hcl
hassaku63hassaku63

環境ごとにステートファイルを分離する方法について。

ワークスペースによる分離と、ファイルレイアウトによる分離の2つの方法がある。

ワークスペース

使い方はこんな感じ

$ terraform workspace new example1
$ terraform workspace list
$ terraform workspace seelct example1

ワークスペースは同一のバックエンドを共有する。

ワークスペースに応じた値の切り替えが、例えば三項演算子で可能。

resource "aws_instance" "example" {
  ami = "ami-xxx"
  instance_type = terraform.workspace == "default" ? "t2.medium" : "t2.micro"
}

ファイルレイアウト

「よくある」terrafrom プロジェクトのレイアウトは、

  • stage
  • prod
  • mgmt (DevOps ツール用の環境、踏み台や CI サーバーなど)
  • global(S3 とか IAM など)

各環境内で、コンポーネントごとのフォルダを構成する。一例はこちら

  • vpc
  • services (この環境で動かすアプリケーション)
  • data-storage

各コンポーネントのディレクトリないには設定ファイルがある。

  • variables.tf
  • outputs.tf
  • main.tf

他にも使われることがある例は、例えばこちら

  • dependencies.tf (データソースのように、コードが外部に依存している部分を分離する)
  • providers.tf
  • main-xxx.tf (main が長くなってきたら必要に応じて分割するやつ。main をプレフィックスにしておくとディレクトリ上の並びが揃って多少見やすくなる)
hassaku63hassaku63

terraform_remote_state と、TF_VAR プレフィックスの環境変数を併用して、例えば RDS リソース作成時のマスターユーザーの設定をいい感じに秘匿できるようになる。ここは端折るので、必要になったら p.107 あたりを参照。

hassaku63hassaku63

第4章より。

モジュールで再利用可能なインフラを作る

module の使い方。(定義の仕方ではない)

module "<NAME>" {
  source = "<SOURCE>"

  [CONFIG...]
}

NAME はモジュール参照のための名前。SOURCE はモジュールのコードがあるパスの指定。

自前のモジュールを作るにあたって、入力変数を指定できる。たとえば

variable "cluster_name" {
  description = "name to use for all the cluster resources"
  type = string
}