gRPCとgrpc-gatewayでWebオペレーションの形を再考してみた

先月、GoogleがgRPCのバージョン1.0を発表しました。

GoogleがオープンソースのRPCフレームワーク「gRPC 1.0」を発表 | OSDN Magazine

gRPCとはGoogleが公開しているHTTP2ベースのRPCフレームワークで、Protocol Buffersでサービスインタフェースやリクエストやレスポンスのデータ構造を定義します。特定の言語に依存しないメリットがあり、かつ型の恩恵も受けることができます。Protocol BuffersのIDLでデータ構造やインタフェースを定義すると、C++/C#/Java/Go/Ruby/Python/Objective-Cといった言語のクライアントプログラムを自動生成できるため、生産性でも強みが有ります。

最近ではMicroservices構成におけるサービス間通信によく利用されたり、iOSやAndroidといったモバイルアプリケーションからも利用されつつありますね。FRESH! by AbemaTV でもバックエンドのサービス間通信で一部gRPCを利用しています。

grpc / grpc.io

変わりつつあるWebオペレーション

Webオペレーションの形は変わりつつあると感じています。ちょっと前ならシェルスクリプトで様々な運用スクリプトを書いたり、シェルがしんどいケースではPythonやRubyを利用したり、AWSやGCPにもCLIツールがあるのでそれをスクリプトからキックしたりといった運用が多かったと思われます。

ただ、この流れですがGoが台頭し始めてから変わってきたのではないでしょうか。Goは型があって静的言語ではありますが非常に手軽にCLIツールを書けますし、ビルドしてできたバイナリを配置すれば実行できて、かつクロスコンパイルできるのでポータビリティにも長けています。運用系のツールを書くのに今一番適した言語じゃないかと感じてます。

今のプロジェクトでもかなり時期の段階(1年半くらい前)でgRPCを検証していて採用するつもりだったんですけど、某JavaのプロダクトにバンドルされてるJarの内部にあるProtocol Buffersの別バージョンと衝突して問題が起きたりして、安定稼働には少しリスクがあったので見送ってました。最近の新しめなMicroservicesから投入し始めた感じで、本番運用も始めています。

実際に利用してみて生産性・安定性でも大きな手応えを感じていたのもあり、gRPCって実はWebオペレーションの領域にも向いてるんではないか?という仮説が浮かび上がった次第でありまして、今回のエントリとなります(前置きが長くなってしまった)。

grpc-gateway

実際にWebオペレーションの分野にgRPCを持ち込むとなると、一つ課題がありました。何かというと、grpcはProtocol Buffersを喋るため、HTTP経由でやりとりが可能とはいえ人間が解釈できるようなレスポンスを得ることはできません。運用系のツールや様々なミドルウェアが存在してますが、今となってはRESTfulなインタフェースを備えていないものの方が少ないでしょう。

その課題を解決するのがgrpc-gatewayです。

一言で言うと、grpc-gatewayはバックエンドにあるgRPC serviceに対してのReverse Proxyであり、クライアントに対してRESTfulなインタフェースを提供するものです。Protocol BuffersをJSONに翻訳する役割だと思ってもらえればいいですね。これによって、gRPCなエンドポイントとRESTfulなエンドポイントの両方を提供するものが作れます。

grpcでWebオペレーションの仕組みを再考した

gRPCとgrpc-gatewayベースでWebオペレーションの仕組みを再考し直しました。構成図は以下の通り。

Ops Service

運用系の処理をOps ServiceというMicroservicesが担当し、gRPC/RESTfulなインタフェースを提供。grpc-service側にはAuthの仕組みを配置することでオペレーションに対して適切な権限制御を行います。

FRESH!ではAWSをメインに利用しているので、基本的にはOps Serviceからはaws-sdk-go を使ったクラウドの制御を行うことが主目的です。

Hubot

Hubotを使ったChatOpsを行ってるので、HubotからはRESTfulにOps Serviceへの指示を行えるようにしています。

Ops Scheduler

Hubotでスケジューリングするっていう手もありますが、スケジューリングしたい運用系ジョブをOps Schedulerで行っています。これはGoで書かれたDaemonプログラムですが、Goにはcronのライブラリもあるのでcronチックなスケジューリングが簡単に記述できます。Ops SchedulerからはgRPCでOps Serviceへリクエストします。

EC2のAutoScaling Groupにスケジューリングでの縮退っていう機能がありますが、この機能では少し我々が必要なオペレーションを満たせなかったので、このスケジューラーを書くことで少し高度な縮退スケジューリングを実現しています。

Other Service

これはまだ何も作ってないですが、その他のMicroservicesからOps Serviceを利用したいケースもそのうち出てくるでしょう。そうなった場合にOps ServiceをgRPCでリクエストできるように作ります。もちろん、言語はなんだっていい。

まとめ

オペレーションもプログラマブルに、かつ型の恩恵を受けたかったり、CIを使って継続的に品質を担保したいという欲求があるならば、gRPCを使ったWebオペレーションはすごい良いと考えてます。今後も色々と知見を共有できるといいですね(^ω^)。