最近のTerraformのディレクトリ構成こうなった

Terraformの運用を初めてなんだかんだで1年半くらいたったんですが、プロジェクトによって環境も運用も違うので開発環境や本番環境の構成をどのように管理しているかというのは結構バラける気がしてます。1年半経過して行き着いた形を雑にシェアするだけのエントリです。

前提

  • 環境の系統は**dev(develop)/stg(staging)/shd(shared)/prd(production**の4系統がある
  • ドメインは本番用のドメインと開発用のドメインで完全に分けている
  • 全てのリソースをTerraformで管理してはいない。これからもするつもりはない。以前書いたエントリで、運用で状態が変わる性質のあるものには不向きだったり(状態変化を無視設定はあるが)、独自のオペレーションが必要なものであればaws-sdk-goを使って実装したりするため。

こうなった

で、現状こうなってます。

環境でディレクトリを分ける

たぶんこうしてるプロジェクトはそこそこいると思う。ウチもまさにこうやって環境で完全に分けています。各ディレクトリ毎に**.tfstate**が存在するという感じ。 環境系統で分けることで別の環境に影響が及ばないようにしています。

共通のtfファイルを用意

common.tfというのが共通のtfファイルです。Terraformは基本、該当ディレクトリ内のtfファイルを走査してプロビジョニングを行いますが、各系統で共通で使いたいというものも存在します。ウチであればRoute53のZoneだったり、AMIや証明書の変数なんかを共通のtfファイルで定義してます。各環境のディレクトリへシンボリックリンクを貼ることで、これを共有して利用します。

DNS管理だけのディレクトリ

各環境系統の他にDNS管理用のディレクトリをドメイン毎に用意しています。とはいえ全てのDNSをこのディレクトリ内で管理しているわけではないです。Terraformで作成されたリソースに対してRoute53でDNS設定するには以下のようにrecordsをリソースの変数で参照すればよいわけで、例えばdevのTerraformで作られたリソースのDNSは普通にdev内で管理してます。

resource "aws_route53_record" "www" {
   zone_id = "${aws_route53_zone.primary.zone_id}"
   name = "www.example.com"
   type = "A"
   ttl = "300"
   records = ["${aws_eip.lb.public_ip}"]
}

あくまでこのDNS専用のTerraformディレクトリは、Terraform管理外で作られたリソースのDNS管理のために用意しています。そのため、このディレクトリで記述されるaws_route53_recordの値は実際のレコードを直接定義しています。

初期の頃は開発用ドメインを管理しているのがプロジェクトではなく別部隊だったりしたので、その別部隊が管理してるRoadworkerに対してPRしていたりしてました。その後開発用ドメインもこちらで管理できるようになったんですけど、流れでしばらくRoadworkerのままでした。

で、ここ最近のドメイン変更のアレをきっかけにRoadworker管理をやめて、Route53の管理も完全にTerraformで行うように変えてます。Roadworkerは長らく重宝していたけど、Roadworkerの定義ファイル=そのゾーンのレコードの状態という性質があります。今後一部のDNSを動的に変えるような要件が発生する予定なので、たぶん立ち行かなくなるのです。Terraformの場合は定義したリソースの差分だけを見るので、今の運用とも共存していけると思われます。

まとめ

Terraformとは今後もゆる〜く付き合っていきたい。