Get started with ClickHouse Cloud today and receive $300 in credits. To learn more about our volume-based discounts, contact us or visit our pricing page.
本日、ClickHouse CloudがPrometheusによる拡張モニタリングをサポートしたことをお知らせできるのを楽しみにしています。この機能は一般利用可能で、クラウドインスタンスのモニタリングをこれまでになく簡単にします。ユーザーが普段使っているツールをそのまま利用できるため、オブザーバビリティにこだわるエンジニアにとって大きなメリットがあります。
多くの組織にとって、クラウドサービスを導入するときに必須となる要件のひとつが、ClickHouse自体とは独立して、その稼働状況やパフォーマンスを監視できることです。
この機能を試したい方はこちらのドキュメントをご覧ください。DatadogやGrafanaとどう連携するかを学習したい方のために、ドキュメントにはシンプルな例も用意しています。
Prometheus APIを既存のアプローチに比べてどう活用できるかや、効率的に実装する上での課題に興味があれば、ぜひこのまま読み進めてください。
背景と課題
依存するクラウドサービスを集中して監視できることは、組織にとって重要です。これまで、ClickHouse Cloudを監視したいユーザーは、必要なメトリクスをsystemテーブルに対してSQLで問い合わせて取得する方法に頼っていました。SQLに慣れていたとしても、目的に合ったクエリを組み立てるために必要なsystemテーブルを探すのは時間がかかりがちです。さらに、監視エージェント用に適切なアクセス制御や権限の設定を行う手間も発生します。
Datadogなどのエージェントを利用してClickHouse Cloudを監視する方法もありますが、Datadogの例ではクラウド側のプロキシレイヤーの都合上、呼び出すたびに異なるインスタンスへリクエストが飛ぶ可能性があり、結果的に取得したメトリクスの解釈が難しくなる課題がありました。clusterAllReplicas関数を使い、細かな設定を行うことで対策は可能でしたが、SELECTクエリによる定期的なポーリングが続くため、インスタンスがアイドル状態になるのを妨げる問題もありました。
ClickHouse Cloudのインスタンスは、利用していないときに自動的にアイドル化してコンピュートコストを抑える仕組みを備えています。そのため、監視のために継続的にクエリを投げ続けることが、ユーザーにとって好ましくないケースが多かったのです。
さらに、Prometheusフォーマットはこの手のメトリクスデータにおいて事実上の標準になりつつあり、GrafanaやDatadogなどの人気ツールも標準で対応しています。
よって、インスタンスが未使用のときに邪魔をせず、アイドル状態を妨げることなくPrometheus形式のメトリクスを提供できるシンプルなエンドポイントが最適解だと考えました。
シンプルでエレガントな設計
今回のエンドポイントに求められる要件は以下のとおりです:
- Prometheus形式のメトリクスを返す - 既存の広く使われている監視エージェントに対応する
- アイドル状態のインスタンスを起こさない - アイドル状態なら、そのことを示す簡単な情報だけ返す
- インスタンスのアイドル化を妨げない - このエンドポイントへのリクエストは、インスタンスのアイドル化判定に影響を与えない
ClickHouse本体側の設定機能を活用して各インスタンスにPrometheusエンドポイントを個別に設定することも考えられましたが、アイドル状態のインスタンスをどう扱うかという問題があり、さらにインスタンスごとにユーザーを作り権限を設定してエージェント側へ配布するのは、セキュリティ上のリスクや運用面の煩雑さを招きます。
そこで、このエンドポイントを既存のCloud APIとして実装することにしました。このAPIはすでにインスタンスの作成や設定を扱っており、組織単位のアクセス制御も備えています。数クリックでAPIキーを作成・取り消しできるため、セキュリティの攻撃面を最小限にしつつ、ClickHouseやSQLの知識が不要なシンプルなエンドポイントを提供できます。
その結果、組織IDとインスタンスIDを指定するだけで、Prometheus形式のメトリクスを安全にリクエストできるCloud APIエンドポイントを用意しました。
APIキーは組織単位で作成され、「Developer」または「Admin」を選択できます。Prometheusエンドポイントには「Developer」権限で十分なので、不正アクセスを受けても新しいサービスの作成や破壊などのリスクを最小化できます。
実装
Cloud API経由でこのエンドポイントを実装することで、仕組みをシンプルに保ちました。Cloud APIはすでに各インスタンスの状態を把握しており、アイドル状態のインスタンスにはリクエストを送らないようにできるからです。インスタンスが稼働中であれば、権限を絞った専用ユーザーでリクエストを発行します。このユーザーからのリクエストは、インスタンスのアイドル化判定の対象外となります。
メトリクス収集の効率化
あとは、systemテーブルで必要なメトリクスを集約するクエリをどう書くかという問題が残りました。ユーザーが必要とするメトリクスは複数のsystemテーブルに散在しており、ひとつの大きなクエリで取得するとそれなりに負荷がかかります。そこで、このクエリを毎回実行しないよう、最近追加されたRefreshable Materialized Viewsの仕組みを活用しています。
このビューは現在1分ごとに定期的にクエリを実行し、その結果をsystem.custom_metrics
テーブルに書き込みます。このターゲットテーブルはMemoryエンジンを使っており、Cloud APIから高速に参照可能です。以下のテーブル定義とビューの例を示します(興味がある方向けです)。
CREATE TABLE system.custom_metrics
(
`name` String,
`value` Float64,
`help` String,
`labels` Map(String, String),
`type` String
)
ENGINE = Memory
CREATE MATERIALIZED VIEW system.custom_metrics_refresher
REFRESH EVERY 1 MINUTE TO system.custom_metrics
(
`name` String,
`value` Nullable(Float64),
`help` String,
`labels` Map(String, String),
`type` String
)
AS SELECT
concat('ClickHouse_', event) AS name,
toFloat64(value) AS value,
description AS help,
map('hostname', hostName(), 'table', 'system.events') AS labels,
'counter' AS type
FROM system.events
UNION ALL
//他のメトリクス
このように、マテリアライズドビューのリフレッシュ間隔によってクエリを実行する頻度を制御し、1分に1回以上は走らないようにしています。誤った設定のエージェントなどから過剰なリクエストを送られても、サービスに負荷がかかるようなことを防げます。
エンドポイントの利用方法
まずはClickHouse CloudでAPIキーを作成します。その手順は次のとおりです。
エンドポイントが利用できる状態になったら、組織IDとインスタンスIDを取得します。
あとは、以下のようにHTTPリクエストを送るだけです:
export KEY_SECRET=<key_secret>
export KEY_ID=<key_id>
export ORG_ID=<org id>
export INSTANCE_ID=<instance id>
curl --silent --user $KEY_ID:$KEY_SECRET https://api.control-plane.clickhouse-staging.com/v1/organizations/$ORG_ID/services/$INSTANCE_ID/prometheus
…
# HELP ClickHouse_ServiceInfo サービスに関する情報(クラスタのステータスやClickHouseのバージョンなど)
# TYPE ClickHouse_ServiceInfo untyped
ClickHouse_ServiceInfo{clickhouse_org="c2ba4799-a76e-456f-a71a-b021b1fafe60",clickhouse_service="12f4a114-9746-4a75-9ce5-161ec3a73c4c",clickhouse_service_name="test service",clickhouse_cluster_status="running",clickhouse_version="24.5",scrape="full"} 1
# HELP ClickHouseProfileEvents_Query クエリとして解釈され、実行される可能性があるクエリの数
# TYPE ClickHouseProfileEvents_Query counter
ClickHouseProfileEvents_Query{clickhouse_org="c2ba4799-a76e-456f-a71a-b021b1fafe60",clickhouse_service="12f4a114-9746-4a75-9ce5-161ec3a73c4c",clickhouse_service_name="test service",hostname="c-cream-ma-20-server-3vd2ehh-0",instance="c-cream-ma-20-server-3vd2ehh-0",table="system.events"} 6
# HELP ClickHouseProfileEvents_QueriesWithSubqueries サブクエリを含むすべてのクエリの数
# TYPE ClickHouseProfileEvents_QueriesWithSubqueries counter
ClickHouseProfileEvents_QueriesWithSubqueries{clickhouse_org="c2ba4799-a76e-456f-a71a-b021b1fafe60",clickhouse_service="12f4a114-9746-4a75-9ce5-161ec3a73c4c",clickhouse_service_name="test service",hostname="c-cream-ma-20-server-3vd2ehh-0",instance="c-cream-ma-20-server-3vd2ehh-0",table="system.events"} 230
# HELP ClickHouseProfileEvents_SelectQueriesWithSubqueries サブクエリを含むSELECTクエリの数
# TYPE ClickHouseProfileEvents_SelectQueriesWithSubqueries counter
ClickHouseProfileEvents_SelectQueriesWithSubqueries{clickhouse_org="c2ba4799-a76e-456f-a71a-b021b1fafe60",clickhouse_service="12f4a114-9746-4a75-9ce5-161ec3a73c4c",clickhouse_service_name="test service",hostname="c-cream-ma-20-server-3vd2ehh-0",instance="c-cream-ma-20-server-3vd2ehh-0",table="system.events"} 224
# HELP ClickHouseProfileEvents_FileOpen 開かれたファイルの回数
# TYPE ClickHouseProfileEvents_FileOpen counter
ClickHouseProfileEvents_FileOpen{clickhouse_org="c2ba4799-a76e-456f-a71a-b021b1fafe60",clickhouse_service="12f4a114-9746-4a75-9ce5-161ec3a73c4c",clickhouse_service_name="test service",hostname="c-cream-ma-20-server-3vd2ehh-0",instance="c-cream-ma-20-server-3vd2ehh-0",table="system.events"} 4157
# HELP ClickHouseProfileEvents_Seek 'lseek'関数が呼び出された回数
# TYPE ClickHouseProfileEvents_Seek counter
ClickHouseProfileEvents_Seek{clickhouse_org="c2ba4799-a76e-456f-a71a-b021b1fafe60",clickhouse_service="12f4a114-9746-4a75-9ce5-161ec3a73c4c",clickhouse_service_name="test service",hostname="c-cream-ma-20-server-3vd2ehh-0",instance="c-cream-ma-20-server-3vd2ehh-0",table="system.events"} 1840
…
ClickHouse CloudのPrometheusエンドポイントは、ClickHouseネイティブのPrometheusエンドポイントと同等のメトリクスを公開しています。上記は一部の例ですが、実際にはClickHouseを監視するのに有用な1000を超えるメトリクスを返しています。公開されているメトリクスはClickHouseのドキュメントで確認できます。
もし必要なメトリクスがあれば、ぜひご要望をお知らせください。
インスタンスがアイドル状態の場合は、以下のように示されます:
# HELP ClickHouse_ServiceInfo サービスに関する情報(クラスタのステータスやClickHouseのバージョンなど)
# TYPE ClickHouse_ServiceInfo untyped
ClickHouse_ServiceInfo{clickhouse_org="c2ba4799-a76e-456f-a71a-b021b1fafe60",clickhouse_service="12f4a114-9746-4a75-9ce5-161ec3a73c4c",clickhouse_service_name="test service",clickhouse_cluster_status="idle",clickhouse_version="24.5",scrape="full"}
Prometheusの例
Prometheusをインストールするには、公式のガイドを参照してください。
下記はClickHouse CloudをPrometheusでスクレイプする設定例です。先ほどの手順で取得した <ORG_ID>
、<INSTANCE_ID>
、<KEY_ID>
、<KEY_SECRET>
が必要です。honor_labels
の設定はtrue
にしておく必要があります。こうしないと、インスタンスラベルが正しく設定されません。
global:
scrape_interval: 15s
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
- job_name: "clickhouse"
static_configs:
- targets: ["api.clickhouse.cloud"]
scheme: https
metrics_path: "/v1/organizations/<ORG_ID>/services/<INSTANCE_ID>/prometheus"
basic_auth:
username: <KEY_ID>
password: <KEY_SECRET>
honor_labels: true
Datadogの例
Datadog AgentとOpenMetrics連携を使うと、ClickHouse Cloudのエンドポイントからメトリクスを収集できます。以下は簡単な設定例です。
init_config:
instances:
- openmetrics_endpoint: 'https://api.control-plane.clickhouse.com/v1/organizations/97a33bdb-4db3-4067-b14f-ce40f621aae1/services/f7fefb6e-41a5-48fa-9f5f-deaaa442d5d8/prometheus'
namespace: 'clickhouse'
metrics:
- '^ClickHouse_.*'
username: username
password: password
下記は、Datadogエージェントで収集したメトリクスを使い、大きなINSERT処理を実行中のClickHouseを監視する様子です:
DatadogやGrafanaとの連携については、こちらのドキュメントで詳しく解説しています。
結論
今回リリースしたPrometheus連携によって、お気に入りのオブザーバビリティツールでClickHouse Cloudを簡単に監視できるようになります。メトリクスのセットは、私たちがClickHouseを監視する中で有用だと感じたものが中心ですが、今後も拡張される予定です。もし必要なメトリクスや、ほかのツールとの連携に関する要望があれば、ぜひ教えてください。
Get started with ClickHouse Cloud today and receive $300 in credits. At the end of your 30-day trial, continue with a pay-as-you-go plan, or contact us to learn more about our volume-based discounts. Visit our pricing page for details.