NgMonitoring 単体 Deployment 化 (Top SQL / Continuous Profiling 復活)

2026-06-27_tidbmonitor_decommission.md で TidbMonitor を廃止した結果、同梱されていた NgMonitoring が消滅し、TiDB Dashboard のヘッダーに以下の警告が出るようになった。

System Health Check Failed
A required component `NgMonitoring` is not started in this cluster. Some features may not work.

同時に左メニューの Top SQL / Continuous Profiling が無効化される。本資料は NgMonitoring を 単体 Deployment で立て直し、両機能を復活させる手順。

なぜ単体 Deployment か

NgMonitoring は元々 TidbMonitor の Pod 内サイドカーとして動いていたが、TidbMonitor を廃止した時点で「TiDB Dashboard が利用したいヘルスチェック付き軽量コンポーネント」だけが残った。TidbMonitor を NgMonitoring 用に部分復活させると Operator が Grafana / Prometheus も巻き戻し気味に管理し始めるため、純粋な ng-monitoring サーバーだけを Deployment で立てるのが最小構成。

仕組み

  • ng-monitoring サーバー (pingcap/ng-monitoring) は起動時に --pd.endpoints で渡された PD に対して 自己登録 する (PD 内部の etcd /topology/ng-monitoring/... に書き込み)

  • TiDB Dashboard (PD 組み込み) は /topology/ng-monitoring を見に行って ng-monitoring の住所を発見し、/topsql/v1/... / /continuous-profiling/... を叩く

  • v8.1 系では pd-ctl config set ng-monitoring-address存在しない (config item ng-monitoring-address not found で弾かれる)。Service と Deployment を立てれば自動発見されるので明示登録は不要

  • 動作確認は GET /dashboard/api/info/infongm_state フィールド。"started" なら Dashboard 側のヘルスチェックも通る

マニフェスト構成

実体は manifests/monitoring/ng-monitoring/ に配置済み。

manifests/monitoring/ng-monitoring/
├── kustomization.yaml         # namespace: tidb-cluster
├── configmap.yaml             # ng-monitoring.toml (pd / log / storage / continuous_profiling / metric_storage)
├── pvc.yaml                   # local-path 5Gi (Continuous Profiling のサンプル保持用)
├── deployment.yaml            # pingcap/ng-monitoring:v8.1.0, replicas=1, strategy=Recreate
└── service.yaml               # ClusterIP :12020

manifests/monitoring/kustomization.yamlresources にも - ng-monitoring を追加してあるので、kubectl apply -k manifests/monitoring/ 一発で kube-prom-stack 周辺と一緒に投入される。

設定ポイント (config map)

address = "0.0.0.0:12020"
storage_path = "/var/lib/ng-monitoring"
metric_storage = "http://kube-prom-stack-kube-prome-prometheus.monitoring:9090"

[log]
path = ""
level = "INFO"          # ← 大文字必須。"info" は弾かれて起動失敗する

[pd]
endpoints = ["basic-pd:2379"]

[continuous_profiling]
enable = true
profile_seconds = 10
interval_seconds = 60
timeout_seconds = 120
data_retention_seconds = 259200    # 3日
  • log.level は大文字 (DEBUG / INFO / WARN / ERROR)。小文字を指定すると Failed to initialize config, err: log level should be DEBUG, INFO, WARN or ERROR で CrashLoopBackOff になる

  • metric_storage は kube-prom-stack の Prometheus を向ける。Decommission 手順 Step 5 で PD の metric-storage に入れたのと同じ宛先

  • continuous_profiling.enable = true は初回起動時 (docdb が空のとき) の初期値にしかならない。一度 UI / API で OFF にされると docdb に永続化された値が TOML より優先され、Pod を再起動しても無効のまま (復旧は後述「Continuous Profiling の有効化」)

deployment ポイント

args:
  - --config=/etc/ng-monitoring/ng-monitoring.toml
  - --advertise-address=$(POD_IP):12020
env:
  - name: POD_IP
    valueFrom:
      fieldRef:
        fieldPath: status.podIP

--advertise-address は PD への自己登録に使われる。Pod IP を渡しておくと Dashboard / 他コンポーネントから Pod IP に直接アクセスできる (Service 経由でも到達可能だが、PD 自己登録には個別 Pod IP の方が無難)。

