[Cloudbase tockn氏]進化する事業とデータ構造〜Cloudbaseの場合〜 #データ負債解消

Connpass詳細はこちら

アーカイブはこちら

資料はこちら

Cloudbaseの事業の進化やある機能において求められるデータ構造の変化の過程や、データ構造変化のマイグレーションをどのように行ったか、将来を予見したデータ設計の勘所について紹介させていただきます。

CloudbaseはAWSやGoogle CloudやAzureといったパブリッククラウド向けのリスク検出・対応サポートを行うSaaSで、設定ミスや脆弱性スキャンなどの検出機能があります。

事業の進化とデータ構造の変化

のS3バケットやSSHポートが解放されてるSecurity Groupのような、クラウド上の構成ミスなどを検出する機能です。

最初にこのスキャン機能を提供してリリースした結果、市場に受け入れられて順調に導入企業が増加しました。その中で、設定ミスだけでなくワークロードに潜む脆弱性にも課題がありそうだと分かってきて、既存のお客様からの要望も多く寄せられました。

ですが、会社として今脆弱性の領域に踏み込むべきなのかといった議論も巻き起こっていました。ただでさえ設定ミスのスキャンという大きな機能を提供してる中で、当時社員8人ぐらいの中で新しい機能開発に踏み込むべきかどうかが論点になりました。

そこで、コンテナイメージの脆弱性スキャン機能を提供して市場を伺ってみました。

コンテナスキャンはクラウド上のコンテナイメージをスキャンして脆弱性を検出する機能です。最初のデータ構造は、スキャン対象のコンテナリポジトリやイメージがあって、 それに紐づく脆弱性を表したテーブルがあるシンプルな構造でした。ちなみにこれはかなり抽象的なイメージなので、実際とは少し違います。

シンプルな構造でリリースした結果、新規契約獲得など市場に受け入れられたというハッピーな結果になりました。

そして今度はVMスキャンもやりたいという話になってきました。VMスキャンはAmazon EC2などのVMに潜む脆弱性を検出する機能です。データ構造は先ほどのコンテナと同じようにVMのテーブルがあって、それに紐づく検出結果があるシンプルな設計でした。

こちらもリリース後すぐに新規契約を獲得するなど、市場に受け入れられました。

では今度はFunctionスキャンや検出された脆弱性の横断検索もやりたいという話が出てきました。 だんだん予想がついてくると思いますが、そもそもFunctionスキャンはAWS LambdaなどのFunctionに潜む脆弱性のスキャンで、データ設計は同じようにFunctionテーブルや脆弱性の検出結果のテーブルを作るのかと考えます。

しかし、スキャンの種類ごとにデータが完全に独立してしまっていてアプリケーション側としてもかなり冗長だったんですね。あと、脆弱性の横断検索も非常に難しい構造だったので、データ構造を変えようという話になりました。

脆弱性のスキャン対象のリソースを表す抽象テーブルを用意して、それに紐づく形で検出結果のテーブルを持って、その具象テーブルとしてコンテナ・VM・Functionテーブルを作りました。要はCTI(Class Table Inheritance)と言われるよくある設計パターンに置き換えた形です。

これによって扱いやすくなって横断検索も可能になりました。

整合性の確認によるマイグレーションの実施

そして実際にどのようにマイグレーションしたかというのが次のお話です。

データの特性を考えてみると、スキャン結果はスキャン時にしか更新されませんし、ステートレスでした。あとはワークフローとして、お客さんの環境をスキャンするScannerとスキャン結果をデータベースでロードするLoaderというコンポーネントで分かれていました。

以上より、ダブルライトができそうだという話になります。

ダブルライトは新設計のテーブルを新たにv2として用意して、 ワークフローとしてv1にデータをロードするLoader v1と並列でLoader v2を作ってあげて、スキャンが終わるとLoader v1,v2が並列で動いて、それぞれのテーブルに書き込む形です。

最初はv1テーブルの内容をアプリケーション側に今まで通り返します。整合性の確認が取れたら、v2の値に切り替えるマイグレーションを考えました。

そうすると、今度は整合性をどうやって確認するのかという話になります。

これもCloudbaseの特徴ですが、データのパターンが膨大という課題があります。 クラウドプロバイダもAWSやGoogle Cloud、Azureなどがありますし、各プロバイダの対象のサービスや検出項目、脆弱性もたくさんあるので、事前に検証データを用意するのはなかなか難しいです。

そこで弊社プラットフォームチームのメンバーが不整合チェッカーを開発してくれました。

これは本番環境のv1とv2で溜まっている集計値に不整合が無いかをチェックするツールです。これをデイリーで回して、異常があればslackに通知するようにして、不整合があり次第潰しきったのを見てv2に切り替えるといったマイグレーション方法を取りました。

機能要件に対するコストを天秤にかけた設計

データ構造が負債化する原因は一般的に大きく分けて2つあって、要件を満たす設計ができていなかったこと、もう一つが設計当時の要件から変化や拡張があったことです。

今回のケースは後者かなと思っていますが、解決策として常に要件の変化や拡張を完璧に考慮した設計をするのは本当に正しいのでしょうか。

