Terraformを使って自社サービスのクラウド環境を再設計してる話

# はじめに
※この記事は「LTSグループAdvent Calendar 2023」の一環として執筆されました。

開発エンジニアとして転職してからそろそろで3年がたちそうで、その間、RubyやPythonを使ったアプリ開発と、AWS環境でのインフラ構築・運用に携わってきました。

今回の記事では、AWSのマネコンで作業していた現状から、Terraformを使って、EC2からFargateへの移行をコードで構成管理できるように進めていることを記載しようと思います。

# 背景
自社で数年間運用しているサービスのインフラ環境は現在EC2やRDSなどを使った基本的なWebサーバーの構成となっています。

インフラ専門といったチームがあるわけではなく、アプリ開発の一部メンバーが運用・保守をしている状態です。

この状況だと、アプリ開発に集中すべきな一方で、ミドルウェアのアップデートなどが後回しになりがちとなっていました。
そこで、AWS Fargateへ移行し、インフラ管理をタスク定義とDockerfileで管理することができれば、メンテナンスの手間も減少するのではないかと考えました。

ただ、既に稼働中のサービスをEC2からFargateへ移行するために、検証環境と本番環境を別で構築する必要がありました。

マネコンを使って手動で構築すると属人化になりがちになるため、今回をきっかけにインフラ構築をコードで構成管理できるようTerrafromの導入を決めました。

# 方針とディレクトリ構成
Google Cloudのベストプラクティスを参考に環境ごとでディレクトリを分けるようにしました。

https://cloud.google.com/docs/terraform/best-practices-for-terraform?hl=ja#separate-directories


```bash
├── envs
│   ├── dev
│       ├── <service-name> # VPCやRDSなどの基本的なインフラコンポーネント
│       │   ├── backend.tf
│       │   ├── locals.tf
│       │   ├── provider.tf
│       │   ├── ...other... 
│       ├── monitoring     # 監視系のインフラコンポーネント
│       ├── batch          # バッチ処理に関するコンポーネント
│       └── cicd           # CI/CDに関するコンポーネント
│       └── ...other...
│   ├── prod
│       ├── <service-name>
│       │   ├── backend.tf
│       │   ├── locals.tf
│       │   ├── provider.tf
│       │   ├── ....other...
│       ├── monitoring
│       ├── batch
│       └── cicd
│       └── ...other...
│   └── stg
│       ├── <service-name>
│       │   ├── backend.tf
│       │   ├── locals.tf
│       │   ├── provider.tf
│       │   ├── ...other...
│       ├── monitoring
│       ├── batch
│       └── cicd
│       └── ...other...
├── modules
　　　　      └── ...other...

```

# 進めてみて

### moduleは適切に設計して利用すべき
moduleはTerraformの複数のリソースを再利用可能な単位として扱うことができ、とても便利だと思いAWSのリソース単位で作成していたのですが、 こちらの構成だと[単なる薄いラッパー](https://developer.hashicorp.com/terraform/language/modules/develop#when-to-write-a-module:~:text=%E4%BB%96%E3%81%AE%E5%8D%98%E4%B8%80%E3%81%AE%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%20%E3%82%BF%E3%82%A4%E3%83%97%E3%81%AE%E5%8D%98%E3%81%AA%E3%82%8B%E8%96%84%E3%81%84%E3%83%A9%E3%83%83%E3%83%91%E3%83%BC%E3%81%A7%E3%81%82%E3%82%8B%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E3%81%AF%E3%81%8A%E5%8B%A7%E3%82%81%E3%81%97%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E5%86%85%E3%81%AE%E3%83%A1%E3%82%A4%E3%83%B3%20%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%20%E3%82%BF%E3%82%A4%E3%83%97%E3%81%A8%E7%95%B0%E3%81%AA%E3%82%8B%E5%90%8D%E5%89%8D%E3%82%92%E8%A6%8B%E3%81%A4%E3%81%91%E3%82%8B%E3%81%AE%E3%81%8C%E9%9B%A3%E3%81%97%E3%81%84%E5%A0%B4%E5%90%88%E3%81%AF%E3%80%81%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%81%8C%E6%96%B0%E3%81%97%E3%81%84%E6%8A%BD%E8%B1%A1%E5%8C%96%E3%82%92%E4%BD%9C%E6%88%90%E3%81%97%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%81%9F%E3%82%81%E3%80%81%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%81%8C%E4%B8%8D%E5%BF%85%E8%A6%81%E3%81%AA%E8%A4%87%E9%9B%91%E3%81%95%E3%82%92%E5%8A%A0%E3%81%88%E3%81%A6%E3%81%84%E3%82%8B%E5%8F%AF%E8%83%BD%E6%80%A7%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82%E4%BB%A3%E3%82%8F%E3%82%8A%E3%81%AB%E3%80%81%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%97%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%81%A7%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%20%E3%82%BF%E3%82%A4%E3%83%97%E3%82%92%E7%9B%B4%E6%8E%A5%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84%E3%80%82)となってしまい。

- モジュールの汎用性が高くはならなかった
- モジュールが大量に作成されていってしまう

という事態に落ちいり、下記記事に記載があるようなアンチパターンにハマってしまいました。

https://qiita.com/bigwheel/items/2b420183639416b5c6bb

### サービスごとのディレクトリ構成の工夫
Terraform導入において、ログ監視やバッチ処理などアプリチームに密に関連しているものに関して、将来的にはアプリチームにも担当してもらえるよう専用のディレクトリを設けてみました。

このようにすることで、アプリチームは自分たちの関心がある分野に集中しやすくなる
一方で、ECSやRDSの基盤よりの作業はインフラチームで効率的に管理できるようになるのではないかと考えています。

# 最後に
Terraformを取り入れてみて、まだ行き届いていない点も多いのですが、コードによるインフラ管理がもたらす最大のメリットは、属人化の問題を減らせることだと感じています。
今回の学びをもとに積極的にIac化を進めていこうと思います。

# 参考URL

https://lab.mo-t.com/blog/microservice-tf-structure

https://tech.groove-x.com/entry/cloud-terraform-zero