Cloud Run services メトリクス監視「だいたいぜんぶ」

## はじめに
こんにちは、Datadog Japan で Sales Engineer をしている [**AoTo**](https://qiita.com/AoTo0330) です。
Google Cloud で好きなサービスは、圧倒的に **Cloud Run** です！

この投稿は **[<font color="#6495ED">AoTo Advent Calendar 2024</font>](https://qiita.com/advent-calendar/2024/aoto) 15日目**の記事です。

皆さんは　**Cloud Run** の監視、きちんと行えているでしょうか？

**Cloud Run** は **Google Cloud** のマネージドサービスであり、デフォルトで **Cloud Logging, Cloud Monitoring, Cloud Trace** と統合されています。

![Monitoring_CloudRun.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/17ae2c59-bb66-d48b-3a1b-a65c4740fc85.png)

ということは、**Cloud Run service** のメトリクス監視は **Cloud Monitoring** で自動的にできるから設計を考える必要がないのでしょうか？
いやいや、まだまだメトリクス監視は奥深いんです！

…ということで、**Cloud Run service** を利用されるすべての方に向けて、**Google Cloud** で利用できるデフォルト・オプションそれぞのメトリクス監視とを体系的にまとめてみました🐶

:::note info
ちなみに Cloud Run 監視の基本は、「[**Cloud Run Advent Calendar 2023**](https://qiita.com/advent-calendar/2023/cloud-run)」で Google Cloud Japan の諏訪さんがまとめられています。
:::


https://zenn.dev/google_cloud_jp/articles/cloudrun-monitoring

## Cloud Run のリソースモデルと組み込みメトリクス
**Cloud Run service** はシンプルなマネージドコンテナホスティングサービス(Container as a Service, CaaS) です。[**Cloud Run service**](https://cloud.google.com/run/docs/resource-model?hl=ja) を頂点として、①サービス -> ②リビジョン -> ③インスタンス -> ④コンテナのように階層構造のリソースモデルを持ちます。

![Logging_CloudRun_number.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/335c24dd-9976-cb0a-4c5a-72cff29c3fe4.png)

**Cloud Monitoring** では、**Cloud Run service** のそれぞれのリソース階層を対象にしたメトリクスを提供しています。

 - ①サービス: リクエスト数・リクエストレイテンシー・リクエスト/レスポンスサイズ・クォータ
 - ②リビジョン: リクエスト数・リクエストレイテンシー・リクエスト/レスポンスサイズ
 - ③インスタンス: 課金対象の時間・起動数・コンテナ最大同時実行数・コンテナ起動時のレイテンシ
 - ④コンテナ: CPU/メモリ 割り当て時間・CPU/メモリ/GPU メモリ使用率・送受信バイト

ざっくりと各リソース階層に分類すると、このようになります。各リソースにおいて重要なメトリクスは概ね**何も設定しなくても**取得されるのが、**Cloud Run** がマネージドサービスである利点です。

これらのメトリクスは Google Cloud 公式ドキュメントでも「[組み込み指標](https://cloud.google.com/run/docs/monitoring?hl=ja#built-in_metrics)」として紹介されています。提供されているすべての「組み込み指標」は [Google Cloud metrics(run)](https://cloud.google.com/monitoring/api/metrics_gcp#gcp-run) ページから確認できます。

## Cloud Run のカスタムメトリクス監視
ここからは、追加のカスタムメトリクス監視として「[Prometheus 指標](https://cloud.google.com/run/docs/monitoring-managed-prometheus-sidecar?hl=ja)」と「[OpenTelemetry 指標](https://cloud.google.com/run/docs/tutorials/custom-metrics-opentelemetry-sidecar?hl=ja)」を詳しく解説します。どちらも **Cloud Native Computng Foundation(CNCF)** から生まれた、メトリクスを扱うオープンソースプロジェクトです。

### Google Cloud Managed Service for Prometheus
メインアプリケーションコンテナから生成されたそれぞれのカスタムメトリクスは、[サイドカー(マルチコンテナ)デプロイメント](https://cloud.google.com/run/docs/deploying?hl=ja#sidecars)で用意された監視エージェントコンテナにより収集・転送され **Cloud Monitoring** 上で可視化できます。

**Google Cloud Managed Service for Prometheus(Google Managed Prometheus, GMP)** は **Cloud Monitoring ingest API** を利用して、Prometheus 形式のメトリクスを受け取ることができます。こうしたメトリクスは [**Monarch**](https://research.google/pubs/monarch-googles-planet-scale-in-memory-time-series-database/) と呼ばれる分散型インメモリ時系列データベースに保管され、堅牢で高効率なインフラストラクチャーによる Prometheus マネージドサービスが提供されています。

**GMP** は **Cloud Monitoring** と緊密に統合されているため、利用時にはサービスの存在を意識することはありません。**Google Cloud Console** 上での **Cloud Monitoring** や、**Cloud Monitoring API** の利用時に Prometheus 形式のメトリクスや PromQL クエリを利用する場合に、内部的に **GMP** や **Monarch** が用意されています。

### Prometheus メトリクス
![CloudRun_P.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/2f545f96-39ac-3446-9cf3-617170d4d428.png)


#### `RunMonitoring` の構成
Prometheus メトリクスを収集する場合には、既存のアプリケーションコンテナからサイドカーコンテナが pull 型でメトリクスエンドポイントからメトリクス情報をスクレイピングして取得します。

こうした Prometheus メトリクスエンドポイントの構成を行うのが `RunMonitoring` です。これは、Kubernetes `PodMonitoring` から Kubernetes 固有のオプションを除外し、Cloud Run で必要な構成だけをサポートしたサブセットです。

Cloud Run は `kind: Service` で Knative Serving 互換構成のコンテナのみを扱います。そのため、この `kind: RunMonitoring` 構成は監視エージェントコンテナの `/etc/rungmp/` に `config.yaml` として配置して、コンテナ構成の定義として直接参照する必要があります。特に指定がない場合、`RunMonitoring` は `/metrics` のポート `8080` から30秒ごとにメトリクスをスクレイピングします。

カスタム `RunMonitoring` 構成により、スクレイピング用のエンドポイントとポートなどの構成をカスタムで定義できます。構成できるオプションは『[Cloud Run で GMP を利用する際の注意点](https://zenn.dev/aotolog/articles/cr-gmp-notes#rummonitoringの構成)』で解説しています。

https://zenn.dev/aotolog/articles/cr-gmp-notes

カスタム `RunMonitoring` 構成ファイル `config.yaml` を作成したら、[**Google Cloud Secret Manager**](https://cloud.google.com/secret-manager/docs/overview?hl=ja) シークレットとして `config.yaml` を格納します。そのシークレットを、Cloud Run の`run-service.yaml` に直接 `volumes:` としてマウントし、Cloud Run の `RunMonitoring` 構成ファイルとして使用します。[^1]
[^1]: Cloud Run 第二世代では、マウントされたボリュームは Cloud Run コンテナインスタンスの `root` が所有します。

```run-service.yaml
spec:
  template:
    metadata:
      annotations:
        (中略)
+       run.googleapis.com/secrets: 'mysecret:projects/PROJECT_ID/secrets/mysecret'
    spec:
      containers:
      　(中略)
+     volumes:
+     - name: config
+       secret:
+         items:
+         - key: latest
+           path: config.yaml
+         secretName: 'mysecret'
```

#### 監視エージェントコンテナの構成
前述の `RunMonitoring` 構成に従って Prometheus メトリクスを取得する監視エージェントコンテナは、[`cloud-run-gmp-sidecar/collector`](https://github.com/GoogleCloudPlatform/run-gmp-sidecar/tree/main/collector) として公開されています。

[`cloud-run-gmp-sidecar/collector`](https://github.com/GoogleCloudPlatform/run-gmp-sidecar/tree/main/collector) で構成されている内容を確認すると、Prometheus メトリクスは **OpenTelemetry Collector** の **Prometheus Receiver** によって取得されます。その後、同じく OpenTelemetry Collector の **Google Managed Service for Prometheus Exporter** が **GMP** への転送を担います。


### OpenTelemetry メトリクス
![CloudRun_O.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/2581e829-9dcd-7db0-3807-693cfe4d68e3.png)

OpenTelemetry メトリクスを取得する際は、OpenTelemetry Collector の構成とデプロイのみで一連の収集・制御・転送が実現できます。[Googl Cloud 公式サンプル](https://cloud.google.com/run/docs/tutorials/custom-metrics-opentelemetry-sidecar?hl=ja#review-code) では、カスタム OpenTelemetry Collector をビルドする案内があります。

このカスタム OpenTelemetry Collector は、OTLP Receiver, Batch Processor, Google Managed Service for Prometheus Exporter を基本に、Memory Limiter, Resource Detection, ResourceMemory Limiter, Resource Detection, Resource などの Processor を構成しています。

カスタム OpenTelemetry Collector を作成したことない場合は、逆井([@k6s4i53rx](https://x.com/k6s4i53rx))さんの『[OpenTelemetry Collector Builder (ocb) を使ってお好みの OTel Collector を作る](https://zenn.dev/k6s4i53rx/articles/df59cb65b34ef8)』をご参考ください。

https://zenn.dev/k6s4i53rx/articles/df59cb65b34ef8

## 番外編: ログベースメトリクス
Cloud Run に限った話ではないですが、**Cloud Monitoring** では収集したログをもとにログベースメトリクスを作成できます。

この機能では、特定の条件に合致するログを集計しメトリクス化することで、特定の期間における特定のログの発生頻度を可視化できます。また、ログベースメトリクスを条件としたグラフやアラートを簡単に設定できる点も大きなポイントです。

ログベースメトリクスは [Logging のクエリ言語](https://cloud.google.com/logging/docs/view/logging-query-language?hl=ja)に基づいてフィルタリングされたログの数を対象の時間範囲に対して測定する[カウンタメトリクス](https://cloud.google.com/logging/docs/logs-based-metrics?hl=ja#counter-metric)と、フィルタリングされたログ内のフィールドの数値の分布を記録する[分布メトリクス](https://cloud.google.com/logging/docs/logs-based-metrics?hl=ja#counter-metric)を作成できます。

Cloud Run の特定のサービスを対象としたログを元にメトリクスを作成する場合は、以下のようにフィルタリングできます。

```hql: logging.ebnf
resource.type = "cloud_run_revision"
resource.labels.service_name = "<SERVICE_NAME>"
resource.labels.location = "<REGION_NAME>"
 severity >= DEFAULT
```

## おわりに
**Cloud Run service** で利用できるメトリクス監視の様々なオプションを、図解されたアーキテクチャと具体的な実装方法に触れながら解説しました。

**Cloud Run service** はマルチコンテナ対応によって Prometheus, OpenTelmetry メトリクスの Google Managed Service for Prometheus への連携ができるようになりました。これらの実装方法を詳しく知っておくことで、今後 Cloud Run 上でメトリクスを測定・収集しサービスの信頼性を向上することができるはずです🐶