ある機能要件を開発する時、将来的に開発予定だけど今はやらない機能要件、将来的に開発するかわからないけど、何となくやりそうな機能要件、思いもよらない機能要件の3つの予見が一般的に潜んでいます。 設計をするときはどこまでを対象に含めるかが重要です。

将来的に開発予定だけど今はやらない機能要件については基本的に考慮すべきです。しかし、今考慮するコストVS将来考慮するコスト&マイグレーションコストを天秤にかけて、 マイグレーションコストがかなり低い状況であれば設計スコープから外した方が良いです。

次に将来的に開発するかわからないけど何となくやりそうな機能要件については、考慮しない方が良い場合が多くて、先ほどと同じコストの天秤になりますね。

ただ、この解像度の低さから要件定義をするコストは大体高く付きがちで、 諦めて定義が曖昧なまま設計をすると、ギャンブル性を持ったオーバーエンジニアリングになると感じています。

最後の思いもよらない機能要件は考慮するべきではなくて、大体オーバーエンジニアリングになります。

今回のケースで考えると、VMスキャンやFunctionスキャンは「将来的に開発予定だけど今はやらない機能要件」で、横断検索は「将来的に開発するかわからないけど何となくやりそうな機能要件」だったと思います。

先ほどのコストの天秤にかけてみると、今考慮するコストはVMスキャンやFunctionスキャンの仕様、技術的制約の明確化が必要になります。脆弱性市場をまず見に行く目的の上で、これらを全部を考慮して作るのはコストが高くなります。

一方で、将来を考慮するコストとマイグレーションコストで言うと、スキャンの仕様や技術的制約の明確化を今やっても将来やってもコスト自体は変わりません。ダブルライトは可能だったので、マイグレーションコストは低いという想定がありました。

以上から、今回開発する機能要件だけにスコープを絞って設計しました。 結果的にはこの設計で良かったかなと思っています。ただ、マイグレーションを推進してくれたメンバーにはすごい感謝をしていて、不整合チェッカーのようなマイグレーションを楽にする基盤作りが大切だと感じています。

視聴者からの質問に答える質疑応答タイムへ

――ここからは、視聴者の方からの質問に回答していきます。まず1つ目は、「データ構造の負債を解消するために専用のメンバーを配置しているのでしょうか、それとも開発メンバーが機能アップデートと並行して進めているのでしょうか」という質問です。陳さんからご共有いただけますか。

陳:我々は全て同じメンバーがやっています。なぜなら、ここを分けると背景がわからないメンバーも入ってきてしまうからですね。 基本的に解消する際は短期間で皆で一緒にやり切るという形で進めています。

――続いてtocknさん、お願いします。

tockn:弊社も同じで、特に負債解消の専門チームは置いていません。プロダクトを開発するメンバーが解消しています。クォーターの最初の2週間は非機能系の改善に当てるといった改善ウィークも設けたりして、色んな方法でプロダクト開発と共に並行できる施策を練っている感じですね。

――続いて大島さん、お願いします。

大島:Nayose Groupは歴史が長く大きいチームになっていて、その結果システムとしても大きくなってしまいました。そのため、チームを分割してより改善しやすくなる構造にしています。

――続いて森山さん、お願いします。

森山:弊社も機能アップデートと並行してやっていますね。 開発を進めるか、負債を解消するかを天秤にかけていて、場合によっては負債の解消を優先しています。

――最後に弓場さんはお願いします。

弓場:フツパーもチームを分けてはいなくて、開発メンバーが担う体制で今はやっています。

――続けて、「どれぐらいの時間をかけて負債を解消してきましたか」とのことですが、陳さんからお願いできますか?

陳:基本的には2〜3週間でやりきることを徹底しています。 何か行動的に問題が発覚した場合は一旦開発を止めて2〜3週間で全部やりきって、無理にその先に進まないという判断をしてきました。 短期間で細かく、問題があるところだけ集中的にアタックする形ですね。

――続いてtocknさん、お願いします。

tockn:先ほどの回答と被りますが、改善ウィークみたいな形で1週間〜2週間を改善の期間に当てていますね。あとは、クォーター単位でプロダクトや非機能系の開発も含めて何をやるのかを整理する段階で期間を当てはめたりしています。

――続いて大島さん、お願いします。

大島:細かいところは2週間くらいの短期間でやって、 どうしても歴史的経緯で大規模改修が必要なタイミングであれば半年〜1年ぐらいかけて、現在動いているものをリプレイスする形です。

――続いて森山さん、お願いします。

森山:大体メンバーは複数人いるので、一人が負債回収して、もう一人は機能開発という感じでやっていましたね。負債回収をやると大体1ヶ月ぐらいかかります。それぐらいで今回の課題などは対応していました。

――続いて弓場さん、お願いします。

弓場:今回発表したデータベースの移行に関してはいきなり全部を変えるのではなくて、ステップを区切って1ヶ月単位で行いました。

――本日のイベントはこちらで終了とさせていただきます。 登壇者の皆さん、視聴者の皆さんありがとうございました。

この記事をシェア

関連記事


副業・フリーランス

プログラミング

インタビュー

デザイン

お金

採用・組織

イベントレポート

転職