イベントベースアプリケーションの重要性
Cloud Native
Cloud Native とはなんでしょうか。Cloud Native の定義は Cloud Native Computing Foundation が以下のように定義しています。
クラウドネイティブ技術は、パブリッククラウド、プライベートクラウド、ハイブリッドクラウドなどの近代的でダイナミックな環境において、スケーラブルなアプリケーションを構築および実行するための能力を組織にもたらします。 このアプローチの代表例に、コンテナ、サービスメッシュ、マイクロサービス、イミュータブルインフラストラクチャ、および宣言型APIがあります。
これらの手法により、回復性、管理力、および可観測性のある疎結合システムが実現します。 これらを堅牢な自動化と組み合わせることで、エンジニアはインパクトのある変更を最小限の労力で頻繁かつ予測どおりに行うことができます。
Cloud Native Computing Foundationは、オープンソースでベンダー中立プロジェクトのエコシステムを育成・維持して、このパラダイムの採用を促進したいと考えてます。 私たちは最先端のパターンを民主化し、これらのイノベーションを誰もが利用できるようにします。
CNCF Cloud Native Definition より引用
Cloud Native と記載されているからと言って、Public Cloud 上で動かすアプリケーションを指し示している訳ではありません。オンプレミスの環境であっても、上記の要素を満たしていれば Cloud Native と言えます。逆にいうと Public Cloud 上で動いていても上記の要素を満たせなければ CNCF のいう Cloud Native ではありません。
Cloud Native とステート
では、Cloud Native なアプリケーションを開発していく点で重要な点は何でしょうか。
上記を見ると、回復性、管理力、および可観測性のある疎結合システムと記載されています。回復性、管理力、可観測性については Kubernetes をはじめとするコンテナプラットフォームやその周辺の OSS を用いることで充足できそうです。
ただし、問題はその上で動作するアプリケーションになります。
Cloud Native 以前のアプリケーションはいかにダウンさせないかに着眼してアーキテクチャが作られていましたが、Cloud Native 以降ではダウンしてもすぐ回復する点、言い換えるとダウンしてもよい作りに変えていく必要があります。
ステートと回復性、スケーラブル
仮に、現在複数のデータソース A、B、C に接続してデータの更新をおこなうアプリケーションがあったとします。このアプリケーションは Cloud Native と言えるでしょうか。
個人的な見解では上記のアプリケーションは Cloud Native とは言わないと考えています。理由は 3 つあります。
- マイクロサービスではない
本アプリケーションは一つのサービスに対して 3 つのデータソースにアクセスしているため、マイクロサービスとは言えないでしょう。 - 回復性に乏しい
例えば 3 つのデータソースの更新中、書き込んでいるアプリケーションが落ちた場合、このアプリケーションは回復処理を行えるでしょうか。Kubernetes は Node の CPU リソースに空きがないと、スケジューラがこのアプリケーションが動く Pod を Kill して優先度の高い Pod を別に動かすかもしれません。 - スケーラブルではない
クライアントへすべてのデータソースへの書き込みを持って成功とするレスポンスを返す必要がありそうです。そうするとステートを持たざるを得ません。ステートを持つということはスケーラビリティにかけるということです。スケールアウトされたサービスが同じステートを引き継いで動くことはできません。
こうした理由からこのアーキテクチャは Cloud Native とは言えないのではないかと思います。
イベント
回復性がある、もしくはスケーラブルなアプリケーションを構築する上で重要なポイントはステートを持たないアプリケーションにする必要があるということです。ではステートの代わりになるものは何かというとイベントになります。
イベントにはドメイン駆動設計におけるドメインイベントとデータソースの変更に伴い発生するチェンジイベントがあります。イベントの重要な点は発生したイベントは変更しようのない事実であるということです。これはステートのように時間によって変わるものではなく、イミュータブルであるという点です。イミュータブルはスケーラブルなアプリケーションを構築する点で非常に重要です。
上記の例の場合、書き込み先リソースはただ一つとしてマイクロサービスを構築し、他のデータソースへのデータの連携はチェンジイベントを使います。チェンジイベントを利用可能なプロダクトとしてチェンジデータキャプチャが使えるでしょう。OSS としては Debezium があります。
イベントストア
ドメインイベントに対応するにしろ、チェンジイベントに対応するにしろ、イベントをストアする容れ物が必要です。イベントストアに相当するのが OSS である Apache Kafka になります。
Apache Kafka は従来のメッセージングアプリとは異なり、他のアプリケーションが消費したメッセージでも、Kafka 上には残存するため(保存期間やサイズは自分で指定可能)、新しいアプリケーションを起動して、メッセージの最初から読み込むということも可能です。
Knative Eventing
イベントドリヴンアーキテクチャを Kubernetes 上で実現するためのベストプラクティスとして Cloud Native Computing Foundation は Knative を展開しています。Knative はサーバーレスで有名な Knative Serving、イベントを扱うアプリケーションを Kubernetes 上で実現する Knative Eventing、またこうしたアプリケーションをビルド、デプロイするための Build の3つのコンポーネントで構成されています。
Knative Eventing では、イベントをストアする部分を Kubernetes 上の Custom Resource である Channel として定義します。Channel は NATS や上記でご紹介した Apache Kafka を利用することができます。
Amazon AWS を利用されている方はご存知だと思いますが、例えばS3 のバケットに画像を格納すると、イベントが発生し、そのイベントを受け取って AWS Lamda が発火、画像に対して Deep Learning をかけるみたいなことを実現することができます。
このイベント部分をベンダー依存にならないように Cloud Native Computing Foundation が業界標準の CloudEvents として策定しています。
様々なシステムにつないでイベントに変換する便利屋
本記事ではデータベースの変更イベントを他のデータソースに伝え、データを反映させるという単純な話を最初にしましたが、AWS の例のようにデータベースの変更をトリガーにして Debezium 経由でイベントを Channel に格納、サーバーレスアプリケーションが起動され AI/ML を実行するというアーキテクチャも実現することが可能です
これが RDBMS ではない場合、Debezium は使えません。例えば Twitter のツイートをトリガにしたい場合、Sales Force のデータが反映された場合などがトリガになるかもしれません。
様々なシステムにつないで Apache Kafka にイベントを格納できる仕組みがあれば便利です。
Apache Camel、Camel K
これが Apache Camel になります。Camel は様々なシステムへのプラグインを持っており、プロトコル変換やデータの分岐などを簡単に実現することができます。
ただし、Camel をそのまま利用するのではなく Kubernetes 上で動作させる Camel として Camel K を利用します。
詳しくはこちらの資料をご覧ください。
http://ppalaga.github.io/presentations/191017-baselone-camel/index.html#/
Camel K は kamel コマンドを利用して、GitHub 上に定義された CustomResource(一部 Java や Groovy、JavaScript などのコードも指定)を食わせることで、様々なシステム同士を結合するインテグレーションアプリを Kubernetes 上に展開することができます。
Camel K 自体は Knative のドキュメントにも記載されていますので、ご確認ください。
Wrap Up
Cloud Native なアプリケーションを開発するには、スケーラビリティや回復性を持たせることが必要です。そのためにはマイクロサービスの定義に則って1サービス1DBの作りにしたり、ステートではなくイベントを取り扱うアプリケーションに変えていく必要があります。複数のデータソースへの反映もチェンジイベントを利用します。そうすれば Kuberentes 上でもスケール可能でかつスケジューラに Kill されても問題ないアプリケーションを実現できるでしょう。
最終的には Knative を利用して、イベント到着でサーバーレスアプリケーションが動き出し、処理が終わるとスケールダウンして 0 になり、Node の CPU を有効活用できるアーキテクチャを描けます。
ここで紹介した OSS はいずれも Red Hat から利用可能なものばかりです。
- Red Hat Fuse(Apache Camel)
- Red Hat AMQ(Apache Kafka)
- Red Hat Integration(Debezium)
- Red Hat OpenShift Container Platform(Knative、ServiceMesh等含む)