適用手順

前提: ~/.kube/config-mycluster から TiDB クラスタへ到達可能 (Tailscale 経由 node1:6443)

export KUBECONFIG=~/.kube/config-mycluster

# 1. 適用
kubectl apply -k manifests/monitoring/ng-monitoring/

# 2. Pod Ready 待ち
kubectl -n tidb-cluster rollout status deploy/ng-monitoring --timeout=90s

# 3. ログで config 読み込みと PD client 接続を確認
kubectl -n tidb-cluster logs deploy/ng-monitoring --tail=20
#   "Welcome to ng-monitoring." と
#   "create pd client success" [pd-address=basic-pd:2379] が出ていれば OK

Top SQL の計測を有効化 (TiDB 側)

ng-monitoring を立てても、TiDB は デフォルトでは Top SQL データを送らないtidb_enable_top_sql システム変数を ON にする必要がある (TiDB v6.0+)。SET GLOBALmysql.global_variables に永続化されるので Pod 再起動では消えないが、TiDB Cluster ごと作り直したら再投入が必要。

export KUBECONFIG=~/.kube/config-mycluster
kubectl -n tidb-cluster port-forward svc/basic-tidb 14000:4000 >/dev/null 2>&1 &
sleep 2

# TiDB の Pod / Service には mysql クライアントが入っていないので手元から実行
mysql -h 127.0.0.1 -P 14000 -u root --protocol=TCP -e "
  SET GLOBAL tidb_enable_top_sql = 1;
  SELECT @@global.tidb_enable_top_sql AS top_sql_global;
"
# → top_sql_global = 1 になればOK

pkill -f "port-forward.*basic-tidb.*14000"

Continuous Profiling は ng-monitoring 側だけで完結するが、Top SQL は TiDB 側のフラグも要る、という非対称があるので注意。

Continuous Profiling の有効化 (ng-monitoring 実行時設定)

TOML の [continuous_profiling] enable = true初回起動時 (docdb が空のとき) の初期値 でしかない。一度でも Dashboard UI や API で OFF にされると docdb に false が永続化され、以後 Pod を再起動しても docdb の値が TOML より優先される。ON に戻すには ng-monitoring の /config API を叩く (Dashboard UI の「プロファイリングを有効化」ボタンが裏で呼んでいるのと同じ API)。

export KUBECONFIG=~/.kube/config-mycluster
kubectl -n tidb-cluster port-forward svc/ng-monitoring 12020:12020 >/dev/null 2>&1 &
sleep 2

# 実効設定の確認 (TOML ではなく docdb 反映後の値が返る)
curl -s http://localhost:12020/config | jq .continuous_profiling

# 有効化 (docdb に永続化。Pod 再起動でも維持、PVC を消したら再投入が必要)
curl -s -X POST http://localhost:12020/config \
  -H 'Content-Type: application/json' \
  -d '{"continuous_profiling": {"enable": true}}'
# → {"status":"ok"}

# 収集確認 (interval_seconds=60 なので 1〜2 分待ってから)
NOW=$(date +%s)
curl -s "http://localhost:12020/continuous_profiling/group_profiles?begin_time=$((NOW-300))&end_time=$NOW" \
  | jq '[.[] | {ts, state}]'
# → state: "finished" のエントリが 1 分刻みで並べば OK

pkill -f "port-forward.*ng-monitoring.*12020"

Top SQL (tidb_enable_top_sql) と同じ性質: コマンドで永続化され Pod 再起動では消えないが、ストレージ (PVC) ごと作り直したら再投入が必要。TOML だけ直しても docdb に古い値が残っていると反映されない。

動作確認

Dashboard 側のヘルスチェック

# TiDB Dashboard が動いている PD pod に port-forward (dashboard-address を見て選ぶ)
kubectl -n tidb-cluster exec basic-pd-0 -- /pd-ctl config show all | grep dashboard-address
# → "dashboard-address": "http://basic-pd-1.basic-pd-peer.tidb-cluster.svc:2379"

