DBインスタンスを作るときの Platform Engineering 的な失敗例と学び

この記事は [Platform Engineering Advent Calendar 2023](https://qiita.com/advent-calendar/2023/platform-engineering) の17日目のポストです。

Web サービスを開発する会社のインフラチームでエンジニアをしています。普段から全社の開発基盤やプロダクトが稼働するシステム基盤の開発運用をしているのですが、その中で「これってPlatform Engineering 的な考え方かも」と思ったエピソードを紹介します。

# TL;DR

- 「使われないプラットフォーム」の認知負荷は高く開発においてボトルネックになる
- 開発プロセスの流れに沿ってボトルネックと最適化箇所を見つける
- 開発者が実現したい開発プロセスのために方法を選べるようにする

## Platform Engineering とはなにか

あくまで個人的な理解ですが、ざっくりいうと「現代のプロダクト開発ではやることが多すぎるので、やることと考えることを減らして開発速度を上げるための方法論」だと理解しています。

現在のプロダクト開発において、アプリケーション以外にプロダクトを作るときに考えること・必要なことが大量にあります。どのアプリケーションフレームワークするとか、データベースどこに置くとか、CI/CDどうするとか、オブザーバビリティは、などなど。これらをうまく使うことでプロダクト開発の品質や速度を上げることが可能ですが、そのための技術とツールが加速度的に増え、それらを組み合わせて効果を最大化すること自体が難しくなってきました。また事業の成長によって複数の開発チームや基盤チームがあると、コミュニケーションパスが増大し、開発のアジリティが落ちてしまいます。これに対処するための思想 DevOps 文化が挙げられます。開発チームが運用も行うことでコミュニケーションパスを最小化し、プロダクト開発のフィードバックループを高速化・チーム自己成長させる目論見でしたが、いままで他のチームが担っていたエンジニアリングも開発チームが行う必要があり、逆に遅くなることもしばしばです。

こんな状況に対応すべく、開発者に向けたドキュメント、共通ライブラリ、インフラストラクチャ、アーキテクチャ、開発プロセスなどなどを対象とし、どう全体最適 or 個別最適するか？開発における認知負荷を減らすためにはどうしたら良いのか？といった方法論が語られるようになったと思っています。

## エピソード： データベース用にいい感じの Terraform Module 作った

社内では monorepo の Terraform でクラウドインフラが管理されており、インフラチームにより社内全体に提供されいます。各開発チームが Terraform コードを書き、データベースインスタンスの設計していました。

しかしその設定を適切に行うことは思いの外大変です。監査ログやバックアップ、DBパラメーターなど重要な設定が漏れたり適切でなかったりして、運用やパフォーマンスに影響する問題が起こりうることもあります。開発者としては最初からいい感じに設定しておいておいてもらえれば楽、と思うことも多いでしょう。

そのためにインフラチームでは、これまでのデータベース運用の知見を詰め込んだ、データベースをいい感じに設定できる Terraform module を書きました。社内のデータベース運用のための設定推奨値がデフォルトで入ります。これによって必要なコードも数十行から数行になりました。ドキュメントも書きました。ドキュメントには使い方だけではなく、デフォルト値とその根拠が書かれているので、チューニングポイントもわかります。

### 全然使われなかった 🥺

全然使われませんでした 🥺

社内のコードをみると、90%はまだ Terraform AWS Provider をそのまま書いています。社内のコンピューティング基盤は Kubernetes のシングルクラスタマルチテナントで構成されていることもあり、開発環境のデータベースにおいては YAML を書いて PostresSQL on Kuberenes を選択するチームもありました。

### なんで使われなかったか

#### 存在を知らない

ドキュメントは書きましたが、開発者はそのドキュメントにたどり着けていませんでした。社内にはドキュメント基盤があり検索も可能なのですが、開発者が一番最初に見るものの1つに**前に書いた自分のコード**があると思います。monorepo なのでインフラチームもレビューに加わることもあるのですが、基本的に開発チームが書くので、前の設計とコードを流用することも多いです。レビュー段階で

* 「こんな便利な module があるよ」
* 「便利ですね！」(でももう書いちゃったしな…)

となりますよね。module を使うために貴重な開発者の時間を使ってしまっては本末転倒です。なんならインフラチーム内でも同じことが起こっていました。


#### 存在意義を知らない

ドキュメントには、この moudule を使うことで何が嬉しいのかをあまり書いていませんでした。たとえば、開発環境から本番環境の運用面を考慮した設定にしておけば、開発中に本番運用で起きそうな問題に検知できる、など長期的に嬉しいこともありますが、網羅的に整理もできていなけば、それを伝えることもできていませんでした。そのため「結局どれがいいのか」という相談がインフラチームに来ることになります。

####  いまのフェーズではいらない / 開発チームにとって他にいいものがある

そもそもクラウドリソースでデータベースを作るというのは、ある程度本番へのデプロイが現実的になってきたら必要になるものです。それまではローカルのDBでもいいし、Kubernetes上のコンテナで動かしてもいいわけです。

いまの組織の開発チームの Kubernetes がわかる開発者は慣れたもので、1分もあれば PostgreSQL の Kubernetes StatefulSet の YAML を書いて `kubectl apply` します。開発初期段階でクラウドでのデータベース構築が不要であり他に簡単に実現できる好きな方法があれば、それを選択することは自然なことです。

## 学び

「なぜ使われなかったか」からいくつか考えたことがあります。

### 「使われないプラットフォーム」の認知負荷は高く開発においてボトルネックになる

「存在を知らない」ならまだしも「方法が複数あってどうすればいいかワカラナイ」「なんか module があるけど使われてなさそう」という状態では、認知負荷を減らすために作ったプラットフォームが逆に認知負荷を高めてしまっています。 

いくつかやれることはあったなと思っていますが、今回の例かつ筆者の環境だとこんな感じかなーと。

- **大前提、使われるものを作る**: そのためにもユーザーとユースケースを特定する必要がありました。今回の場合はインフラチームもデータベースインスタンスの運用に責務を置いており、メインユーザーとなるので、これはクリアできていたと思っています。
- **プロダクト開発チームに紹介する啓蒙活動をする**: 有識者がDBインスタンスを作るときに考えていることやそれを実現する機能の説明が必要です。また、実現したいことに対して選択可能な手法一覧と得られる効果、判断軸など具体的なシーンを伝えることが有用だと思います。
- **インフラチームが Terraform module に全部置き換えてしまう**: 便利なんだから置き換えてしまって効果を体感してもらってファクトを積む戦略です。ダメだったら戻せばいい。これくらいの移行やその自動化はできるチームです。ただしこれはインフラチームもデータベースインスタンスの運用に責務を置いているからこそ可能な選択です。

### 開発プロセスの流れに沿ってボトルネックと最適化箇所を見つける

「いまのフェーズではいらない」で感じたのは「全体的な速度を向上させるには、開発のフルサイクルを理解した上で最適化する箇所を見つけると効果が最大化できるのでは」ということです。開発初期段階でやっておいたほうが後々楽になることや速度が上がることもあるし、不確実性が高いプロジェクトでは逆に不要になることもあります。今回取り上げたデータベースインスタンスを構築するのもその流れのうちの一つでしかなく、最適化には周辺のプロセスやモノとの関連性を理解する必要があります。
その中でも「開発者」と開発者の行動の流れである「開発者プロセス」が最適化の対象であると感じました。

### 開発者が実現したい開発プロセスのために方法を選べるようにする

複数のチームがありそれぞれが自律的に動いていく環境において、あることを実現するのに単に1つの方法や機能を提供するだけでは不十分（または不可能）とおもいました。開発チームが実現したいことは様々なので、社内のユースケースに合わせて機能を複数提供する必要があります。

[DevOps Research and Assessment (DORA)](https://dora.dev/) が提唱する DevOps の能力で [Empowering teams to choose tools](https://dora.dev/devops-capabilities/technical/teams-empowered-to-choose-tools/) があります。その説明には

『ソフトウェアデリバリーのパフォーマンスを向上させ、技術スタッフの仕事に対する満足度を高めたいのであれば、彼らが業務に使用するツールやテクノロジーについて、十分な情報を得た上で選択できるようにする必要がある。』（意訳）

ということが書かれています。インフラチームである筆者としても、インフラ技術を抽象化しツールやプラットフォームとして開発に必要な機能を提供していますが、その提供の仕方しだいで「Empowering teams to choose tools」が実現でき、ソフトウェアデリバリーのパフォーマンスに寄与できると思っています。

そのためにも、プロダクト開発チームがやりたいことに合わせて技術やアーキテクチャを選択していくところで、プラットフォームとしてなにか抽象化や機能提供すべきことはないかと、議論・対話することが重要と考えます。

そこから開発者にとって最高のインターフェースが議論され、最高の基盤に1歩近づけるのではないでしょうか。

## おわりに

「これって Platform Engineering 的な思考かも？」と思ったことを失敗例とともに紹介しました。今回は開発プロセスの中で「DBを作る」というごく一部でしたが、開発プロセス全体を考えるととても大きなエンジニアリングですね。道のりは長いです。

また以前、プラットフォームについてどちらかというと技術マネジメント的な観点で物事を考えたことがあります。こちらもよかったら読んでみてください。

https://www.wantedly.com/companies/wantedly/post_articles/504040