ことのはじめ
こんにちは、freeeのSREの久保木です。
freeeにはたくさんのProjectがあり、それらが複雑に依存関係を持ちます。
ですが僕はSREという所属上いったんはこれら全てに関与する可能性があります。なのでどんなProjectがあって、どれとどれがどう関わっているか、といったことを意識しなくてはならないわけですが。
はい。無理です。まだ入社から二ヶ月弱なのにそれがすぐできたら苦労はないのです。
ということで、この問題をどうにかしてみましょう。
目指すところ
どうにかする、って具体的にどういうことか。 今回はfreeeで運用しているProject間の依存関係を図示しよう、という話になりました。
こうすることで、僕のように入ったばかりでProject名が何を示しているかはわからないくらいの人が、一つのProjectを調べながら扱っていきたいという時、でも何に気をつけながら触っていけばいいだろうという疑問を解決する手助けになることを目指しました。
どうやって実現しようか模索するターン
ではいよいよ具体的な話に入っていきます。どこから考えていきましょうか?
まずは絵を描く方法から考えてみましょうか。
方法はいろいろあります。 Draw.io のように手書きする方法もあれば、PlantUMLやMermaidのようなCodeで書いて図にしてもらうような仕組みもあります。 調べてみると他にもDiagramsというPython Codeで書いたものを図にしてくれるものとか、terraform-graph-beautifierやInframap、terraform-plantumlといったTerraformのState Fileから図を起こすようなものもあります。
ところで、今回の目的はProjectの依存関係を図示することです。
freeeでもTerraformを扱っているので、そのState Fileから図示するということには魅力を感じますが、ちょっと待ちましょう。
今回はInfrastructure構成図を生成するわけではなく、Projectの依存関係です。
State Fileから絵を描く仕組みというのは、基本的にそのState Fileに記載されているResourcesを全て利用している一つのProjectのInfrastructure構成図を描くというものです。 Terraform自体、Project単位とか、他でも共有出来るNetwork系やDatasource系を切り分けたものとかになりがちで、一つのState Fileの中に複数のProjectのResourceが混在するということはあんまりありません。
とすると、です。Project間の依存関係を見たい、という今回の狙いは、State Fileをまたぐ、一つ粒度の抽象度が高いもの = 単にState Fileを一つ取り扱って図示する、という方向性ではないことがわかってきました。
となるとお絵かきする方法はDraw.io等で自力で描くか、PlantUML等でCodeで表現して絵にするか、という方向になってきます。
でもまあEngineerという生き物は人手を介在させたら天に召されてしまうはかない生き物なので、必然的になんとかCodeを自動生成して絵にしたいと考えることになります。その方法がないとわかれば手書きもやぶさかではないけれど、できるなら、できるなら、今後もずっと人手で作業するような仕事を増やしたくありません。やです。
ということでProject間の依存関係を何らかの方法でCodeにし、それを絵に変換する、これをもって人手を介在させず仕事を増やさず、Projectを扱う敷居をこれまでよりもぐっと下げたい、という風に目的がすこしはっきりできました。
具体的な実現方法を考えていく
実は今回は着手したとき、Mermaidの存在を見落としていたので、PlantUMLのCodeに落としたいということは早々に決まりました。 MermaidならGitHubが公式にSupportしているのでReadmeに埋め込んでしまうだけでもいいので、また機会を見て検討してみたいところではあります。
さてとはいえProject間の依存関係をPlantUMLに起こすと決めたのはいいものの、どうやって実現しましょうか。
はい。Terraformです。
先ほどは「Terraform自体、Project単位とか、他でも共有出来るNetwork系やDatasource系を切り分けたものとかになりがちで、一つのState Fileの中に複数のProjectのResourceが混在するということはあんまりありません」と書きました。ということは逆を言えば、Project間でInfrastructure Layerにおいて依存関係があるようなものは、他のProjectのStateなりOutputなりを見ているはずです。
ということでCodeを見てみましょう。ありました。data.terraform_remote_state
で他Projectを呼び出しています。
こうなれば簡単ですね。Command使ってfindとgrepを組み合わせてfind ./${ProjectのTerraform Source CodeがあるDirectory} -type f -name 'terraform_remote_stateをまとめて記載したfile名\.tf' -type f -exec grep --color=auto -nH -E "key\s+=" \{\} +
とかで調べて、あとは似るなり焼くなり好きにできます。
(そのまま使えるCodeを見せて! と思う気持ちもあると思いますが、後述する分類のListやら、社内でのTerraformの管理の仕方を前提とした部分など色々あるのでご勘弁を)
これで特定のProjectが利用している別Projectを見ることが出来ました。 そして逆のことをすれば、逆方向の依存関係も調べられます。
これで双方向のProject間の依存関係がわかると、
こんなPlantUMLのCodeを描けるようになります。
@startuml Project -down-> A Project -down-> B Project -down-> C Project -down-> D Project -down-> E Project -down-> ... @enduml
まあ、描けるようにはなったね!
色々思うところはあるけれどまずは一歩前進。よし。
Layoutなんとかしていこうか
絵を描けるようになったとはいえ、これだとさすがにひどいので、PlantUMLの構文を調べてもうすこしマシにしていきます。
そうこうしているうちにProjectにもいくつか分類できることがわかってきたので、以下の方向性でProjectを分類したListを作りました。
Group | Description |
---|---|
Services | 外部に提供しているProject (ex. 会計) |
Internal Services | Servicesが利用する、外部に直接公開しているわけじゃないProject (ex. 認証基盤) |
Others | ServicesやInternal Servicesと依存関係がある外部公開していないProject (ex. ECR, Slackへの通知) |
あとはこれを踏まえて絵を生成するCommandを作ると、最終的にこういったPlantUMLのCodeが生成出来るようになりました。
@startuml agent "product" rectangle "Services" as service #A9DCDF { agent "Product_A" agent "Product_B" } rectangle "Internal Services" as internal #ADD1B2 { agent "Product_C" agent "Product_D" agent "Product_F" } rectangle "Others" as others #EB937F { agent "Product_E" } "product" -up- "internal" "product" - "service" "product" -down- "others" @enduml
これを絵にするとこうなります。
ただこれだけだと依存関係の向きがわかりませんので、以下のような表も生成出来るようにしました。
Group | Dependency(From) | Dependency(To) |
---|---|---|
Services | Product_A Product_B | Product_B |
Internal Services | Product_C Product_F | Product_D |
Others | Product_E |
本当は絵の中の線を矢印にするなどして、依存関係の方向もわかるようにしたかったのですが、Sampleに出している絵と違ってfreeeの本当のProject間の依存関係を描くと、Servicesの中に16個、Internal Servicesの中に20個なんてこともざらで、それだけの数のProjectの関係を全部表現しようとすると大変見づらい絵になってしまいます。なのでそこは割り切りながら、表も使って情報補完することにしました。
おわりに
以上で今回のお話は終わりになります。
freeeでは今後もProjectの数が増えていきそうですし、たくさんの開発が日々進んでいきます。その中、開発の敷居が低くなるような施策を今後もとっていくことになるでしょう。その際に得られた知見が、また誰かお役に立てば幸いです。