RareJob Tech Blog

レアジョブテクノロジーズのエンジニア・デザイナーによる技術ブログです

Terraform運用の個人的ベストプラクティス

こんにちは、EdTech Labの齋藤です。

スパイダーマン:アクロス・ザ・スパイダーバースをみましたが私には複数の並行世界をどうこうする大いなる力はないので、AWSで複数の環境をいじっている話をしようかなと思います。

というわけで、この一年ちょっとTerraform でAWSリソースの管理・運用をしてきて個人的にやりやすい方法をまとめました。 あくまで私の場合には何が肌に合って・合わなかったかという話なので、そのあたりご了承ください。

なぜTerraform?

AWSをdevelopment・staging・productionのように複数環境で構築してそれを管理したいなと考えたときインフラ素人としては、複数環境をよしなに管理できて・学習コストが低いものが嬉しいなと思いそれらの条件を満たしているのがTerraformだったためTerraformを利用しています。

また、もともとEdTechLabではTerraformで一部のAWSリソースの管理・運用が行われていたということもあり、チーム内に知見がたまっておりとっつきやすかったということも理由の一つです。

個人的ベストプラクティス

module vs workspace

個人的にはmoduleがとても使いやすく、moduleを作成し、利用したい環境分のディレクトリを用意する構成で管理しています。 具体的な構成例は以下のような感じです。

_____
|---aws
|        |---env_name
|        |            |---aws.tf
|        |            |---main.tf
|        |            |---variables.tf
|
|---modules
|        |---resource_name
|        |            |---main.tf
|        |            |---output.tf
|        |            |---variables.tf

env_nameを利用したい環境分作っておき、それぞれのvariables.tfでリソースの数値やvpc_idなどの環境ごとに変えたいものを管理するという方向性です。

このような管理にすることで、env_namevariables.tfの設定を変更するだけで、複数環境に同じリソースを簡単に作成できる上、ちょっとした変更もしやすくなったと感じています。

moduleの設計は 実践Terraform AWSにおけるシステム設計とベストプラクティス に挙げられている

  • Small is beautiful
    • moduleは小さくシンプルにする
  • 疎結合
    • module同士で依存しないようにする
  • 高凝集
    • 変更の理由・タイミングが同じものはまとめ、不要なリソースはmodule化しないようにする
  • 認知的負荷
    • moduleの入力値から必須項目を減らし、オプション項目を増やすことで認知的負荷を減らす

を意識して設計すると良いものになると思います。

さて、このような構成に至る前にworkspaceも利用したのですが、個人的に以下のことが気になりました。

自分が今どのワークスペースにいるのかぱっと見でわかりにくい

terraform workspace showして違うならselect で環境を切り替えるなどapplyにたどり着くまでのコマンド量が地味に多くめんどくさいなと感じることがありました。

というのも、自分が利用しているターミナルの設定ではカレントディレクトリが常に表示されているようにしているので、そこを見ればいまどの環境にapplyされるのかがわかるという状況が好ましいと思っていたためです。

環境ごとに違う設定にしたいときの柔軟性が低い

作業の都合で特定の環境のみにつけたい権限などが発生した場合にcount = terraform.workspace == env_nameみたいな判定を入れる必要があったという点と、このやり方で制御してしまうと本番環境のみに適用したいけどいきなり本番環境はちょっと心配という状況で変更箇所がむやみに増えてしまう上に、countで環境別のリソース制御を行っていくのは見通しが悪いと感じていました。

また、変更を入れたい環境のディレクトリにいてもworkspaceは切り替わっていないためここでも「自分が今どのワークスペースにいるのかぱっと見でわかりにくい」問題が発生しました。

この2点を解消したのがmoduleでの管理+ディレクトリを環境ごとに分離という方法でした。

s3にtfstateを保存しておく

なんというか、当然のことではあると思うのですが一度設定を忘れて辛い目にあったことがあるので戒めを込めて書きます。

環境を作り始めたころ作っていた環境を破壊しかけて、tfstateをS3に保存していなかったばかりに環境を復元するのに無駄な時間を使ってしまい悲しい思いをしました。

なので各環境でローカルではない場所にちゃんとtfstateを保存してバージョンなどを適切に管理しましょう。また、その際管理するバケットはTerraform公式ドキュメントでも記載してある通り、Terraformで管理しないようにしてください。Terraform触っていてミスって消してしまったりしたら元も子もなくなってしまうので...

最後に

いろいろやり方あると思いますが、複数環境を管理するという条件では今のところこのような形がしっくりきています。moduleとしてもterraform importはできるので構成さえ決まってしまえば、コンソールから作成したものや既存のリソースであってもそこそこ楽にmodule化できるので「とりあえず触ってみる」がやり易いのもいい点でした。

いろいろな職種で一緒に働いてくださるエンジニアを募集していますので興味ある方は是非! rarejob-tech.co.jp