😎

最低限のTerraformコード規約を定義した

2024/05/31に公開

はじめに

インフラ・SREチームのよしたくです。
2ヶ月ほど前にTerraformの公式スタイルガイドが発表されましたね。
実は同じ時期にココナラ用のTerraformコード規約を作成していたので、今回はその紹介をしようと思います。

なぜ作成したのか

コード品質をあげることが目的です。
実のところ、チーム内でTerraform記述の経験値はかなりバラバラであり、またもともと記載されているものもキレイな状態とは言えませんでした。
そこで、最もTerraform経験のある自分が最低限の規約を整え、メンバーの実装やレビュー時に活用してもらうことで、一定のコード品質を担保できないかと考えました。
また、明文化することでこの記述をベースにそれぞれのアタリマエだと思っていたことを議論して反映できるという狙いもあります。

すべてではないですが、どのようなことを定義したのかを以下に記載していきます。

ディレクトリ構成

最もきちんと整理したかったのがディレクトリ構成です。
詳しくは過去ブログ記事を参照してください。
ここが統一されていないので、例えば、新しいサービスインフラを管理するときにどこに書けばよいのかがメンバーによって違った、ということがレビュー時によくありました。
そこで、思想も含めて以下の2つをまず定義しています。このブロックだけで全体の50%程度にはなっているくらいに詳しく記載しています。

  • ディレクトリをどのように作成するのか
  • 基本的なファイル構成はどうするのか

記載の一部

### 第1階層

サードパーティおよびクラウドベンダーによってディレクトリを分類

terraform
├── aws/
├── gcp/
├── datadog/

### 第2階層

第1階層によって構成は異なる

#### aws

配置するリソースの目的によってディレクトリを分類

├── aws/
│  └── services/
│  └── resources/
│  └── managers/
│  └── monitoring/

- services:稼働しているサービス
- resources:複数のサービスから参照されるリソース(ex. S3)
- managers:サービスに直接関わってなく、管理上必要なリソース(ex. 踏み台)
- monitoring:モニタリングやHDS等の通知を行う仕組み、主にCloudWatchやChatbot

tfファイルの書き方

ごくごく一般的なこと(例えば「半角英数字とアンダースコアで記載」など)だけではなく、レビュー時に指摘することの多かった点を抽出して記載しています。

記載の一部

変数で名称のくり返しを避ける

◯
resource "aws_lb_target_group" "admin" {
  name     = "admin-prod"
}

✕ target_groupという名称が重複
resource "aws_lb_target_group" "admin_target_group" {
  name     = "admin-tg"
}

事前定義ロールを紐付ける場合は`iam_member`、新規に作成したロールを紐付ける場合は`iam_binding`を利用する
  - `iam_member`:ユーザー/サービスアカウントに対して、ロールを追加するイメージ
  - `iam_binding`:指定のロールをもつユーザー/サービスアカウントを制限するイメージ

ステート管理

ステートはいわずもがなAWSやTerraformCloudといったクラウドストレージで管理するわけですが、弊社ではAWSやGCPのストレージを使用しているため、そのバケット/ストレージについて明記することとしました。

記載の一部

- 各ディレクトリのステートファイルはクラウド上で管理する
  - `aws`以下はS3、`gcp`以下はGoogleCloudStorage
- 管理バケットには1世代分のバージョニングを設定する
- 管理バケットによるステートロック機能は必須としない
  - 複数人同時に同一moduleの変更を行うことは想定されないため

アンチパターン

このブロックは自分が経験上よくないな、と思ったことをつらつらと記載しています。ですので人や運用方法によってはアンチパターンではないものも含まれますが、ココナラ専用の定義を記載しているので、現行の運用ではアンチパターンになるよね、ということを記載しました。

記載の一部

### DRYではない

複数箇所、複数リポジトリにわたってほとんど同じコード/モジュールを記載しない
-> `terraform-modules`に共通箇所を移動して、これを呼び出すように変更する

### 古いterraformおよびproviderバージョンを使用

日々機能追加/改善が行われているものであるため、一定周期でバージョンを上げていくことが望ましい
本定義においては「majorバージョンが1世代以上以前」「minorバージョンが4世代以上以前」のバージョンを使用していることをアンチパターンとして定義する
少なくとも新規作成時は、作成時点の最新バージョンを利用すること

参考文献

作成当時は公式スタイルガイドがなかったため、以下を参考にしています。

効能

最後にPRテンプレートの事前チェックリストとして「コードの記載がコード規約に従っていること」を追加しました。現メンバーがコード規約を意識して修正できるようにすることが狙いです。
実際にコード規約を設定してからは、新規サービスの管理対象追加をする際の構成やtfファイル品質が統一的になり、自身が基本的だと思っていたレビュー指摘内容はかなり減りました。記載内容はそれほど充実しているわけではないですが、ないよりはあったほうが意味があると思います。

おわりに

今回はTerraformのコード規約を定義しましたが、これを機にGithubActionsやCircleCIのコード規約も整えようかなと思いました。アウトプットして議論することで実装者による記載揺れが少なくなり、コード品質向上やレビューコスト削減に寄与できるのではないかなと感じています。


ココナラでは一緒に働く方を募集しています。
幅広く募集していますので、ご興味ある方はぜひご応募ください!

ブログの内容への感想、カジュアルにココナラの技術組織の話をしてみたい方はこちら

https://open.talentio.com/r/1/c/coconala/pages/70417
※ブログ閲覧者の方限定のカジュアル面談の応募フォームとなります!

エンジニアの募集職種一覧はこちら

https://coconala.co.jp/recruit/engineer

Discussion