Terraformをディレクトリ分割する方法 〜remote_state&Module化入門〜

こんにちは!インフラエンジニアのnaya(@NayaTaiyo)です。最近、Terraformについて学習したので、ディレクトリで分割する方法/remote_stateとmodule化の使い方をブログします。

Terraformの動作フロー

  1. Terraform 初期化(terraform init)

    • ルートモジュール(カレントディレクトリ内)の.tf ファイルを読み込む

    • 使用するプロバイダ(AWSやGCP、オンプレ等)やデータソース情報を取得

    • .terraformディレクトリが作成される

  2. terraform.tfstateの読み込み

    • 過去の構成情報(すでに作成されたリソースの情報)を読み込む

    • リモートで管理(s3など)している場合は、そこから取得

  3. 差分の検出(terraform plan)

    • .tfファイルとterraform.tfstateの内容を比較

    • 変更差分が表示される

  4. 差分の適用(terraform apply)

    • planで出た差分をもとにデプロイ先へ反映(リソースの作成・更新・削除)

    • 適用後、最新の状態がterraform.tfstate に記録される

Terraformはルートモジュール(カレントディレクトリ)の.tfファイルをに記述された内容を基に処理を実行します。

その際に、プロバイダ(AWSやGCP等)どこのデータ(gitやクラウドストレージ)を基にデプロイするかを設定することが可能です。これらはterraform initコマンドを使用します。変更が生じた際には、データの取得元との整合性が取れなく、エラーが発生してしまうため、既存の.terraformディレクトリを削除してから再度terraform initコマンドを使用するか、-reconfigureオプションを使用して修正後の状態に強制的に上書きする必要があります。

remote_stateの使用例

Terraformはapply時にデフォルトではローカルに保存されているterraform.tfstateに保存されます。s3などのterraform.tfstateをリモート管理している場合はremote_stateで情報を取得することができます。

その他にも、outputsすることでルートモジュール(カレントディレクトリ)ではない.tfファイルから値を取得することができます。

上記のように、特定のサービス内の機能ごとにファイルを分割することが可能となっており、チーム内での並行作業によるコンフリクト(競合)も防ぐことができます。

構成図

module化の使用例

module化を使用することで、以下の構成のように各機能をmoduleとして作成することができます。これらを呼び出すことによって環境ごとで異なる設定を可能とします。

上記の例では、異なる環境でのVPCの設定変更のみになりますが、例えば、本番環境にだけLBを建てたいといった場合やNat gatewayを実装したいといった場合に、必要なmoduleを呼び出して特定の環境のみ機能を追加する、ということも可能となります。

※逆に特定の環境のみmoduleを呼び出さずに機能を追加しない、といったことも可能です。

構成図

実際の設定ファイル

先ほどのディレクトリ構成の設定ファイルとなります。

※module化はstg環境のみとなります。

環境

  • EC2
    • 台数:1台
    • OS:Amazon Linux2
    • インスタンスタイプ:t2.micro
  • VPC:10.0.0.0/16
    • サブネット:10.0.0.0/24
  • セキュリティグループ
    • ingress/egress:0.0.0.0/0
    • port:80
    • protocol:TCP

remote_state

※.tfファイルがディレクトリごとで分割されているので、ディレクトリごとにterraformコマンド(plan、apply等)を行う必要があります。

  • TechBull-project/vpc/vpc.tf

  • TechBull-project/vpc/vpc_internet_gateway.tf

  • TechBull-project/vpc/vpc_subnets.tf

  • TechBull-project/vpc/vpc_sg.tf

  • TechBull-project/vpc/outputs.tf

  • TechBull-project/vpc/variables.tf

  • TechBull-project/vpc/terraform.tfvars

  • TechBull-project/vpc/provider.tf

  • TechBull-project/vpc/backend.tf

  • TechBull-project/ec2.tf

  • TechBull-project/variables.tf

  • TechBull-project/terraform.tfvars

  • TechBull-project/provider.tf

  • TechBull-project/backend.tf

※terraformブロックのkey =terraform.tfstateファイルの保存先を指定しております。data “terraform_remote_state” ブロックのkey = ではterraform.tfstateの参照先を指定しています。

上記により、異なるディレクトリ間の値を取得することを可能にしています。

module化

※stg環境設定ファイルのみとなりますが、可変部分の値を変えることで環境ごとで異なる設定が可能です。

また、remote_stateとは違い、TechBull-project/stg/配下でのterraformコマンド(plan、apply)のみで大丈夫です。

  • TechBull-project/stg/main.tf

  • TechBull-project/stg/variables.tf※可変部分を記述

TechBull-project/stg/variables.tfdefault = には、環境ごとで異なる設定の値を記述します。

例:stg環境ならvpc_cidr = “10.0.0.0/16” prod環境ならvpc_cidr = “10.1.0.0/16″等

環境ごとにec2_nameの値を変更したいのであれば ec2_name = “stg-ec2″(stg環境)、ec2_name = “prod-ec2″(ptod環境)等

また、terraform.tfvarsファイルを使用することで、remote_stateと同様に変数と値をマッピングすることが可能ですが、module化では、変数の管理や処理が複雑となってしまうため、本記事のmodule化では使用していません。

  • TechBull-project/stg/modules/vpc/main.tf

  • TechBull-project/stg/modules/vpc/variables.tf ※module側の変数の値を記述

default =にmodule側の変数の値を指定します。

module側で変数の値を定義しているので、各環境(TechBull-project/stg/ TechBull-project/prod/)配下でこちらの変数を上書きされない限り、共通の設定となります。

  • TechBull-project/stg/modules/vpc/outputs.tf

  • TechBull-project/stg/modules/ec2/main.tf

  • TechBull-project/stg/modules/ec2/variables.tf

※TechBull-project/stg/modules/vpc/variables.tfと同様

  • TechBull-project/stg/modules/ec2/outputs.tf

まとめ

今回は、Terraformでディレクトリを分割し、.tfファイルを整理して管理する方法について記事にしました。module化については初めて試してみたのですが、変数の受け渡しや、処理の優先順位、呼び出し元と呼び出し先の関係性など、思っていたよりも迷った部分が多く、どこで処理が実行されているのか、どの変数がどこから参照されているのかなどでハマった場面がありました。

今回の学習を通して、これまで感覚的に使っていた部分への理解が深まる良いきっかけになったと思います。最後までご覧いただき、ありがとうございました。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール