Sansan Tech Blog

Sansanのものづくりを支えるメンバーの技術やデザイン、プロダクトマネジメントの情報を発信

Vol.11 IaC(Infrastructure as a Code)改善チームの立ち上げから半年の活動の振り返り

はじめに

こんにちは。技術本部 Bill One Engineering Unitの田畑です。

昨年11月に横串チームとしてIaC(Infrastructure as a Code)改善チームが立ち上がりました。横串チームとは、Bill One Engineering Unit(以下、Bill One EU)内の各Groupの垣根を超えた横断チームのことで、Bill Oneで抱えている課題を解決するために有志で集まったメンバで構成されています。*1 IaC改善チームとは、文字通りインフラのコード化を改善するチームで、Bill One EUではTerraformを採用しています。

この記事では、立ち上げから半年間取り組んできた活動内容や今後の展望についてを、活動を振り返りつつ説明します。

なお、この記事は【Bill One 開発 Unit ブログリレー】という連載記事のひとつです。

目次

IaC改善チームを立ち上げるまで

チームを立ち上げる前のIaCの状況

IaC改善チームを立ち上げる前の状況としては、Terraformは一部で利用されていたものの、機能開発チーム単位や個人単位でTerraformの活用度が大きく異なっていました。また、Bill Oneのシステム全体に関わっているインフラリソースのコード化については、実現されていない状態でした。コード化自体進んでいないので、もちろんテストを行うCIは存在しない状態でした。

上記の課題感は以前からあったものの、既存リソースのコード化を行う優先度がどうしても低くなっており、いつまでもコード化が完了しない状態になっていました。

チームを立ち上げるまで

その頃にBill Oneにジョインしたメンバー複数人がTerraform利用経験があり、チーム立ち上げ前に起こっていた当時の課題感を何とか改善したいと声をあげました。
当初は草の根活動の一貫として取り組もうとしましたが、先ほどご紹介した横串チームの文化が存在していたため、新たにチームを立ち上げて活動を開始しようと決めました。

活動開始時には、やりたいことの洗い出しを行いました。何が課題か?何を解決したいか?よりも、Bill Oneで使うなら理想はこういう状態にしたいという観点から考えることでたくさんアイデアを出しました。

当時のアイデア出しメモ

また、チームとしての活動目的を掲げました。チーム結成当時は、まずはコード化しないと何も始まらないということで、「Bill One内でIaCを実現する」を目的に置き、目的達成に向けてやるべきことの順序を整理しました。さらに、横串チームを結成しても改善が進まなければ以前と同様の状態が続いてしまうため、週1回のミーティングを行い進捗管理するようにしました。

チームの活動内容

ディレクトリ構成の検討

Bill One内でIaCを実現するために、早速コード化しよう!といきたいところですが、事前に考えることがあります。それはインフラリソースを管理するディレクトリ構成です。

Terraformはインフラの現在の状態をStateに保存し、前回からの変更をStateから判断して環境への適用を行います。ただし、多くの開発者が関与する場合、全てのリソースを単一のStateで管理すると、同時に複数の開発者の変更が発生する際にStateが衝突します。これを防ぐためには、適切な大きさのStateに分割することで軽減することができます。また、Terraformの仕様では、適用コマンドを実行するディレクトリごとに独立したStateが作成されるものになっていますので、ディレクトリ構成は重要となります。

実際にチーム結成当初のBill Oneシステムでは、プロジェクト環境毎に単一のStateが管理されていました。その結果、開発者が同時にリソースを変更しようとすると競合が発生してしまい競合解決する時間がかかるため、並列作業が非効率でした。そこで、「各担当チームが並行して効率よく作業できるようにする」目的を達成するためのディレクトリ構成を考えることにしました。

なお、前提として、Bill Oneのシステムはマイクロサービスアーキテクチャを採用しています。*2 また、Bill One EUでは機能毎に担当チームが自律的に開発・運用していますが、機能毎にはマイクロサービスを分離していないです。

「各担当チームが並行して効率よく作業できるようにする」目的を満たすために設計したディレクトリは以下の通りになります。

.
├── microservices
│   ├── service_A
│   │   ├── environments
│   │   │   ├── prod
│   │   │   │   ├── main.tf
│   │   │   │   └── provider.tf
│   │   │   └── stg
│   │   └── modules
│   │       ├── cloud_sql.tf
│   │       ├── cloud_storage.tf
│   │       ├── ... (tf files)
│   │       └── variables.tf
│   ├── service_B
│   ├── service_C
│   └── ... (service directories)
└── shared_resources
    ├── resource_A
    │       ├── environments
    │       └── modules
    ├── resource_B
    ├── resource_C
    └── ... (resource directories)

単一のマイクロサービスを同じディレクトリ内で定義しStateで管理するためのmicroservicesディレクトリを作成しました。Bill One EUのチーム体制は各機能ごとに担当チームが存在していますが、Terraformを利用してインフラリソースを管理する際に、機能単位で分割しようとすると複雑さが増すため、それよりも抽象度の高いマイクロサービス単位でリソースを分離しました。このアプローチにより、マイクロサービスごとに単一のStateを持つことが可能となり、競合を抑制しつつ、関連性の低い各チーム間での並列作業が可能になると考えました。*3
また、サブディレクトリ配下は開発者のTerraform利用ハードルが上がらないよう、ディレクトリを過度に細分化せずシンプルにしました。今後運用していく中でそれでも開発者間で競合が生じてしまう場合は、再度見直していくと良いかもしれません。

また、マイクロサービスを跨る共通リソースを管理するshared_resourcesディレクトリを作成しました。
こちらでプロジェクト全体にまたがるクラウドリソースやBill Oneシステム全体で利用しているマイクロサービスを定義できるようにしています。
ただし現状shared_resourcesディレクトリ内のサブディレクトリ数が増え続けているため、今後はさらにディレクトリ分割しても良いかもしれません。

ディレクトリ構成には明確な正解はありませんが、Bill One EUで運用するためには適したディレクトリであると考えています。

既存コードの新ディレクトリへの移行

元々Terraformは部分的に導入していたものの、ディレクトリ構成を変更したためディレクトリのリファクタリングを行っています。
リファクタリングの際には、terraform rm & terraform importコマンドを実行して移行しました。
リファクタリングするための他の案としてTerraform version 1.1.0で追加された機能である moved Blockが挙がりましたが、異なるStateへの移動が現時点ではできないため、使用を断念しました。ただし同じStateの移動であれば、terraform rm & terraform importコマンドよりもコードで表現できレビューが容易となる点が有用なため、今後利用できる場面があれば積極的に使っていきたいですね。

既存リソースのコード化

目的達成の肝となる、既存リソースのコード化を行いました。
この既存リソースのコード化はリソース数が多いと泥臭くて骨が折れやすく、ひたすらimportするリソースをコードに列挙してからterraform importコマンドを実行する作業になります。

IaC改善チームでは、この作業をimport祭🎉🥳と称して担当範囲を決めてチーム全員でやり切ろうと取り組みました。
作業分担すると実装内容が人によってバラバラになるので、やり方としてはまず特定のマイクロサービスでコード化を完了させ、それを見本に他のマイクロサービスや共通リソースでもコード化することで、一様に反映させるようにしました。その際に弊社ではTeamflowというバーチャルオフィスを導入している*4のですが、タイミングが合うときにバーチャルオフィス上に一同集まり気軽にコミュニケーションを取りながら共同作業を行うようにしました。

また、このタイミングでIaC改善活動に興味を持つメンバー数名が参加しました。既存リソースのコード化は泥臭い作業でしたが、彼らは気にせず積極的に関わってくれました。中にはTerraform未経験の方もいましたが、操作方法や内容をレクチャーしつつペアプロ形式で共同実施し、最終的には彼らが自律的に作業を行うまでになりました。

これらにより、数十名体制の開発規模となるシステムで、それぞれのメンバーが機能開発をやる中で合間を縫って作業を実施し、本番環境とステージング環境の大半のコード化を実現しました。
現在は、本番環境とステージング環境以外にもプロジェクト環境があり、そちらのコード化を手分けして行っています。

Terraform用CIの作成

Terraformコードを自動的に構文解析するためのベーシックなCIも作成しました。具体的にはformatとlintを行っています。

formatはterraform fmtを実行するようにしています。
lintはterraform validateコマンドの実行に加えて、tflintでもコード解析するようにしています。tflintがTerraformのコードをチェックし、コードに存在する非推奨の構文や未使用の宣言などの潜在的な問題を見つけ出してくれます。

また、併せてreviewdogを導入しました。GitHub Actionsの各種linterと連携することで問題箇所をコメント形式で指摘してくれるようになりますので、CI失敗後の修正を素早く行えます。

コード化方針の共有

IaC改善チームでコード化してきたTerraformを開発者が操作する敷居を下げるために、利用方針をまとめることにしました。この方針にはTerraformの基本的な使用方法やベストプラクティスを記載することで、新たにTerraformを学ぶ開発者が迷うことなく使用できるよう配慮しています。

コード化方針ドキュメントのイメージ

また、以下はコード化方針の詳細ルールの一部です。

  • リソースは原則コード化する。
    • ただし例外としてアプリケーションが動的に作成するリソースはコード化しない。
  • 他人の変更を上書きしないよう、Terraformの実行前に必ず差分を確認し、自身の変更のみであることを確認する。
  • Terraformのリソース名・変数名・module名はスネークケースにする。
  • Terraform Providerのバージョンを固定するための.terraform.hcl.lockファイルはGit管理対象とする。*5

今後の展望

現在は、チームで掲げている「開発者がストレスなく自然とIaCを活用できるようにする」という目的を達成するための改善活動を行っています。これまでIaCの経験がなかった開発者にも利用してもらい始めていますが、作業の手間が発生することや、インフラ領域に手を入れることの不安や抵抗感があるとの声もあり、まだまだ対応すべきことが多いです。

今後予定している取り組み内容としては以下のことを考えています。

  • CIの拡充
    • planやapplyの自動化
    • tflintによるTerraform利用方針の各ルールのより厳密なチェック
  • Renovateを用いた継続的なTerraformバージョンアップの仕組み作成
  • Terraform利用フロー・ガイドラインの作成
  • 開発者が自由に実行できるTerraformテスト用実行環境の作成

これらを実現してBill Oneのプロダクト価値創出がしやすい環境を整えていきたいですね。

おわりに

IaC改善チームの立ち上げや活動を振り返りつつ説明しました。IaC導入に取り組む際の参考になれば幸いです。

また、IaC改善チームを通じてアプリケーション開発エンジニアがインフラ領域を自律的に改善してきたように、Bill Oneでは領域問わずサービスを構成する要素にフルスタックに携わることが出来ます。そんなBill One EUでは、一緒に働く仲間を募集しています。ご応募お待ちしています。

open.talentio.com

*1:他の横串チームについて、Bill One 開発 Unit ブログリレーの中でもフロントエンドチームの活動が紹介されていました。そちらの活動記事もご覧ください。

*2:Bill Oneのマイクロサービスアーキテクチャに関しては設計方針の紹介記事でより詳細に紹介しています。

*3:管理単位を細分化すればより競合を抑えるための並行作業も可能ですが、関係性の強い開発者がTerraformを同時に扱うタイミングは大抵既知であり、リソース変更の手間がかかるデメリットもあるため、これらの要素をバランス良く考慮して設計しました。

*4:Teamflow活用イメージはBill One 開発エンジニア 紹介スライドの通りです。

*5:理由は公式ドキュメントの通り、Terraform実行時に全く同じバージョンのプロバイダを選択することを保証するためです。

© Sansan, Inc.