kubectl -n tidb-cluster port-forward basic-pd-1 12379:2379 &
sleep 2
curl -s http://localhost:12379/dashboard/api/info/info | jq .ngm_state
# → "started"  ← これになれば Dashboard ヘッダーの赤バナーは消える
pkill -f "port-forward basic-pd-1 12379"

ブラウザ側

https://tidb-dashboard.<tailnet>.ts.net:2379/dashboard をリロード:

  • ヘッダーの System Health Check Failed - NgMonitoring is not started バナーが消える

  • 左メニューの Top SQL が活性化し、TiDB instance を選んでしばらくすると (収集間隔約 1 分) SQL 別の CPU 使用率時系列が描画される

    • 描画されない場合は tidb_enable_top_sql = 1 が入っているか再確認 (上記「Top SQL の計測を有効化」)

  • 左メニューの Continuous Profiling が活性化し、Start Profiling ボタンから On-CPU / Off-CPU / Mutex / Goroutine プロファイルを取れる

トラブルシュート

CrashLoopBackOff: log level エラー

Failed to initialize config, err: log level should be DEBUG, INFO, WARN or ERROR

configmap.yaml[log] level を大文字に直して kubectl apply -kkubectl -n tidb-cluster rollout restart deploy/ng-monitoring

CrashLoopBackOff: PD に繋がらない

"create pd client failed" ... connection refused

[pd] endpoints の Service 名/ポートが間違っているか、PD が起動していない。 kubectl -n tidb-cluster get svc basic-pd でポート (2379/TCP) を確認。

Top SQL タブが "No data" のまま

  • TiDB の tidb_enable_top_sql が 0 のまま。「Top SQL の計測を有効化」節の手順で 1 にする

  • それでも出ない時は ng-monitoring の metric_storage が kube-prom-stack の Prometheus を向いているか確認 (configmap.yaml)。Top SQL UI は ng-monitoring 経由で Prometheus にも問い合わせる

  • 一定時間経過しても出ない場合は kubectl -n tidb-cluster logs deploy/ng-monitoring | grep -i topsql でエラーがないか確認

Continuous Profiling が TOML で enable = true なのに無効のまま

  • 実行時設定は docdb に永続化された値が TOML より優先される。「Continuous Profiling の有効化」節の /config API で ON に戻す

  • 有効化直後の収集で finished_with_error (TiKV heap profile の Unable to create profile directory /root/jeprof: File exists) が単発で出ることがあるが、以降の収集が finished になっていれば問題ない

Dashboard で ngm_state が "unknown" のまま

  • ng-monitoring Pod が Running でも --advertise-addressService ClusterIPlocalhost になっていると PD からの自己登録が見えない。--advertise-address=$(POD_IP):12020 になっていることを確認:

    kubectl -n tidb-cluster get pod -l app.kubernetes.io/name=ng-monitoring -o jsonpath='{.items[0].spec.containers[0].args}'
    
  • それでも直らない時は ng-monitoring を再起動 (rollout restart) して PD への登録を打ち直す

廃止する場合

export KUBECONFIG=~/.kube/config-mycluster
kubectl delete -k manifests/monitoring/ng-monitoring/

# ノード上の PVC 実体 (local-path)
PV=$(kubectl -n tidb-cluster get pvc ng-monitoring -o jsonpath='{.spec.volumeName}' 2>/dev/null)
[[ -n "$PV" ]] && kubectl delete pv "$PV" --ignore-not-found
for n in node1 node2 node3; do
  ssh $n 'sudo rm -rf /opt/local-path-provisioner/*ng-monitoring*'
done

manifests/monitoring/kustomization.yaml から - ng-monitoring 行も削除。

TODO

  • 2026-06-25_construction_plan.md の本編に NgMonitoring 単体 Deployment 構成として統合する (Phase 4.5 の直後あたり)

  • 2026-06-27_tidbmonitor_decommission.md の「別資料化 TODO」セクションから本資料へのリンクに更新

参考

  • pingcap/ng-monitoring — 上流リポジトリ。config フィールド名と起動フラグの一次ソース

  • TiDB Operator monitor manifest (参考用) — TidbMonitor 内で ng-monitoring に渡している args / config を参考にした

  • docs/source/tasks/2026-06-27-tidbmonitor-decommission.md — 本資料の前段 (なぜ単体 Deployment 化が必要か)