インフラの技術選定の失敗は高くつくよという話です。
未来のことを考えてアーキテクチャを考えていれば起こる問題も少なく、追加で発生するコストを減らせたかもしれません。
この記事の内容はざっくりいうと以下のような感じです
- サイト内検索を作るのに AWS CloudSearch というAWSにロックされた楽チンなソリューションを選択してしばらく運用していた
- 手元開発環境と本番環境のインフラ構成が食い違うことにより諸々の細々とした問題が発生した
- 全環境で可能な限りインフラ構成を合わせようと ElasticSearch を使うように変更する
※この記事は手元開発環境への導入のプルリクエストが書き終わった時点で書いているので、本番への導入でまた何か問題が起こる可能性はありますが・・・
最初にAWS CloudSearchを導入した。その時何を考えていたか?
AWS CloudSearchは超ざっくりいうと「全文検索エンジンを細かい設定とか気にせずすぐに使えるAWSフルマネージドのサービス」です。
CloudSearchの裏ではElasticSearchが動いているらしく、だいたい同じことができますが、細かいこと気にしなくていいです。自分でElasticSearch立ち上げてメモリ設定してスケール設定して、細かい日本語形態素解析設定とか、そういうことを気にしなくていいのは良いです。ただし、1台4000円程度から。
当時(11ヶ月前くらい)の状況と考えてたこととしては
- 本番環境と開発環境の2つのCloudSearchインスタンスを作る
- 開発者が当時2人だけ。だからLocalで開発するときも開発環境のCloudSearchインスタンスに繋げればおっけー⭐️
- Localの環境整えるのも手間だしね
- Localと開発のデータ差異もプロジェクトが始まってまもないのでそんなにないのでDBの内容と CloudSearch の Index が多少食い違ってもOK
- サイト内検索の精度は、最初はその機能がどう使われるかの検証するレベルなのでそんなに高くなくて良いし、導入コストをたくさん払いたくない
発生したトラブル
- LocalからCloudSearch繋げないと検索周りの確認ができないが、env設定変更が面倒
- 面倒がゆえに、開発中に一時的にCloudSearchに繋げないでメソッド内部で固定値を返すように無理やり変更。これがうっかりプルリクエストに入ってマージされて本番でも固定値しか帰らないようになるトラブル
- 無理やり固定値を返さなくても良いようにLocalではDBから検索するように分岐をするようにした(LaravelのServiceProviderでの分岐)。本格的なサイト内検索を作ろうとすると、CloudSearch叩く方とDBから検索する方と両方の開発を同時に進めなくてはならず、コストが膨らんでいった
- ちゃんと検索機能を開発しようとするとDBとの整合性も大事なので、手元で書いて開発環境にデプロイして確認、また書いてを繰り返すのがコスト
根本対応をしたい。環境差異を無くそう
開発者も3人になって、Localと開発環境のDBデータの差異も大きくなってきた。もう環境差異があってはやっていけない! ということで合わせることに。
環境を合わせる選択肢は以下のものが現れました
- CloudSearch を各開発者向けに1台ずつ立ち上げる
- 10人いたら10台*4000円? 無駄じゃね
- 裏で ElasticSearch 動いているんだから ElasticSearch 動かせばよくない?
- EC2 に ElasticSearch 立てて自分たちでマネージしていくの? きつくない?
こんな話があり、しかしちょっと調べてみると ElasticSearch は思ったよりも簡単に導入できそうだということがわかりました。
- Localに関しては、Laradock(Laravel 動かせる Docker開発環境)で,
docker-compose up
するときに elasticsearch を追加したらすぐに立ち上がることがわかりました。しかもkibanaも同様に簡単につけられる - 開発/本番環境に関しても、フルマネージドのAWS ElasticSearch Serviceがある
- これはまだ本運用に入っていないので断言できませんが、バージョン指定してLocalと合わせられるので差異は大きな問題にはならないと考えています
というわけで、コード書き換え
- 幸いコードの方はアプリケーション層とインフラ層がインターフェースで疎結合になるアーキテクチャを採用しており、アプリケーション層の書き換えはほとんど発生しませんでした。素晴らしい
- しかもその切り替えがServiceProviderでやっており、環境ごとにどちらを使うか選択可能なので、Localだけ先行してコードを書いてテストしていける
- インフラ層だけCloudSearch向けの検索query string表現(ANDとかORとかboost設定とか)を、ElasticSearch向けの表現を作り直す作業がありました。これはコピペして愚直に
- CloudSearchだとあんまり深く考えなくて良いところですが、ElasticSearchの形態素解析設定なども書く必要がありました
ここら辺の話については別途記事で詳細を書こうかなと思います。
振り返って
- 振り返ると、初動でCloudSearchを選択したのは悪くなかったかもしれません。実際導入は楽チンでしたし。まず動かせるものがすぐできるというのは正義。
- サイト内検索を単純なものから機能を追加していく前にElasticSearchに置き換えるタスクを差し込んでやるのはありだったかもしれません
- ただ、ビジネス的な要請でさっさと機能追加したかったので、このタスクを間に差し込む判断ができたかどうかは微妙なところです。「最高の形になってから進める」だと本質的な開発が止まってしまいこともあるのでバランス大事。
- 今後ここら辺でインフラアーキテクチャ起因での問題は減らせると思うので、もっと変更が大変になってからではなくて、現時点で判断材料を並べてチームで判断できたのはよかったと思います