IstioとPrometheusを組み合わせると、アプリのコードに手を入れずに、サービスごとのリクエスト数、エラー率、レイテンシを集められます。この記事では、標準メトリクスの読み方、既存のPrometheusへの収集設定、PromQL、GrafanaとKialiへのつなぎ方、時系列を抑える設定を、Istio 1.31系の公式ドキュメントに沿ったYAMLで示します。
まとめ:Envoyのメトリクスを集めreporterで絞りラベルを削る
Istioのサイドカーやゲートウェイは、通過したリクエストをistio_requests_totalなどの標準メトリクスとして公開します。Prometheusはこれを収集するだけでよく、アプリ側に計装を足す必要はありません。検証ならsamples/addonsのPrometheus、Grafana、Kialiをkubectl applyで入れれば数分で画面まで届きます。
集計では、1回のリクエストが送信元と宛先の両方から報告される点に注意し、reporterラベルをどちらかに固定します。そろえないと件数が2倍になります。
本番では、既存の監視基盤へscrapeの設定を足すか、記録ルールで集約した値をフェデレーションで送ります。ラベルの多さで時系列が膨らむため、Telemetry APIで不要なラベルを削る設計も最初から入れておきます。
Istioが出す標準メトリクスとPrometheusが集める対象を確認
Istio全体の仕組みはIstioとは?サービスメッシュの仕組みとサイドカー/アンビエント方式・導入判断を解説で扱っています。ここでは、Prometheusから見えるメトリクスの名前とラベルを押さえます。
HTTPとgRPCとTCPで出るistio_で始まる標準メトリクス
Istio Standard Metricsのリファレンスによると、HTTP、HTTP/2、gRPCの通信では次のメトリクスが出ます。
istio_requests_total(COUNTER):処理したリクエスト数istio_request_duration_milliseconds(DISTRIBUTION):リクエストの所要時間istio_request_bytes(DISTRIBUTION):リクエスト本文の大きさistio_response_bytes(DISTRIBUTION):レスポンス本文の大きさ
gRPCではこれに加えて、メッセージ数を数えるistio_request_messages_totalとistio_response_messages_totalが出ます。TCPの通信では、送受信バイト数のistio_tcp_sent_bytes_totalとistio_tcp_received_bytes_total、接続の開始と終了を数えるistio_tcp_connections_opened_totalとistio_tcp_connections_closed_totalの4つです。DISTRIBUTIONの型は、Prometheus上では_bucket、_sum、_countの3系列に分かれたヒストグラムとして見えます。
集計時のreporterラベルと送信元・宛先のラベルの読み方
同じリファレンスは、メトリクスに付くラベルも定めています。集計でよく使うのは次のラベルです。
reporter:宛先側のプロキシが報告したらdestination、送信元側のプロキシかゲートウェイならsourcesource_workloadとdestination_workload:呼び出し元と呼び出し先のワークロード名destination_service:宛先のサービスのホスト名(例:details.default.svc.cluster.local)response_code:HTTPのステータスコード(HTTPのメトリクスだけに付く)connection_security_policy:宛先側の報告でmTLSが使われていればmutual_tls
サイドカー方式では、1回の呼び出しが送信元と宛先の両方のサイドカーで数えられます。受信量はreporter="destination"、呼び出し元から見た遅延はreporter="source"と決めておくと、画面とアラートの数字が食い違いません。
samples/addonsでPrometheusとGrafanaとKialiを入れて試す
まずは検証用のクラスタで、メトリクスが届くまでを確かめます。Istio本体のインストールにPrometheusは含まれないため、別に入れる必要があります。
kubectl applyでアドオンを入れistioctl dashboardで開く
IstioのPrometheus連携ページは、クイックスタートとして次のマニフェストを示しています。GrafanaとKialiも同じrelease-1.31のディレクトリにあります。
# Istio 1.31系に対応したアドオンを入れる
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.31/samples/addons/prometheus.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.31/samples/addons/grafana.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.31/samples/addons/kiali.yaml
# Prometheusのサービスが起動したか確かめる
kubectl -n istio-system get svc prometheus
# ポートフォワードしてブラウザでUIを開く
istioctl dashboard prometheus
istioctl dashboard grafana
istioctl dashboard kiali
公式のQuerying Metricsタスクの手順どおり、アプリに何度かリクエストを送ってから、PrometheusのUIでistio_requests_totalを実行すると結果が返ります。公式はこれらをデモ用と明記しており、Observability Best Practicesによれば、クイックスタートのPrometheusの保持期間は6時間です。
15020番ポートのメトリクスマージとプロキシからの直接確認
Prometheus連携ページによると、Istioは既定で「メトリクスマージ」を有効にしています。データプレーンのPodにはprometheus.ioのアノテーションが自動で付き、Envoyのメトリクスとアプリ自身のメトリクスがまとめて:15020/stats/prometheusから公開されます。
メトリクスが見えないときは、先にプロキシが値を出しているかを確かめます。公式のCustomizing Istio Metricsタスクの確認方法は次のとおりです。
# サイドカーのEnvoyが出しているistio_requests_totalを直接見る
kubectl exec "$(kubectl get pod -l app=productpage -o jsonpath='{.items[0].metadata.name}')" \
-c istio-proxy -- curl -sS 'localhost:15000/stats/prometheus' | grep istio_requests_total
ここに値があれば原因は収集の設定です。アプリが同名のメトリクスを出す場合やTLSで収集したい場合は、Podにprometheus.istio.io/merge-metrics: "false"を付けてマージを止めます。
既存のPrometheusやOperatorにIstio向けの収集設定を足す
すでに監視基盤のPrometheusがある場合は、アドオンを入れずにIstioの収集ジョブを追加します。Prometheusそのものの構築とexporterの設計はPrometheusで監視を構築する手順|exporter設計・PromQL・保持期間の見積りにまとめています。
scrape_configsにistiodとenvoy-statsのジョブを追加する
Prometheus連携ページが示すジョブは2本です。1本目はコントロールプレーンのistiodを、2本目はサイドカーとゲートウェイのEnvoyを対象にします。
scrape_configs:
- job_name: 'istiod'
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- istio-system
relabel_configs:
- source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: istiod;http-monitoring
- job_name: 'envoy-stats'
metrics_path: /stats/prometheus
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_container_port_name]
action: keep
regex: '.*-envoy-prom'
envoy-statsのジョブは、コンテナのポート名が-envoy-promで終わるものだけを残します。サイドカーが注入されたPodにはこの名前のポートが定義されるため、アプリのポートと取り違えずに済みます。
PodMonitorとServiceMonitorで集めるOperator向けの書き方
Prometheus Operatorやkube-prometheus-stackを使っている環境では、scrape_configsを直接書かずにカスタムリソースで指定します。Istioのリポジトリにあるsamples/addons/extras/prometheus-operator.yamlから、要点を抜き出すと次のとおりです。
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: envoy-stats-monitor
namespace: istio-system
labels:
monitoring: istio-proxies
release: istio
spec:
selector:
matchExpressions:
- {key: istio-prometheus-ignore, operator: DoesNotExist}
namespaceSelector:
any: true
jobLabel: envoy-stats
podMetricsEndpoints:
- path: /stats/prometheus
interval: 15s
relabelings:
- action: keep
sourceLabels: [__meta_kubernetes_pod_container_name]
regex: "istio-proxy"
- action: keep
sourceLabels: [__meta_kubernetes_pod_annotationpresent_prometheus_io_scrape]
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: istio-component-monitor
namespace: istio-system
labels:
monitoring: istio-components
release: istio
spec:
jobLabel: istio
targetLabels: [app]
selector:
matchExpressions:
- {key: istio, operator: In, values: [pilot]}
namespaceSelector:
any: true
endpoints:
- port: http-monitoring
interval: 15s
原本のPodMonitorには収集先のアドレスを組み立てるrelabelingも続くため、適用には原本を使ってください。release: istioのラベルは、PrometheusリソースのpodMonitorSelectorとserviceMonitorSelectorに合わせて書き換えます。一致しないと収集は始まりません。
STRICTのmTLS環境でアプリのメトリクスを集める証明書の設定
Prometheus連携ページによると、コントロールプレーン、ゲートウェイ、サイドカーのメトリクスは平文で収集されます。mTLSの影響を受けるのは、アプリ自身が出すメトリクスだけです。PeerAuthenticationがSTRICTなら、Prometheusにもメッシュの証明書を持たせる必要があります。PERMISSIVEの場合は、PrometheusにTLSを設定してはいけません。
公式の方法は、Prometheusのポッドにサイドカーを注入しつつ、通信の横取りは止め、証明書だけを共有ボリュームへ書き出させるものです。
# Prometheusのポッドテンプレートに付けるアノテーション
traffic.sidecar.istio.io/includeInboundPorts: ""
traffic.sidecar.istio.io/includeOutboundIPRanges: ""
proxy.istio.io/config: |
proxyMetadata:
OUTPUT_CERTS: /etc/istio-output-certs
sidecar.istio.io/userVolumeMount: '[{"name": "istio-certs", "mountPath": "/etc/istio-output-certs"}]'
# 収集ジョブ側のTLS設定
scheme: https
tls_config:
ca_file: /etc/prom-certs/root-cert.pem
cert_file: /etc/prom-certs/cert-chain.pem
key_file: /etc/prom-certs/key.pem
insecure_skip_verify: true
Prometheusのコンテナには同じistio-certsを/etc/prom-certs/にマウントします。insecure_skip_verifyは、Istioのセキュアネーミングに未対応なため公式が付けている設定です。STRICT化の手順そのものはIstio AuthorizationPolicyの書き方:ALLOW・DENYの評価順とmTLS前提のYAML例で扱っています。
PromQLでリクエスト数とエラー率とP95レイテンシを出す
集めたメトリクスから、サービスの状態を表す数字を作ります。関数の詳細はPrometheusのQuery functionsにあります。
rateとsum byでサービスごとの毎秒リクエスト数を出す
istio_requests_totalは増え続けるカウンターなので、rateで毎秒の値に直してから集計します。
# 宛先サービスごとの毎秒リクエスト数(過去5分の平均)
sum by (destination_service_name, destination_service_namespace) (
rate(istio_requests_total{reporter="destination"}[5m])
)
# 呼び出し元と呼び出し先の組み合わせで見る
sum by (source_workload, destination_workload) (
rate(istio_requests_total{reporter="destination"}[5m])
)
2本目は、どのサービスがどこを呼んでいるかを表で見るクエリです。destination_workloadがunknownの行は宛先の情報が取れていない呼び出しで、メッシュ外への通信が混ざっていないかの手がかりになります。
5xxのエラー率とhistogram_quantileでP95を求めるクエリ
エラー率は、5xxの件数を全体の件数で割って出します。レイテンシは_bucketの系列をhistogram_quantileに渡します。
# サービスごとの5xxエラー率(0〜1)
sum by (destination_service_name) (
rate(istio_requests_total{reporter="destination", response_code=~"5.."}[5m])
)
/
sum by (destination_service_name) (
rate(istio_requests_total{reporter="destination"}[5m])
)
# 呼び出し元から見たP95レイテンシ(ミリ秒)
histogram_quantile(0.95,
sum by (destination_service_name, le) (
rate(istio_request_duration_milliseconds_bucket{reporter="source"}[5m])
)
)
# mTLSを使っていない受信がないかを確かめる
sum by (destination_workload) (
rate(istio_requests_total{reporter="destination", connection_security_policy!="mutual_tls"}[5m])
)
histogram_quantileに渡すsum byには、必ずleを残します。leを落とすとバケットの境界が失われ、値が計算できません。3本目のクエリは、PERMISSIVEからSTRICTへ移す前に平文の通信が残っていないかを数えるのに使えます。エラー率やレイテンシをSLIとして扱う考え方はSLIとは?SLOとの違いと指標の選び方・PromQLでの測り方で解説しています。
PrometheusRuleでエラー率が上がったときのアラートを定義する
Prometheus Operatorを使っている場合、上のエラー率の式をそのままアラートの条件にできます。閾値と継続時間は、サービスのSLOに合わせて決めてください。
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: istio-service-alerts
namespace: monitoring
spec:
groups:
- name: istio-service
rules:
- alert: IstioHigh5xxRate
expr: |
sum by (destination_service_name) (
rate(istio_requests_total{reporter="destination", response_code=~"5.."}[5m])
)
/
sum by (destination_service_name) (
rate(istio_requests_total{reporter="destination"}[5m])
) > 0.05
for: 10m
labels:
severity: warning
annotations:
summary: "{{ $labels.destination_service_name }} の5xx率が5%を超えています"
リクエストの少ない時間帯は1件の失敗で率が大きく振れるので、分母の値に> 1などの条件をandで足すと誤報が減ります。Kubernetes全体のアラート閾値の考え方はKubernetes監視・モニタリングの設計|メトリクス・ログ・アラート閾値の実装判断にまとめています。
GrafanaのIstioダッシュボードとKialiを外部Prometheusへ接続
クエリを毎回書かなくても、Istioが用意したダッシュボードとKialiで全体を見渡せます。アドオンではなく既存のGrafanaやPrometheusを使う場合のつなぎ方を示します。
grafana.comのダッシュボードIDと既存Grafanaへの取り込み
IstioのGrafana連携ページは、メッシュ全体、サービス別、ワークロード別、性能、コントロールプレーン、WebAssembly拡張、ztunnelの7種類のダッシュボードを挙げています。grafana.comでのIDは7639、11829、7636、7630、7645、13277、21306で、7639がIstio Mesh Dashboard、21306がztunnel用です。
既存のGrafanaでは「Import」にIDを入れ、Istioのメトリクスを集めているPrometheusをデータソースに選びます。公式ページには7つをまとめて取り込むスクリプトも載っています。リビジョンはIstioの版ごとに作られるので、使っている版に合うものを選んでください。
KialiのCRでexternal_servicesのPrometheus接続先を指定
Kialiは、Prometheusに入っているistio_requests_totalなどからトポロジー図と健全性を組み立てます。Prometheusにメトリクスが無ければ、図には何も描かれません。Kiali OperatorのCRの記載例では、接続先をexternal_servicesの下に書きます。
apiVersion: kiali.io/v1alpha1
kind: Kiali
metadata:
name: kiali
namespace: istio-system
spec:
external_services:
prometheus:
url: "http://prometheus-operated.monitoring:9090"
grafana:
enabled: true
internal_url: "http://grafana.monitoring:3000"
external_url: "https://grafana.example.com"
URLは自分の環境の値に置き換えます。internal_urlはKialiのサーバーからの問い合わせ先、external_urlはブラウザで開くリンク先です。IstioのKiali連携ページは、サンプルのKialiを外部に公開するならConfigMapのsigning_keyを変えるよう注意しており、本番はKialiプロジェクトの手順での導入を勧めています。
時系列数を抑えるTelemetry APIと記録ルールの設計判断
標準メトリクスには20を超えるラベルが付き、サービスとバージョンとステータスコードの組み合わせごとに時系列ができます。メッシュが大きくなるほど、Prometheusのメモリとクエリ時間が膨らみます。
Telemetry APIでラベルの削除と追加・メトリクスの停止
Telemetryリソースのリファレンスには、ラベルを削る例と、メトリクスの出力を止める例が載っています。次の例は、特定のワークロードでistio_requests_totalからresponse_codeを外すものです。
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
name: remove-response-code
namespace: foo
spec:
selector:
matchLabels:
service.istio.io/canonical-name: bar
metrics:
- providers:
- name: prometheus
overrides:
- match:
metric: REQUEST_COUNT
tagOverrides:
response_code:
operation: REMOVE
tagOverridesにvalue: "request.host"のような式を書けばラベルを足せ、metric: ALL_METRICSとmode: SERVERにdisabled: trueを付けると受信側のメトリクスをまとめて止められます。利用者IDやリクエストパスのように値が際限なく増える項目は、ラベルに入れないでください。カーディナリティの考え方はメトリクス監視とは|4種のメトリック型・収集方式・アラート閾値の設計と導入判断を実装目線で解説でも扱っています。
記録ルールとフェデレーションで本番のPrometheusを軽くする
Observability Best Practicesは、本番規模の監視には階層フェデレーションと記録ルールの組み合わせを勧めています。メッシュ側のPrometheusでPod単位の差を集約した系列を作り、本番のPrometheusはその集約済みの系列だけを取りに行く構成です。
groups:
- name: "istio.recording-rules"
interval: 5s
rules:
- record: "workload:istio_requests_total"
expr: |
sum without(instance, kubernetes_namespace, kubernetes_pod_name) (istio_requests_total)
- record: "workload:istio_request_duration_milliseconds_bucket"
expr: |
sum without(instance, kubernetes_namespace, kubernetes_pod_name) (istio_request_duration_milliseconds_bucket)
上は公式の14本のうち2本の抜粋です。本番側は/federateからworkload:で始まる系列を取り込み、metric_relabel_configsで接頭辞を外すので、既存のダッシュボードをそのまま使えます。
注意したいのはsum withoutで外すラベル名です。公式の記録ルールはkubernetes_namespaceとkubernetes_pod_nameを外しますが、同じページはクイックスタートのPrometheusが付けるラベルをinstance、pod、namespaceと説明しています。実際のラベル名にそろえないと、Pod単位の系列が集約されずに残ります。
アンビエント方式はztunnelがTCP分、waypointがL7分を出す
サイドカーを使わないアンビエント方式では、メトリクスを出す場所が変わります。Ambient data planeのページによると、ノードごとのztunnelが出すのは標準メトリクスのうちTCPの系列です。istio_requests_totalのようなHTTPの系列は出ません。
Use Layer 7 featuresのページは、waypointプロキシを置くとIstioのトラフィックメトリクス一式が出ると説明しています。エラー率やレイテンシを見たいサービスには、waypointを置く前提で設計してください。
アドオンのまま使う条件と保持期間・監視要件で本番の監視基盤へ移す条件
アドオンのPrometheusで済むのは、検証環境と、直近数時間の様子が見えれば足りる小さなクラスタです。保持期間が6時間のため、障害の振り返りや容量計画には使えません。
本番の監視基盤へ移すのは、過去の障害を後から調べる、複数のクラスタをまとめて見る、Istio以外のメトリクスと同じ画面で見る、アラートを当番体制に流す、のどれかが必要な場合です。規模が大きければ記録ルールとフェデレーションを組み合わせます。
収集の設定やダッシュボードは、Istioの更新やサービスの追加に合わせて手直しが続きます。監視の運用まで含めて任せたい場合は、保守運用 / 内製化支援のように、運用の引き受けから社内チームへの引き継ぎまでを相談できる窓口もあります。
Istio Prometheusの設定と運用で挙がるよくある質問
IstioのメトリクスをPrometheusで集め始めたときに出やすい疑問に、公式ドキュメントの記述をもとに答えます。
istio_requests_totalがPrometheusに表示されないのはなぜですか?
カウンターは通信が発生するまで現れないため、まずリクエストを流します。次にサイドカーのlocalhost:15000/stats/prometheusを見て、値があればPrometheusの収集ジョブ(アノテーション、PodMonitorのラベル選択、ポート名)を調べます。
アプリが出す独自のメトリクスも同じPrometheusで集められますか?
同じPrometheusでの収集が可能です。既定のメトリクスマージでは、アプリのメトリクスも:15020/stats/prometheusから一緒に公開されます。マージを止めて個別に集めるなら、STRICTの環境ではPrometheus側に証明書の設定が要ります。
Kialiのトポロジー図に一部のサービスが表示されないのはなぜですか?
KialiはPrometheusのメトリクスから図を描くため、選んだ時間範囲に通信の無いサービスは線が出ません。Kialiが参照するPrometheusのURLが、メトリクスを集めているものと同じかも確かめてください。アンビエント方式でwaypointの無いサービスは、HTTPのメトリクスが出ない点にも注意します。
カナリアリリースの新旧バージョンを分けて比べられますか?
比べられます。destination_versionやdestination_canonical_revisionのラベルで分けて、エラー率とP95を並べます。Podのversionラベルが正しく付いていないと値がunknownになるため、Deploymentのラベルを先に確かめてください。重み付けの設定はIstio VirtualServiceの書き方:DestinationRuleとカナリア・リトライのYAML例を参照してください。
Istioのバージョンを上げるとダッシュボードや設定の変更が要りますか?
アドオンとダッシュボードは版ごとに用意されているため、release-1.31のようなURLは更新時に書き換えます。Istioのサポート表を見ると、2026年10月時点のドキュメントは1.31系(1.31.2)が対象です。版ごとの差分はIstioの最新バージョンは1.31|1.28〜1.31の新機能・サポート期限とアップグレード手順にまとめています。
関連記事
- Istioとは?サービスメッシュの仕組みとサイドカー/アンビエント方式・導入判断を解説:Istio全体の仕組みと導入判断
- Prometheusで監視を構築する手順|exporter設計・PromQL・保持期間の見積り:Prometheus本体の構築と保持期間
- Kubernetes監視・モニタリングの設計|メトリクス・ログ・アラート閾値の実装判断:クラスタ全体の監視設計
- Istio Gatewayの設定方法:Ingress GatewayのYAML・TLS終端・Gateway API対応:外部からの入口の設定
- Istio AuthorizationPolicyの書き方:ALLOW・DENYの評価順とmTLS前提のYAML例:サービス間認可とmTLS
- サービスメッシュとは?サイドカー方式の仕組みとAPIゲートウェイとの違い・導入判断を解説:サービスメッシュの位置づけ
- Linkerdとは?軽量なRust製サービスメッシュの仕組みとIstioとの選び分けを解説:より軽量なメッシュとの比較