Inside of LOVOT

GROOVE X 技術ブログ

ゼロからTerraformを導入した話

こんいす〜!ISUCON楽しかったですね。GROOVE X クラウドチームの mineo です。

この記事はGROOVE Xアドベントカレンダーの13日目の記事です。

qiita.com

クラウドチームでは、LOVOTと通信するクラウドプラットフォームの開発・運用をしています。今回は、インフラ管理にTerraformを導入したので、その話をさせてください。

www.terraform.io

導入した理由

Terraformを導入する以前はインフラを作成したコマンドをMakefileに残すことで管理されていました。Google Cloudをメインのクラウドとして使っているので、gcloudコマンドがMakefileに多く記載されていました。(記録が残っているだけでも素晴らしい...!)

作成記録を残すことで、どのようなリソースがあるか把握し、再度リソースを作成する必要が出来たとき、再利用することは可能です。ただし、

  • あくまで、実行記録のため、実体と乖離していってしまう可能性があり、もし、そうなっても気付けない
  • 各環境(staging/productionなど)に適用するオペレーションが難しい
  • Makefileが肥大化していく

といった課題がありました。そこで、宣言的にIaCを導入することで、解決したいと考えました。

Google Cloudでは、Deployment ManagerというIaCのサービスもありますが、現時点ではTerraformがデファクトスタンダードであるため、Terraformを導入しました。

方針

弊社では、Terraformを導入した実績がなかったため、なるべく認知負荷が低い方針を採用しました。

シンプルなディレクトリ構成

ディレクトリ構成はGoogleのこのセクションを参考に以下のような構成にしました。環境ごとに、ディレクトリを分ける構成としています。シンプルでわかりやすく気に入っています。

-- envs/
   -- dev/
      -- main.tf
      -- locals.tf
      -- xxx.tf
   -- stg/
      -- main.tf
      -- locals.tf
      -- xxx.tf
   -- prod/
      -- main.tf
      -- locals.tf
      -- xxx.tf

cloud.google.com

moduleを使わない

moduleはTerraformのリソースを共通化できる強力なツールです。

しかし、moduleは設計が難しく、使い方もとっつきにくいです。時期尚早と考えて、導入しませんでした。

そのため、環境ごとにほぼ同じコードをコピペで運用する管理となり、その点は少し手間ではあります。今後はなんらかの工夫をしていく必要があるかもしれませんが、ベタで管理するようにしています。

変数を一つのファイルでのみ管理する

moduleを使わず、環境をディレクトリごとに管理するため、変更をコピペで適用することが多いです。 このときに、環境ごとの固有の値が散らばっていると大変なため、locals.tfでlocal変数を宣言して、ここでのみ変数を扱うようにしています。そのため、locals.tfとbackend等の設定を記載したmain.tfのみ、環境個別のファイルとすることが出来ました。

また、外部から値を注入することがないので、variableは使わず、localのみ変数として定義しています。

例↓

locals {
  cloudenv = "dev"
  region   = "asia-northeast1"
}

これもGoogleのベストプラクティスを参考にしました。

Terraform を使用するためのベスト プラクティス  |  Google Cloud

master mergeでの自動デプロイはしない

Terraformの事例では、GitHubでTerraformのコードをレビューしたのちに、masterにmergeして自動でterraform applyするという運用がみられます。しかし、我々の場合はインフラ専門のチームはなく、小規模なチームのため、以下のような理由で、自動terraform applyは不要ではないか、と考えました。

  • terraform applyを実行しないと成功することがわからないときがある
    • planでは問題なかったのに発生することがあり、手戻りが大きい
  • 自動デプロイの場合は、実際にリソースを作成してから、terraform importをするという、運用ができない
  • ペアワークなどで、その場でterraform applyをする運用が多い
  • masterとの乖離が発生しにくい

可能な限り記述を短くする

先述しましたが、弊社ではTerraformの導入実績がないため、コードリーディングするときの負荷をなるべく減らすべく、コード行数をなるべく短く、わかりやすくするように心がけています。そのため、以下のような工夫をしています。

  • デフォルトの値と同じ場合は、なるべくコードに記述しない
  • 同じようなリソースが複数必要な場合は、for_eachを利用する

developer.hashicorp.com

for_eachは最近初めて使ったのですが、とても便利な機能でした。for_eachの個別のリソースをterraform importするときに少し悩んだのですが、ドキュメントに記載されている通り、以下のような書式で実行することが出来ました。

terraform import 'aws_instance.baz["example"]' i-abcd1234

developer.hashicorp.com

導入してみて

まだ道半ばですが、Terraformで宣言的にインフラの状態を管理することで、

  • 実体と乖離がないこと
  • 環境ごとの差異がないこと

といった安心感を持てるようになりました。また、コピペはやや面倒ではあるものの、一つの環境を他の環境に適用するオペレーションも簡単で、信頼できるものとなりました。

また、クラウドチームでは、Google Cloudだけではなく、中国のサービス展開用にTencent Cloudも使っており、両方ともTerraformでコード化できてよかったです。

ただ、TerraformがOSSでなくなってしまったことによりforkされたOpenTofuの動向も気になっており、状況次第で乗り換える必要があるかもしれない、とも考えています。

opentofu.org

まだ道半ばではありますが、IaCは今後も進めていきたいと思います。

おわりに

GROOVE Xでは一緒にLOVOTを成長させていくメンバーを絶賛募集中です!少しでも、興味を持って頂けたら、お気軽にお話しましょう〜

recruit.jobcan.jp