🍱

k8s上でRustで作ったgRPCサービスのメトリクスを可視化する

2021/12/06に公開約6,400字

この記事はRust Advent Calendar 2021 6日目の記事です。

はじめに

実用的なサービス開発、運用する上でメトリクス計測・可視化は必要不可欠なものとなっています。Rust言語でそのような記事や具体的なサンプルがなかったので、やり方を解説してみます。

やりたいこと

  • Rustで超シンプルなgRPCアプリケーションを作る
  • metrics-rsを使ってgRPCアプリケーションのメトリクスを記録する
  • 作ったアプリケーションをKubernetes上で動かす
  • Prometheusでアプリケーションのメトリクス用のエンドポイントをService DiscoveryしてGrafanaで可視化する

RustでgRPCアプリケーションを作る

RustでgRPCを使う選択肢はいくつかあります[1]。今回はtonicを使ってみたいと思います。tonicを使う利点として、protobuf/grpcのコードを別々にビルドする必要がなく、cargo buildの中で自動的に生成してくれるところにあります。

今回はこのようなプロトコルを使います。

syntax = "proto3";

package foo;

service Foo {
    rpc echo(EchoRequest) returns (EchoReply);
}

message EchoRequest {
   string name = 1;
}

message EchoReply {
    string message = 1;
}

Client,Serverの実装はここを見てください。

metrics-rsとは?

metricsはRust言語でメトリクスを記録したり、Prometheus用のアダプタを簡単に作ることができるcrateです。

metricsプロジェクトには以下のcrateがあります。今回はmetricsmetrics-exporter-prometheusを使います。

metrics-rsでメトリクスを記録する

metricsは以下の3つのメトリクスをサポートしています。

  • Histgram
    histogram!("some_metric_name", 34.3);
    
  • Gauge
    gauge!("some_metric_name", 42.2222);
    
  • Counter
    counter!("some_metric_name", 12);
    

また、全てのメトリクスのタイプに共通して、任意のkey/valueを追加することができます。ここで追加したkey/valueはGrafana側で可視化するためのクエリで使うことができます。

histogram!("some_metric_name", 34.3, "key" => "value");

今回はServer側のechoAPIのハンドラ内で以下のメトリクスを記録しています。コードの詳細はこちら

// "echo" APIのレイテンシーの計測
histogram!("foo_histgram", now.elapsed(), "api" => "echo", "result" => "ok");

// とりあえず増えていくだけのカウンター
increment_counter!("foo_counter");

// とりあえず増えていくだけのゲージ
increment_gauge!("foo_gauge", 10.0);

Prometheus互換のexporterを立てる

metrics-exporter-prometheusを使うと、たった一行でPrometheus互換のexporterを簡単に立てることができます。

metrics_exporter_prometheus::PrometheusBuilder::new().install()?;

この一行でプログラムの中で小さいhttpサーバーが起動し、JSONでメトリクスを返すことができます。

git clone git@github.com:yukinarit/rust-k8s-grpc-metrics-example.git
cd rust-k8s-grpc-metrics-example/server
cargo run

serverを実行すると、0.0.0.0:9000をLISTENしたhttpサーバーが立ち上がりました。

$ netstat -an | grep LISTEN | grep 9000
tcp4       0      0  *.9000                 *.*                    LISTEN

このエンドポイントに対してcurlするとメトリクスのスナップショットを表示できます。

$ curl http://localhost:9000/
# TYPE foo_counter counter
foo_counter 120

# TYPE foo_gauge gauge
foo_gauge 1200

# TYPE foo_histgram summary
foo_histgram{api="echo",result="ok",quantile="0"} 0.000011611
foo_histgram{api="echo",result="ok",quantile="0.5"} 0.00003000039410022207
foo_histgram{api="echo",result="ok",quantile="0.9"} 0.00005798651714158709
foo_histgram{api="echo",result="ok",quantile="0.95"} 0.00007568731078309839
foo_histgram{api="echo",result="ok",quantile="0.99"} 0.0001138418862207591
foo_histgram{api="echo",result="ok",quantile="0.999"} 0.0001233727823801684
foo_histgram{api="echo",result="ok",quantile="1"} 0.00048648716917468264
foo_histgram_sum{api="echo",result="ok"} 0.005295823000000002
foo_histgram_count{api="echo",result="ok"} 120

gRPCアプリケーションをKubernetes上で動かす

cd rust-k8s-grpc-metrics-example

Prometheusでメトリクスを収集する

Prometheusにはkubernetes_sd_config[3]というKubernetes上のサービスをService Discoveryする機能があります。今回作ったserver-metrics-serviceサービスを追加するためのyamlは以下のようになります。

      - job_name: kubernetes-service
        scheme: http
        kubernetes_sd_configs:
        - role: endpoints
        relabel_configs:
        - source_labels:
          - __meta_kubernetes_namespace
          - __meta_kubernetes_service_name
          regex: default;kubernetes
          action: drop
        - source_labels:
          - __meta_kubernetes_namespace
          - __meta_kubernetes_service_name
          - __meta_kubernetes_endpoint_port_name
          regex: default;server-metrics-service;metrics
          action: keep

Grafanaでメトリクスを可視化する

Grafanaで自分で記録したfoo_histgram, foo_counter, foo_gaugeメトリクスを使って以下のダッシュボードを作ることができました。ダッシュボードの設定の詳細は知りたい人は、dashboard.jsonを使ってみてください。

おわりに

アドベントカレンダーに間に合わせるために説明がかなり雑になってしまいましたw

この記事作成に使ったコードは全て以下のリポジトリにあるので、興味がある人は参照してみてください。

脚注
  1. RustのgRPCライブラリ ↩︎

  2. Rust: Into tracing world ↩︎

  3. Prometheus の監視対象を ServiceDiscovery で動的に設定する ↩︎

Discussion

ログインするとコメントできます