ArmeriaアプリをCentral Dogmaと連携させてKubernetes上で動かす
今までいくつかArmeriaに関する記事を書きましたが、今回はArmeriaアプリをCentral Dogmaと連携させてKubernetes上で動かしてみます。
Central Dogmaとは?
Gitをベースにした、サービス構成リポジトリです。
Spring Cloud Configみたいなものだと思ってもらって良いと思います。(僕はSpring Cloud Configは使った事ないので細かい事はわかってないですが)
公式ドキュメント
https://line.github.io/centraldogma/
その他の資料
LINE DEVELOPER DAY 2017でのセッション資料と動画が公開されています。
ユースケース
Spring Bootアプリでは、アプリ設定をyamlやpropertiesファイルとしてjarに含めたり、環境変数やコマンドライン引数で設定する事が多いと思いますが、
その場合、設定を変更するためには、アプリのビルド・デプロイや、設定のプロビジョニングが必要です。
サービス稼働中に動的に設定を変更したい場合には、Central DogmaやSpring Cloud Configを導入すると便利です。
例えば、以下のようなユースケースが考えられます。
- サービスが過負荷状態になった場合にスロットリングを行う。スロットリングの設定はCentral DogmaやSpring Cloud Configで管理しておき動的に変更可能にしておく。
※スロットリングとは、サービスが過負荷状態の時にリクエストを制限する手法の事です。
今回のアプリの構成
ブラウザからFrontendのサーバにリクエストすると、FrontendがいくつかのBackendサーバにリクエストして、結果をまとめてブラウザに返します。
構成は以下(画像をクリックすると別ウィンドウで拡大表示します)
Docker for Mac の Kubernetesで動作確認をしています。
![](https://matsumana.files.wordpress.com/2018/11/armeria_central-dogma-k8s-overview1.png?w=750)このアプリで使っているArmeriaの機能
- DocService (Swaggerみたいなやつだと思ってもらうと良いです)
- Thrift API (Async)
- REST API
- Retrofitとのintegration
- RxJava 2
- Spring Bootとのintegration
- Zipkinとのintegration
- Server side: HttpTracingService
- Client side: HttpTracingClient
- Throttling
- Server side: ThrottlingHttpService
- Automatic retry
- Client side: RetryingRpcClient(Thrift), RetryingHttpClient(REST)
- Circuit Breaker
- Client side: CircuitBreakerRpcClient(Thrift), CircuitBreakerHttpClient(REST)
- Client-side load balancing
- Central Dogmaとのintegration
- CentralDogmaEndpointGroup
関連する公式ドキュメント
- Browsing and invoking services with DocService
- Running a Thrift service
- Calling a Thrift service
- Annotated HTTP Service
- Retrofit integration
- ThrottlingService
- Automatic retry
- Circuit breaker
- Client-side load balancing and service discovery
その他、動かしているアプリ・ミドルウェア
- Prometheusによるモニタリング
(KubernetesのAPI Serverでモニタリング対象Podのディスカバリを行っている) - Zipkinによるトレーシング
(過去に書いた記事: Armeria w/ Zipkin) - Central Dogma
armeria-sandbox-job-kubernetes
というアプリでPodのディスカバリを行って、
PodリストをCentral Dogmaに保存。
そのリストをArmeriaのClient-side load balancing
で使用する。
armeria-sandbox-job-kubernetes
アプリの補足
Armeriaには、Client-side load balancing
という機能があります。
リクエスト先のAPIサーバのリストをClient側で保持して、Client側でロードバランスを行う機能です。
Kubernetesでは、PodのIPアドレスはKubernetesが動的に割り振るため、KubernetesのAPI Serverを使ってディスカバリを行い、PodリストをCentral Dogmaに保存しています。
Central DogmaにはArmeria向けのintegrarion機能があるので、Central Dogmaに保存しているPodリストを元に、ArmeriaでClient-side load balancing
が簡単に行えます。
サンプルソースコード
https://github.com/matsumana/armeria-sandbox/tree/0.2.0
0.2.0というtagを付けておきました。
今回使用したバージョン
- Java: OpenJDK (from Oracle) 11.0.1 (build 11.0.1+13)
- Armeria: 0.75.0
- com.linecorp.armeria:armeria
- com.linecorp.armeria:armeria-spring-boot-starter
- com.linecorp.armeria:armeria-thrift
- com.linecorp.armeria:armeria-retrofit2
- com.linecorp.armeria:armeria-rxjava
- com.linecorp.armeria:armeria-zipkin
- Spring Boot: 2.1.0
- org.springframework.boot:spring-boot-starter-validation (これが無いとアプリが起動できない)
- Thrift: 0.9.3 (最新は0.11.0だけど、Central Dogmaは0.9に依存している)
- thrift compiler (ソースリポジトリのlibディレクトリに同梱しています)
- org.apache.thrift:libthrift
- thrift-gradle-plugin: 0.4.0
- Retrofit: 2.4.0
- Central Dogma: 0.32.1
- Docker for Mac: 18.06.1-ce-mac73
- Engine: 18.06.1-ce
- Kubernetes: v1.10.3
サンプルアプリをKubernetesにデプロイする
1. ローカルにDocker registryを起動する
KubernetesはDocker registryからイメージを取得するので、アプリのDockerイメージを保存するためのローカルなDocker registryが必要です。
(Prometheus, Zipkin, Central DogmaはDocker Hubで公開されているので、ローカルなDocker registryにpushする必要はありません)
$ docker run -d -p 5000:5000 --name registry registry:2.6
2. Prometheus, Zipkin, Central Dogmaを起動する
$ make kubectl-create-depends
3. Central Dogmaにスロットリング設定ファイルを登録する
Central Dogmaが起動するまで少し待って、以下のコマンドを実行してください。
$ make kubectl-create-depends-data
スロットリングについては、この記事の下の方で説明します。
4. アプリをビルドする
Java 11が必要です。
$ ./gradlew --no-daemon clean build
ローカルにJava 11がインストールされていない場合、以下のコマンドを使うとDockerコンテナを使ってビルドが出来ます。
ただし処理のオーバーヘッドがあるのでかなり遅いです。
$ make build-with-docker
5. Dockerイメージをビルドする
$ make docker-build-kubernetes-dev
もしくは、
$ make docker-build-kubernetes-production
docker-build-kubernetes-dev
の方は、リモートデバッグの設定が入っているので、IntelliJなどで接続してデバッグが出来ます。
6. ローカルのDocker registryにpushする
$ make docker-push
7. アプリをKubernetesにデプロイする
$ make kubectl-create-apps
8. アプリの起動確認
まず、アプリが全て起動している事をPrometheusの画面で確認します。
以下のURLを開いて、
http://localhost:30000/targets
Status
が全てUP
になるまで待ちます。
次に、KubernetesのAPIサーバからPodの情報を収集して、Central Dogmaに正しく保存出来ているか確認します。
以下のURLを開いて、
http://localhost:30002/#/projects/armeriaSandbox/repos/apiServers
backend1.json
〜backend4.json
とfrontend.json
が出来ていればOKです。
これらのjsonファイルは、armeria-sandbox-job-kubernetes
アプリで生成しています。
9. 破棄コマンド
以下のコマンドで今回のアプリを全て破棄できます
$ make kubectl-delete-apps
$ make kubectl-delete-depends
$ docker stop registry
$ docker rm registry
サンプルアプリを動かしてみる
以下のURLにブラウザやcurlでリクエストすると、
http://localhost:31000/hello/foo
以下のレスポンスが返ってきます。各APIサーバでechoした結果を集めているだけの簡単なAPIです。
Zipkinで見てみるとこんな感じ。
backend1〜4はそれぞれ非同期でリクエストするように実装しているんですが、
Zipkin( http://localhost:30001/zipkin/ )で見るとよくわかりますね。
スロットリングしてみる
Central Dogmaに保存されているthrottling.json
がスロットリング設定ファイルです。
以下のURLを開いて、
http://localhost:30002/#/projects/armeriaSandbox/repos/apiServers/files/head/throttling.json
backend1に対するリクエストをスロットリングして、半分のリクエストを拒否するように設定してみましょう。値を0.5
にします。
http://localhost:31000/hello/foo にリクエストして、Zipkinで見てみると以下のような感じになると思います。
このアプリでは、Armeria clientのAutomatic retry
を設定しているので、リトライしている様子もよくわかりますね。
スロットリングの設定を0とかにすると、Circuit Breaker
の動作確認も簡単に出来ます。
(過去に書いた記事: ArmeriaのCircuit Breaker)
また、余談ですが、実際のサービスでリトライやCircuit Breakerの導入を検討する場合は、
SRE本の21章(過負荷への対応)〜22章(カスケード障害への対応)が参考になると思います
まとめ
今回は、ArmeriaアプリをCentral Dogmaと連携させてKubernetes上で動かし、Client-side load balancing
やスロットリングの機能を試してみました。
以上です。