変化の激しいスタートアップで、変化を歓迎する
私は毎年少なくとも一度は家族でセーリングに出かけます。大げさなものではなく、自分たちで操れる程度のヨットで、自然と家族との時間を楽しむだけです。意外なことに、こうした旅で鍵を握るのが「風」です。向きも強さも、常に変わり続けます。
風と同じように、人生も絶えず変化します。変化の激しいスタートアップではなおさらです。今日うまく機能しているものが、明日には最適でなくなることもあります。方向転換すべきタイミング、最適化すべきタイミング、あるいはシステムそのものを作り直すべきタイミングを見極める力こそが重要です。エンジニアは自分の下した判断や築き上げたシステムに愛着を抱きがちですが、過去の選択にしがみつくことは大きなリスクになりかねません。
Attribute™で私たちが愛するのは「人」であって「作ったもの」ではありません。だからこそ、データ処理スタックを見直す時が来ても、驚きはありませんでした。初期には、当時の制約のなかで最善のインフラを選びました。しかしスケールとともに、その選択自体が足かせとなり、再考と適応を迫られたのです。
初期の判断:Sparkの実行基盤にServerless Dataprocを採用
データ処理基盤の構築を始めた当初、私たちはSparkジョブの実行にServerless Dataprocを選びました。当時としては極めて理にかなった判断でした。エンジニアリングリソースの限られた少人数チームにとって、セルフマネージドのSparkクラスターを構築・運用する余裕はありません。Serverless Dataprocを使えば、運用の負担を抱えずに価値提供へ集中できました。Sparkジョブを書き、そのままデプロイし、あとはGoogle Cloudに任せられたのです。
成長痛:膨らむコストと失われる制御
事業の成長に伴い、データ処理のニーズも急速に拡大しました。データ量が増えれば、ジョブ数も実行頻度も増え、やがてコストは急騰しました。
運用面でもボトルネックが目立ち始めました。Dataprocはブラックボックス的な性質を持ち、ジョブ実行の詳細がほとんど見えないため、パフォーマンス最適化や障害調査を効率よく進めるのが困難だったのです。
この段階では、デメリットがメリットを上回っていました。制御を自分たちの手に取り戻すべき時が来たのは明らかでした。
移行の「なぜ」
私はエンジニアリングプロジェクトに取り組むとき、シンプルなルールを持っています。強い「なぜ」から始めること。納得できる理由がないのなら、最も貴重な資源である「時間」を投じるべきではありません(ヒント:「クールだから」という理由で新技術に手を出すのは、決して十分な理由にはなりません)。
今回のDataproc移行における「なぜ」は明確でした。
- コスト効率:Serverless Dataprocのコストが膨らみすぎていた。
- 運用の透明性:Sparkジョブに対する制御性と可視性をもっと高める必要があった。
- スケーラビリティと柔軟性:進化するニーズに合わせて、インフラを細かくチューニングできるようにしたかった。
これらの理由に背中を押され、私たちはDataprocからセルフマネージドのKubernetesベースのソリューションへとSpark workloadsを移す集中プロジェクトに乗り出しました。
移行の実際:SparkをKubernetesへ
Sparkジョブのデプロイ方式にはSpark-on-Kubernetesを採用しました。これによりSparkアプリケーションをネイティブなKubernetes workloadsとして実行できます。私たちのアプローチの概要は次のとおりです。
インフラ構築:
- 変動するworkloadsに対応できるよう、オートスケーリングを有効化したKubernetesクラスターをGoogle Kubernetes Engine(GKE)上に構築。
- Sparkジョブ専用のnamespaceを用意し、他のサービスから明確に分離。
- コストをさらに抑えるためSpotインスタンスを活用。
SparkApplication CRDによるジョブ実行:
Spark Operatorを活用し、SparkのworkloadsをKubernetesネイティブなリソースとして管理。
これによりKubernetes Custom Resources(CR)を用いてSparkジョブを宣言的に定義でき、管理とスケーリングが容易になりました。
オブザーバビリティとモニタリング:
Victoria MetricsとGrafanaを組み合わせ、ジョブ実行のリアルタイム監視を実現。
成果:高い制御性、低コスト、そして優れた可観測性
この移行によって、次のような大きな改善が得られました。
- コスト削減:Dataprocのマネージドオーバーヘッドを排除し、リソース利用を最適化したことで、Spark処理コストを70%以上削減。
- 透明性の向上:ジョブ実行の内部が深く見えるようになり、デバッグと最適化の質が向上。ブラックボックスがなくなったことでエンジニアリングチームのオーナーシップも高まり、より質の高いエンジニアリングが自然と求められる状態になりました。
- スケーラビリティ:Kubernetes上での稼働により、ベンダー由来の制約を受けずworkloadsを動的にスケール可能に。Sparkのパフォーマンス向上と実行時間短縮は機能開発の効率も押し上げ、プロダクト価値の創出スピードを加速させました。
最後に
エンジニアリングとは、問題を最も効率的な方法で解くことです。初期の私たちにとってServerless Dataprocを選んだのは正しい判断でしたし、スケールした私たちにとってKubernetesへ移行したのも正しい判断でした。
教訓は何か?柔軟であり続けること。自分の判断に恋をしないこと。そして変化を受け入れること――好むと好まざるとにかかわらず、変化は必ずやってくるのですから。
今のSparkアプリケーション基盤に、いつ摩擦を感じ始めるのだろう――そんなことを、つい考えてしまうのです。