CDKTFで実現するコミューンのインフラストラクチャ改善

はじめに

はじめまして、コミューン開発 SRE チーム の池田です。 今回は「コミューンのインフラにおける課題」を解決するために Cloud Development Kit for Terraform (CDKTF) を導入しましたので、導入の進め方やよかったところについてご紹介したいと思います。
「コミューンのインフラにおける課題」については、 SRE 川岡さんの記事「『Terraform と gcloud CLI を使用した完璧な Google Cloud インフラストラクチャの構築』は本当に完璧なのかやってみた」で紹介していますので、ぜひお読みください。 また、この記事では CDKTF の概要や用語については説明いたしませんので、予めご承知ください。 tech.commmune.jp

なぜ、CDKTF にしたのか?

commmuneでは、WEB フロント・バックエンドがTypeScript で実装されています。開発者が普段使用している「TypeScriptで書ける」ことが走り出しの理由です。
Google Cloud にて IaC を行う 代表的なツールとして、Google Cloud Deployment Manager と Terraform があるかと思います。今回、なぜそれを導入しなかったかというと、IaC という新しいことをはじめるために、さらに新しいことを習得するとなるとかなりハードルがあがってしまうのではないかという懸念があったからです。SRE チームのみで IaC の管理を続けていくのであれば、もしかすると TypeScript であることを重要視する必要はないのかもしれません。
しかしながら、いずれは SRE チームに限らずいろいろなメンバーに気軽に IaC をさわってもらいたいと考えており、少しでもちょっとやってみようかなと思ってもらえるよう CDKTF を採用しました。

CDK with TypeScript って実際どうなの?

TypeScript を使うことでアプリケーション側の知見が周辺ツールも含めて活用できました。フォーマッターや静的解析ツール、TypeScript 自体の設定など、こだわりだすとなかなか大変なものを流用できたことは非常に便利で、大きなメリットです。また、ベースは Terraform ですので、Terraform の知見も活かせます。Google Cloud は公式ドキュメントに Terraform のコードサンプルを掲載しています。Terraform ではないのでコピペできないことが少し不便ですが、それでもほとんどそのまま利用できますので、とても役に立ちます。
現状の IaC は SRE メンバーが主に開発していますが、すでに何名かの開発メンバーからレクチャーの依頼や小さなところからプルリクを作成してくれていたりと、積極的に IaC を触る動きがあり、今後も拡大を広げていけそうです。

どうやって、IaC 化していったか?

まずはゼロから作成する

IaC 自体がはじめてのことなので、既存の環境へ影響をあたえないようにまずはゼロから作成することにしました。CDKTF は、Terraform がベースとなっており terraform import コマンドなどをつかって既存リソースを取り込むことができます。そのため、すでにある環境から取り掛かることも可能です。しかし、既存の環境は試している間に環境を壊してしまうかもしれませんし、いずれは同じ環境を簡単に増やせるようにすることを視野にいれています。そのため、新しい Google Cloud プロジェクトで最低限必要なリソースを定義していくことから始めました。

一気にやろうとしない

なるべく小さな単位でリソースを取り込むことを意識しました。何人かで同時に作業をすすめていると、知らぬ間にリソースが取り込まれてしまっていて、思わぬ変更を引き起こす可能性があります。そのため、どのリソースを取り込んだが細かくメンバー同士で共有する必要があり、ときには作業が終わるまで待っている必要があります。また、リソースを取り込むためには以下の手順を踏む必要があります。

  1. コードを書く
  2. cdktf synth で Terraform 用のファイルを生成する
  3. すべての環境にて terraform import で既存のリソースを取り込む
  4. cdktf diff で取り込んだリソースが正しく取り込まれているか確認する

これをリソースの数だけやるとなかなか大変な作業になるので、一度の修正で取り込むリソースは少なくしたほうがいいと思います。
とはいえ、Cloud Load Balancing のように複数のリソースをまとめて取り込む必要があるものもあります。Cloud Load Balancing を例にとると path rule だけを管理したいので url map を取り込みたいとしても、Cloud Run、ネットワークエンドポイントグループ、バックエンドも取り込む必要があります。

// 注意) 説明に必要ない部分は省略しています
// ネットワークエンドポイントグループを管理するために、Cloud Run を定義する
const cloudRun = new CloudRunService();
// バックエンドを管理するために、ネットワークエンドポイントグループを定義する
const severlessNeg = new ComputeRegionNetworkEndpointGroup(scope, id1, {
  cloudRun: {
    service: cloudRun.name,
  },
});
// url map を管理するために、バックエンドを定義する
const backendService = new ComputeBackendService(scope, id2, {
  backend: [{ group: severlessNeg.id }],
});
new ComputeUrlMap(scope, id3, {
  defaultService: backendService.selfLink,
});

その場合は、Data Sources を使ってリソースの情報を取得してから、それを使ってリソースを管理するというような方法をとりました。こうすることで、本来管理したいリソースだけを管理できます。これを繰り返していき、いずれは Data Sources がなくなるようにしていきます。

// 注意) 説明に必要ない部分は省略しています
// url map を管理するために、すでに Google Cloud 上にあるバックエンドを取得する
const backendService = new DataGoogleComputeBackendService(scope, id2, {
  name: target.name,
});
new ComputeUrlMap(scope, id3, {
  defaultService: backendService.selfLink,
});

今回は、Cloud Load Balancing の url map を例にしましたが、変更の多いリソースから取り込んでいくと IaC の恩恵を受けやすいと思います。

今後の展望

まだまだ、IaC の運用を全ての開発メンバーに展開するには課題が残っている状況です。それらの問題を解消して、誰でも気軽にプルリクを出せる環境作りをしていきたいです。運用の過程で出会った問題や課題については、別の機会で紹介したいと思います。
また、将来的には気軽に必要な環境を全て構築出来るようにしていきたいです。必要な時に必要な環境が手に入る、そんな未来を IaC によって実現していきたいです。

さいごに

コミューン株式会社では、Engineer、EngineeringManagerを絶賛募集中です! 記事を読んで、少しでもコミューンの開発にご興味を持っていただけたのであれば、是非カジュアルにお話できると嬉しいです!

docs.google.com

commmune-careers.studio.site