こんにちは。サイオステクノロジーの塙です。
前回は、Red Hat OpenShift Service Mesh(以下、OSM)のセットアップ方法とサービス間のトラフィックの可視化までを行いました。
今回は、ステップアップとして収集したトラフィックデータのメトリクス収集とサービス自体がどのようなフローで流れているのか観察してみたいと思います。
メトリクスの収集
サービスが増加するにつれ、システムのパフォーマンスを測定して評価していくことは運用において重要なプロセスです。
様々なメトリクスが収集できる中でシステム運用に大切なメトリクスを取捨選択していくことが求められます。
OSMでは、サービスメッシュ内において詳細なメトリクスを収集します。これらを利用することで、トラフィックの可視化と同様に、トラブルシューティングの手助けや、最適化することが出来ていきます。
OSMのメトリクスでは、情報を収集出来るコンポーネントとして以下が挙げられます。
- Envoyプロキシ
- アプリケーション
- ControlPlane
参考までに取得出来るメトリクスについて、以下で詳細を確認出来ます。
https://istio.io/latest/docs/reference/commands/pilot-discovery/#metrics
OSMでは、メトリクスを収集するためのツールとして、PrometheusとGrafanaをデフォルトとして搭載しています。アプリケーションから様々なメトリクスを自動的に収集し、パフォーマンスを把握するのに役立ちます。
また時には、アプリケーションに固有のメトリクスを収集して、ダッシュボードに表示、管理したいといったケースも考えられます。
カスタムメトリクスの収集
今回は、カスタムメトリクスを収集するアプリケーションをデプロイし、ダッシュボード上で観察してみます。
OSMはセットアップ済みであることを前提としています。セットアップは以前までの記事を参考にしていただければと思います。
2つのアプリケーションをデプロイします。
- app1:Node.js を使用したJavaScriptのアプリケーション
- app2:Quarkusフレームワークを使用したJavaのアプリケーション
アプリケーション構成とPrometheusの設定の参考を、以下に示しておきます。
app1/xxx.js
prometheus-client パッケージを設定しています。
..(snip).. var prometheus = require('prom-client'); const prefix = 'product_svc_'; prometheus.collectDefaultMetrics({ prefix }); ..(snip)..
メトリクスを収集するためにエンドポイントを作成しています。
..(snip)..
app.get('/xxx', async function (req, res) {
responseTime.setToCurrentTime();
const end = responseTime.startTimer();
page_views.inc();
..(snip)..
app2/pom.xml
メトリクスの収集を有効化するために、依存関係の quarkus-smallrye-metrics を含めます。
..(snip).. <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-smallrye-metrics</artifactId> </dependency> ..(snip)..
app2/xxx.java
例として、ソースコード側でMeteredメトリクスというメトリクスを追記するには以下のようにします。
..(snip).. @Metered(name = "order_svc:orders_processed_rate", unit = MetricUnits.MINUTES, description = "Rate at which orders are placed", absolute = true) ..(snip)..
■ 事前準備
Developユーザーとしてログインします。ユーザーは事前に作成しています。
$ oc login -u testuser -p xxx
$ oc new-project metrics
プロジェクトを、ServiceMeshMemberRoll 内のメンバーに追加します。
$ oc patch servicemeshmemberroll/default -n istio-system --type=merge -p '{"spec": {"members": ["metrics"]}}'
■ アプリケーションのデプロイ
上記2つのアプリケーションとingress gateway, virtual serviceをデプロイします。
Prometheusがアプリケーションからメトリクスを収集出来るようにアノテーションを記載します。
$ oc create -f app1.yaml ..(snip).. annotations: sidecar.istio.io/inject: "true" # Envoyプロキシの追加 prometheus.io/scrape: "true" prometheus.io/port: "8080" prometheus.io/scheme: "http" ..(snip).. $ oc create -f app2.yaml ## 上記と同様 ## $ oc create -f gateway.yaml # 前回の記事を参考 $ oc create -f virtual-service.yaml # 前回の記事を参考
メトリクスのテストのために、IstioゲートウェイのURLを取得し、アプリケーションにアクセスします。
$ oc get route istio-ingressgateway -n istio-system -o template --template '{{ "http://" }}{{ .spec.host }}' $ curl <gateway url>/<endpoint> xxx
■ Prometheusで確認
PrometheusのURLを取得します。
$ oc get route prometheus -n istio-system -o template --template '{{ "https://" }}{{ .spec.host }}'
webブラウザでURLにアクセスします。
OpenShiftのログイン画面へ遷移します。別途アカウントへのサービスアカウントのアクセスを許可するか尋ねられますが、許可して先に進みます。
Prometheusのホーム画面です。上部タブのStatusからTargetsを選択します。
目的のエントリが見つかれば正常に連携出来ています。LabelsからPod名などで判別出来るようになっています。
上部タブのGraphをクリックします。PromQLを使用してクエリーすることが出来るページに遷移します。
クエリーにアプリケーション側で定義したメトリクスを入力すると、アクセス数に応じてグラフが表示されます。
例ではページ閲覧の回数が表示されています。 また下部に、Podごとのインスタンス情報も分かるようになっていますね。
■ Grafanaで確認
GrafanaはデータソースとしてPrometheusを使用するようにデフォルトで設定されています。
GrafanaのURLを取得します。
$ oc get route grafana -n istio-system -o template --template '{{ "https://" }}{{ .spec.host }}'
webブラウザでURLにアクセスします。
OpenShiftのログイン画面へ遷移します。別途アカウントへのサービスアカウントのアクセスを許可するか尋ねられますが、許可して先に進みます。
左タブのDashboards -> Manage をクリックします。
istioフォルダが作成されているので、展開するとistioに関するDashboardがまとめられています。
istio Mesh Dashboard を選択します。
サービスメッシュ全体の概要が表示されます。
先ほどのDashboardsページに戻り、を選択します。
上部タブで、namespaceなどでフィルタリング出来るようになっています。
オペレーション数(ops)や Rateなどが分かるようになっていますね。
Kialiを使用したサービスの観察
Jaegerでは、Podごと(+Envoyプロキシ)にトラフィックのDurationや詳細が分かりました。
Kialiでは、Podごとにどういった経路で通信が流れているのかを表示する役割を持っています。
また、Service Meshの構成とPod間のトラフィックフローをダッシュボードで直感的に理解出来るツールとなっています。
それでは、アプリケーションをデプロイして検証してみます。
■ 事前準備
Developユーザーとしてログインします。ユーザーは事前に作成しています。
$ oc login -u testuser -p xxx
新しいプロジェクトを作成します。
$ oc new-project observe-kiali
プロジェクトを、ServiceMeshMemberRoll 内のメンバーに追加します。
$ oc patch servicemeshmemberroll/default -n istio-system --type=merge -p '{"spec": {"members": ["observe-kiali"]}}'
■ アプリケーションのデプロイ
4つのアプリケーション、ingress gateway, virtual serviceをデプロイします。
下記、kiali-test.yaml には4つのアプリケーションが含まれています。
- 3つのアプリケーション x、y、z
- kiali-test:アプリケーションのエントリーポイントとして機能する API Gateway
- API Gatewayのエンドポイントは各種アプリケーションを順に呼び出します
例えば、/greet エンドポイントを呼び出したとき、kiali-test -> x, kiali-test -> y, kiali-test -> zのように呼び出します。
- API Gatewayのエンドポイントは各種アプリケーションを順に呼び出します
Envoyプロキシ設定と、Prometheus設定は追加しておきます。
$ oc create -f kiali-test.yaml ..(snip).. kind: Deployment metadata: name: x ..(snip).. spec: ..(snip).. template: metadata: annotations: sidecar.istio.io/inject: "true" prometheus.io/scrape: 'true' prometheus.io/port: '8080' prometheus.io/scheme: 'http' ..(snip).. === kind: Service metadata: name: x ..(snip).. ~~~ ..(snip).. kind: Deployment metadata: name: y ..(snip).. $ oc create -f gateway.yaml # 前回の記事を参考 $ oc create -f virtual-service.yaml # 前回の記事を参考
■ Kialiで確認
KialiのURLを取得します。
$ oc get route kiali -n istio-system -o jsonpath='{.spec.host}'
webブラウザでURLにアクセスします。
OpenShiftのログイン画面へ遷移します。別途アカウントへのサービスアカウントのアクセスを許可するか尋ねられますが、許可して先に進みます。
Overviewのページに遷移します。プロジェクト名の範囲にある4Applicationsを選択します。
4つのアプリケーションのHealthが正常であることを確認します。
左タブにあるGraph をクリックし、Graph描写画面に遷移します。
Display をクリックし、グラフの表示形式を選択していきます。
今回は以下のように選択しました。Traffic Animationを選択しておくとクエリが来た時にアニメーションで表示されるので分かりやすいです。
エンドポイントにアクセスするために、istio ゲートウェイの URL を取得します。
$ oc get route istio-ingressgateway -n istio-system -o jsonpath='{.spec.host}'
永続的にエンドポイントにクエリを続けます。
$ while true; do curl <istio-gateway>/greet; sleep 3;done xxx | yyy | zzz ..(snip)..
Kiali ダッシュボードに戻り、トラフィックのグラフを観察します。
アプリケーションのバージョン(v1)、データ伝送速度、通信の分散の割合などが確認出来ます。(先ほど選択したオプションにより表示形式は異なります)
また右側にはService Mesh全体の詳細が表示されます。
アプリケーションを一つ選択すると、そのアプリケーションの詳細が分かるようになっています。
また別のエンドポイントにクエリを投げてみましょう。
/xyz エンドポイントは、kiali-test -> x -> y -> z のように呼び出します。
$ while true; do curl <istio-gateway>/xyz; sleep 3;done xxx | yyy | zzz ..(snip)..
グラフの表示形式が変わりました。API Gatewayからアプリケーションを順に呼び出していることが分かります。
また一つ目のグラフで、アプリケーションのバージョン、トラフィックの割合などにあったように、Virtual ServiceとDestination Ruleを組み合わせると、トラフィックを柔軟に変更することが可能です。
例えば以下のようなマニフェスト定義にすると、アプリケーション x のバージョン1(v1)とバージョン2(v2)に対して、v1には20%、v2には80%の割合でトラフィックを分散してくれるようになります。
kind: DesticatioinRule metadata: name: x spec: hosts: example subsets: - labels: version: v1 name: version-v1 - labels: version: v2 name: version-v2 --- kind: VirtualService metadata: name: x-v2 spec: hosts: - example http: - route: - destination: host: example subset: version-v1 weight: 20 - destination: host: example subset: version-v2 weight: 80
他にもトラフィックの制御が出来るような設定が色々あるので、以下を参考にいただければと思います。
https://istio.io/latest/docs/reference/config/networking/destination-rule/
https://istio.io/latest/docs/reference/config/networking/virtual-service/
まとめ
今回は、メトリクスの収集とサービス観察について記事を書いてみました。
サービスの可視化だけでなく、メトリクスやkialiを使用したサービスの観察も視野に入れていくと運用の効率化に繋がります。
またトラフィックの制御も少しご紹介しました。Service Meshの内部でも分散処理など出来ることが沢山あり、理解していくのは大変と今回検証してみて実感しています。
本書の記載が読者のお役に立てれば幸いです。