Istioメトリクス
対応バージョン: Istio 1.31 最終更新: September 11, 2026
検証範囲: 演習設定は公式資料とオフライン検証器で確認し、クラスターはデプロイしていません。名前空間、ID、ストレージ、バックエンド、負荷の前提は各例で示し、対象環境で検証する必要があります。
Istioプロキシは観測通信のメトリクスを生成します。サイドカー/EnvoyのHTTP/TCPメトリクスと、PrometheusまたはOpenTelemetry Collectorによる収集を扱います。Ambient ztunnelのL4メトリクスは異なり、HTTPにはwaypointが必要です。
目次
- メトリクス概要
- Istio標準メトリクス
- サーキットブレーカーメトリクス
- 耐障害性メトリクス
- OpenTelemetry統合
- Prometheus統合
- Telemetry APIによるカスタマイズ
- 実用メトリクスクエリ
- メトリクス最適化
- トラブルシューティング
メトリクス概要
ゴールデンシグナル
プロキシテレメトリーとノード/コンテナエクスポーターを組み合わせて測定します。
- レイテンシー: 要求処理時間
- トラフィック: システムスループット(RPS、帯域)
- エラー: 失敗率とエラー種別
- 飽和: キュー/接続の圧力とKubernetesエクスポーターのCPU/メモリ
メトリクス収集アーキテクチャ
EnvoyがPrometheusメトリクスを公開 → Prometheusが直接、またはOpenTelemetry CollectorのPrometheus receiverがスクレイプ → 設定済みメトリクスbackend → Grafana/Kiali。Istio OpenTelemetry拡張providerはトレースを設定し、OTLPメトリクス送信器ではありません。
Istio標準メトリクス
HTTP/gRPCメトリクス
Envoyは認識したHTTP/gRPC通信で生成します。報告プロキシごとに出るため、問いに合うreporterを1つ選びます。destination報告はホップの重複観測を避け、宛先に届かなかった上流失敗にはsource報告が必要です。サービス名は名前空間(必要ならクラスターも)とまとめます。
istio_requests_total
型: Counter 説明: 処理した総要求数
istio_requests_total{
reporter="destination", # Peer security policy populated at destination
source_workload="productpage-v1",
source_workload_namespace="default",
source_principal="spiffe://cluster.local/ns/default/sa/bookinfo-productpage",
source_app="productpage",
source_version="v1",
source_canonical_service="productpage",
source_canonical_revision="v1",
destination_workload="reviews-v1",
destination_workload_namespace="default",
destination_principal="spiffe://cluster.local/ns/default/sa/bookinfo-reviews",
destination_app="reviews",
destination_version="v1",
destination_service="reviews.default.svc.cluster.local",
destination_service_name="reviews",
destination_service_namespace="default",
destination_canonical_service="reviews",
destination_canonical_revision="v1",
request_protocol="http",
response_code="200",
response_flags="-",
connection_security_policy="mutual_tls",
grpc_response_status="",
destination_cluster="",
source_cluster=""
}主なラベル:
response_code: HTTP状態コード(200、404、500など)response_flags: Envoy応答フラグUH: 正常な上流なしUF: 上流接続失敗UR: 上流リモートリセット。UT: 上流要求タイムアウトDC: 下流接続終了LR: ローカルリセットURX: 上流再試行上限超過(またはTCP最大接続試行数)
connection_security_policy: mTLS状態(mutual_tls、none。source報告はunknownの場合あり)
istio_request_duration_milliseconds
型: Histogram 説明: 要求処理時間(ミリ秒)
istio_request_duration_milliseconds_bucket{le="10"} # 10ms or less
istio_request_duration_milliseconds_bucket{le="50"} # 50ms or less
istio_request_duration_milliseconds_bucket{le="100"} # 100ms or less
istio_request_duration_milliseconds_bucket{le="500"} # 500ms or less
istio_request_duration_milliseconds_sum # Total time
istio_request_duration_milliseconds_count # Total request countistio_request_bytes
型: Histogram 説明: 要求本文サイズ(バイト)
istio_request_bytes_bucket # Inspect actual le bounds
istio_request_bytes_bucket{le="+Inf"} # All body sizes
istio_request_bytes_sum
istio_request_bytes_countistio_response_bytes
型: Histogram 説明: 応答本文サイズ(バイト)
istio_response_bytes_bucket
istio_response_bytes_bucket{le="+Inf"}
istio_response_bytes_sum
istio_response_bytes_countTCPメトリクス
istio_tcp_connections_opened_total
型: Counter 説明: 開いたTCP接続数
istio_tcp_connections_opened_total{
reporter="source",
source_workload="mongodb-v1",
destination_service="mongodb.default.svc.cluster.local"
}istio_tcp_connections_closed_total
型: Counter 説明: 閉じたTCP接続数
istio_tcp_sent_bytes_total
型: Counter 説明: 送信バイト数
istio_tcp_received_bytes_total
型: Counter 説明: 受信バイト数
サーキットブレーカーメトリクス
スクレイプ前にproxyStatsMatcherで必要Envoy統計を有効にします。デフォルトIstio bootstrapはcluster_nameを抽出しますが、カスタムではラベルが変わり得ます。ブレーカーの_openは0/1ゲージで、イベントカウンターではありません。一部カウンターは通信後だけ現れます。
主なサーキットブレーカーメトリクス
1. 上流接続プール超過
# Requests rejected due to connection pool overflow
envoy_cluster_upstream_cx_overflow{
cluster_name="outbound|80||httpbin.default.svc.cluster.local"
}意味: maxConnections上限超過
2. サーキットブレーカー開状態(ゲージ)
# Gauge: 1 at capacity, 0 below limit
envoy_cluster_circuit_breakers_default_rq_open{
cluster_name="outbound|80||httpbin.default.svc.cluster.local"
}3. 保留要求の超過
# Pending request count exceeded
envoy_cluster_upstream_rq_pending_overflow{
cluster_name="outbound|80||httpbin.default.svc.cluster.local"
}意味: 保留/アクティブ要求のブレーカー拒否。rq_pending_open、rq_open、生成しきい値を調べ、キュー圧力とアクティブ要求上限を区別します。
4. 再試行予算の枯渇
# Retry budget exhausted
envoy_cluster_upstream_rq_retry_overflow{
cluster_name="outbound|80||httpbin.default.svc.cluster.local"
}5. 応答フラグによるブレーカー検出
# Requests rejected by circuit breaker (response_flags="UO")
sum(rate(istio_requests_total{reporter="source",
response_flags=~".*UO.*",
destination_service="httpbin.default.svc.cluster.local"
}[5m]))応答フラグ詳細:
UO: 上流超過(ブレーカー開)URX: 上流再試行上限超過(またはTCP最大接続試行数)UF: 上流接続失敗UH: 正常な上流なし
ブレーカー監視ダッシュボードクエリ
# Fraction of observed samples at capacity over five minutes (%).
100 * avg_over_time(envoy_cluster_circuit_breakers_default_rq_open[5m])
# Active connections and pending requests (per proxy/cluster).
envoy_cluster_upstream_cx_active
envoy_cluster_upstream_rq_pending_active
# Rejected request events over five minutes.
sum by (namespace, pod, cluster_name) (
increase(envoy_cluster_upstream_rq_pending_overflow[5m])
)標準のcircuit_breakers_default_cx_maxやrq_pending_maxゲージはありません。生成クラスター設定から上限を読みます。任意のremaining_cx/remaining_pendingにはEnvoy track_remainingが必要で、メトリクス名を含めるだけでは有効になりません。使用率分母は一致する既知の設定上限から得る必要があります。
ブレーカーのアラートルール
groups:
- name: istio_circuit_breaker
rules:
- alert: CircuitBreakerAtCapacity
expr: envoy_cluster_circuit_breakers_default_rq_open == 1
for: 1m
labels:
severity: warning
annotations:
summary: Request breaker remains at capacity for {{ $labels.cluster_name }}
- alert: ConnectionPoolOverflow
expr: rate(envoy_cluster_upstream_cx_overflow[5m]) > 0
for: 2m
labels:
severity: warning
annotations:
summary: Connection limit exceeded for {{ $labels.cluster_name }}
- alert: PendingRequestsOverflow
expr: rate(envoy_cluster_upstream_rq_pending_overflow[5m]) > 0
for: 2m
labels:
severity: warning
annotations:
summary: Request circuit-breaking rejection for {{ $labels.cluster_name }}耐障害性メトリクス
外れ値検出メトリクス
1. 除外ホスト
# Number of hosts ejected by outlier detection
envoy_cluster_outlier_detection_ejections_active{
cluster_name="outbound|80||httpbin.default.svc.cluster.local"
}2. 除外イベント
# Ejection event rate
rate(envoy_cluster_outlier_detection_ejections_enforced_total[5m])除外タイプ別:
# Consecutive 5xx errors
envoy_cluster_outlier_detection_ejections_enforced_consecutive_5xx
# Success rate based
envoy_cluster_outlier_detection_ejections_enforced_success_rate
# Failure percentage based
envoy_cluster_outlier_detection_ejections_enforced_failure_percentage検出と適用は異なります。外れ値を検出しても適用確率や最大除外率で除外されず提供し続ける場合があります。一部EnvoyアルゴリズムはIstio DestinationRuleから公開されません。系列がないことは設定アルゴリズムの健全性の証拠ではありません。
再試行メトリクス
# Number of retried requests
rate(envoy_cluster_upstream_rq_retry[5m])
# Retry success rate
rate(envoy_cluster_upstream_rq_retry_success[5m])
/
rate(envoy_cluster_upstream_rq_retry[5m])
# Retry budget exhausted
rate(envoy_cluster_upstream_rq_retry_overflow[5m])タイムアウトメトリクス
# Requests that timed out
sum(rate(istio_requests_total{reporter="source",
response_flags=~".*UT.*"
}[5m])) by (destination_service)
# Timeout rate
sum(rate(istio_requests_total{reporter="source",response_flags=~".*UT.*"}[5m]))
/
sum(rate(istio_requests_total{reporter="source"}[5m]))
* 100OpenTelemetry統合
Istioメトリクス用Prometheus receiver
Istioのopentelemetry拡張providerはトレースを出力します。標準メッシュメトリクスにはPrometheus providerを維持し、OpenTelemetry CollectorのPrometheus receiverで公開エンドポイントをスクレイプします。Collectorはメトリクス対応backendへOTLPで送れます。Tempoはトレースbackendで、メトリクス宛先ではありません。
例はCollector Contrib 0.160.0とPrometheusエクスポーターを使い、確認可能なデモ経路を作ります。先にobservabilityを作成します。同一スクレイプ設定のレプリカは全対象を重複収集するため1レプリカです。本番拡張には対象割り当て/シャーディングが必要です。ServiceAccountはPod検出jobに必要なPod読み取りだけできます。平文プロキシメトリクス15090とistiod 15014へのアクセスを設定します。アプリメトリクスとambient ztunnelは収集しません。
apiVersion: v1
kind: ServiceAccount
metadata:
name: otel-metrics
namespace: observability
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: otel-metrics-pod-reader
rules:
- apiGroups:
- ''
resources:
- pods
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: otel-metrics-pod-reader
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: otel-metrics-pod-reader
subjects:
- kind: ServiceAccount
name: otel-metrics
namespace: observability
---
apiVersion: v1
kind: ConfigMap
metadata:
name: otel-metrics-config
namespace: observability
data:
config.yaml: |
receivers:
prometheus:
config:
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: envoy-stats
metrics_path: /stats/prometheus
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels:
- __meta_kubernetes_pod_phase
action: keep
regex: Running
- source_labels:
- __meta_kubernetes_pod_container_name
- __meta_kubernetes_pod_container_port_name
action: keep
regex: istio-proxy;.*-envoy-prom
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_pod_name
target_label: pod
- job_name: istiod
metrics_path: /metrics
kubernetes_sd_configs:
- role: pod
namespaces:
names:
- istio-system
relabel_configs:
- source_labels:
- __meta_kubernetes_pod_label_app
- __meta_kubernetes_pod_container_port_name
action: keep
regex: istiod;http-monitoring
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_pod_name
target_label: pod
processors:
memory_limiter:
check_interval: 1s
limit_mib: 512
batch:
timeout: 10s
send_batch_size: 1024
exporters:
prometheus:
endpoint: 0.0.0.0:8889
const_labels:
environment: production
debug:
verbosity: basic
service:
pipelines:
metrics:
receivers:
- prometheus
processors:
- memory_limiter
- batch
exporters:
- prometheus
- debug
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: otel-metrics
namespace: observability
spec:
replicas: 1
selector:
matchLabels:
app: otel-metrics
template:
metadata:
labels:
app: otel-metrics
annotations:
sidecar.istio.io/inject: 'false'
spec:
serviceAccountName: otel-metrics
containers:
- name: otel-collector
image: otel/opentelemetry-collector-contrib:0.160.0
args:
- --config=/etc/otel/config.yaml
ports:
- containerPort: 8889
name: prometheus
volumeMounts:
- name: config
mountPath: /etc/otel
readOnly: true
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi
volumes:
- name: config
configMap:
name: otel-metrics-config
---
apiVersion: v1
kind: Service
metadata:
name: otel-metrics
namespace: observability
labels:
app: otel-metrics
spec:
selector:
app: otel-metrics
ports:
- name: prometheus
port: 8889
targetPort: prometheus廃止loggingエクスポーターはdebugに置換されています。検証後は診断出力を除去します。既存名に第2のistio_が付かないよう、namespace: istioは加えません。Kialiダッシュボード再利用前に出力ラベル/名前を確認します。Prometheus Operatorではラベル付きServiceを選びます。
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: otel-metrics
namespace: observability
spec:
selector:
matchLabels:
app: otel-metrics
endpoints:
- port: prometheus
interval: 15s
path: /metrics
honorLabels: truePrometheusはこのServiceMonitorと名前空間を選ぶ必要があります。honorLabelsは元のjob/instanceを保持するため、Collectorは信頼するソースでなければなりません。同じ系列にはこの経路か下の直接スクレイプのどちらかを使い、両方は使いません。このServiceMonitorはPrometheusをインストールしません。
収集の確認
kubectl logs -n observability deployment/otel-metrics
# Keep this running in one terminal.
kubectl port-forward -n observability svc/otel-metrics 8889:8889# In a second terminal, after generating test mesh traffic:
curl -fsS http://localhost:8889/metrics | rg '^istio_'トレースOTLP receiver/exporterはトレース章で別設定します。プロキシデバッグログはメトリクス配信を証明しません。
Prometheus統合
Prometheus設定
Pod list/watch権限を持つ導入済みPrometheusで使います。ConfigMap単体はデプロイ/再読み込みしません。Pod検出jobはIPv6も含むKubernetes検出アドレスを保持し、Envoyメトリクスかistiod監視ポートを正確に選びます。サイドカーとGatewayを含むため別Gateway jobは重複します。削除されたMixer istio-telemetry Serviceは対象ではありません。
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
namespace: istio-system
data:
prometheus.yml: |
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: envoy-stats
metrics_path: /stats/prometheus
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels:
- __meta_kubernetes_pod_phase
action: keep
regex: Running
- source_labels:
- __meta_kubernetes_pod_container_name
- __meta_kubernetes_pod_container_port_name
action: keep
regex: istio-proxy;.*-envoy-prom
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_pod_name
target_label: pod
- job_name: istiod
metrics_path: /metrics
kubernetes_sd_configs:
- role: pod
namespaces:
names:
- istio-system
relabel_configs:
- source_labels:
- __meta_kubernetes_pod_label_app
- __meta_kubernetes_pod_container_port_name
action: keep
regex: istiod;http-monitoring
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_pod_name
target_label: podプロキシ専用スクレイプは15090の/stats/prometheusです。デフォルト統合エージェント/アプリメトリクスはprometheus.ioアノテーションで15020の/stats/prometheusを使い、別の重複しないjobが必要です。エージェント証明書メトリクスにもそのエンドポイントが必要です。アプリがSTRICT mTLSでもこれらは平文なので、ネットワーク公開を制限します。別アプリエンドポイントのスクレイプは独自認証ポリシーに従います。
Prometheus Operatorによる代替
手動jobの代わりに使います。Prometheusがラベル/名前空間を選ぶことを確認します。namespaceSelector.any: trueはPodMonitorにアプリ名前空間を調べさせ、port: http-envoy-promは実メトリクスコンテナポートを選びます。カスタムGatewayならポート名を合わせます。ServiceMonitorはDeploymentラベルでなくServiceを選びます。
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: istio-component-monitor
namespace: istio-system
spec:
selector:
matchLabels:
app: istiod
endpoints:
- port: http-monitoring
interval: 15s
path: /metrics
---
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: envoy-stats-monitor
namespace: istio-system
spec:
namespaceSelector:
any: true
selector:
matchExpressions:
- key: istio-prometheus-ignore
operator: DoesNotExist
podMetricsEndpoints:
- port: http-envoy-prom
path: /stats/prometheus
interval: 15s
relabelings:
- sourceLabels:
- __meta_kubernetes_pod_container_name
action: keep
regex: istio-proxyPrometheusクエリ最適化
# Recording Rules to pre-compute frequently used queries
groups:
- name: istio_recording_rules
interval: 30s
rules:
# Request rate by service
- record: istio:service:request_rate:5m
expr: |
sum(rate(istio_requests_total{reporter="destination"}[5m])) by (destination_service_name, destination_service_namespace)
# Error rate by service
- record: istio:service:error_rate:5m
expr: |
sum(rate(istio_requests_total{reporter="destination",response_code=~"5.."}[5m])) by (destination_service_name, destination_service_namespace)
/
sum(rate(istio_requests_total{reporter="destination"}[5m])) by (destination_service_name, destination_service_namespace)
# P95 latency by service
- record: istio:service:latency_p95:5m
expr: |
histogram_quantile(0.95,
sum(rate(istio_request_duration_milliseconds_bucket{reporter="destination"}[5m]))
by (destination_service_name, destination_service_namespace, le)
)
# Circuit breaker state gauge
- record: istio:circuit_breaker:at_capacity
expr: |
envoy_cluster_circuit_breakers_default_rq_openTelemetry APIによるカスタマイズ
メトリクスのカスタマイズ
1. 特定メトリクスだけ有効化
上書きは順番に評価します。最初にALL_METRICSを無効にし、必要なHTTPメトリクス2つを再有効化します。modeはmatch内です。独立例を全部適用せず、選択範囲ごとに1 Telemetryへ関連設定をマージします。
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
name: custom-metrics
namespace: istio-system
spec:
metrics:
- providers:
- name: prometheus
overrides:
- match:
metric: ALL_METRICS
mode: CLIENT_AND_SERVER
disabled: true
- match:
metric: REQUEST_COUNT
mode: CLIENT_AND_SERVER
disabled: false
- match:
metric: REQUEST_DURATION
mode: CLIENT_AND_SERVER
disabled: false2. カスタムラベルの追加
HTTPメトリクスで値を限定したCEL式を使います。request ID、任意User-Agent、タイミングヘッダーは無制限ラベルを生みます。x-envoy-upstream-service-timeは時間で、上流クラスターIDではありません。CELは例のシェル型| split()構文を使いません。
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
name: custom-tags
namespace: prod
spec:
metrics:
- providers:
- name: prometheus
overrides:
- match:
metric: REQUEST_COUNT
tagOverrides:
api_version:
value: 'request.url_path.startsWith("/api/v1/") ? "v1" : (request.url_path.startsWith("/api/v2/")
? "v2" : "other")'
request_method:
value: 'request.method in ["GET", "POST", "PUT", "DELETE"] ? request.method
: "OTHER"'3. 名前空間固有メトリクス設定
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
name: namespace-metrics
namespace: production
spec:
metrics:
- providers:
- name: prometheus
overrides:
- match:
metric: REQUEST_COUNT
mode: CLIENT_AND_SERVER
tagOverrides:
environment:
value: '"production"'4. メトリクス無効化による性能改善
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
name: disable-tcp-metrics
namespace: istio-system
spec:
metrics:
- providers:
- name: prometheus
overrides:
# Completely disable TCP metrics
- match:
metric: TCP_OPENED_CONNECTIONS
disabled: true
- match:
metric: TCP_CLOSED_CONNECTIONS
disabled: true
- match:
metric: TCP_SENT_BYTES
disabled: true
- match:
metric: TCP_RECEIVED_BYTES
disabled: true実用メトリクスクエリ
HTTP状態ベースのエラー比率は全gRPC失敗を捉えません。gRPCではgrpc_response_statusとアプリの失敗定義を調べます。HTTP 200でも非ゼロgRPC状態を運べます。
ゴールデンシグナルダッシュボード
1. レイテンシー
# P50 latency
histogram_quantile(0.50,
sum(rate(istio_request_duration_milliseconds_bucket{reporter="destination",
destination_service_name="reviews", destination_service_namespace="default"
}[5m])) by (le)
)
# P95 latency
histogram_quantile(0.95,
sum(rate(istio_request_duration_milliseconds_bucket{reporter="destination",
destination_service_name="reviews", destination_service_namespace="default"
}[5m])) by (le)
)
# P99 latency
histogram_quantile(0.99,
sum(rate(istio_request_duration_milliseconds_bucket{reporter="destination",
destination_service_name="reviews", destination_service_namespace="default"
}[5m])) by (le)
)
# Average latency by service
sum(rate(istio_request_duration_milliseconds_sum{reporter="destination"}[5m])) by (destination_service_name, destination_service_namespace)
/
sum(rate(istio_request_duration_milliseconds_count{reporter="destination"}[5m])) by (destination_service_name, destination_service_namespace)2. トラフィック
# Request rate by service (RPS)
sum(rate(istio_requests_total{reporter="destination"}[1m])) by (destination_service_name, destination_service_namespace)
# Total request rate
sum(rate(istio_requests_total{reporter="destination"}[1m]))
# Inbound traffic by service (bytes/sec)
sum(rate(istio_request_bytes_sum{reporter="destination"}[1m])) by (destination_service_name, destination_service_namespace)
# Outbound traffic by service (bytes/sec)
sum(rate(istio_response_bytes_sum{reporter="destination"}[1m])) by (destination_service_name, destination_service_namespace)
# Request distribution by protocol (not HTTP method)
sum(rate(istio_requests_total{reporter="destination"}[5m])) by (request_protocol, destination_service_name, destination_service_namespace)3. エラー
# Error rate (5xx errors)
sum(rate(istio_requests_total{response_code=~"5..", reporter="destination"}[5m])) by (destination_service_name, destination_service_namespace)
/
sum(rate(istio_requests_total{reporter="destination"}[5m])) by (destination_service_name, destination_service_namespace)
* 100
# Separate 4xx vs 5xx
sum(rate(istio_requests_total{response_code=~"4..", reporter="destination"}[5m])) by (destination_service_name, destination_service_namespace)
sum(rate(istio_requests_total{response_code=~"5..", reporter="destination"}[5m])) by (destination_service_name, destination_service_namespace)
# Track specific error codes
sum(rate(istio_requests_total{response_code="503", reporter="destination"}[5m])) by (destination_service_name, destination_service_namespace)
# Analyze error types via response flags
sum(rate(istio_requests_total{response_flags!~"-", reporter="destination"}[5m])) by (response_flags, destination_service_name, destination_service_namespace)4. 飽和
# Connection count and breaker state (not a utilization percentage).
envoy_cluster_upstream_cx_active
envoy_cluster_circuit_breakers_default_cx_open
# Active and pending requests.
envoy_cluster_upstream_rq_active
envoy_cluster_upstream_rq_pending_active
# Allocated proxy memory in bytes; compare with the container memory limit separately.
envoy_server_memory_allocatedmTLS監視
# mTLS usage rate
sum(rate(istio_requests_total{
connection_security_policy="mutual_tls",
reporter="destination"
}[5m]))
/
sum(rate(istio_requests_total{reporter="destination"}[5m]))
* 100
# Detect non-mTLS traffic
sum(rate(istio_requests_total{
connection_security_policy="none",
reporter="destination"
}[5m])) by (source_workload, destination_workload)
# HTTP 401 observed on authenticated mesh traffic; this is not a TLS handshake failure.
sum by (destination_service_name, destination_service_namespace) (
rate(istio_requests_total{reporter="destination",response_code="401",connection_security_policy="mutual_tls"}[5m])
)サービスメッシュ健全性ダッシュボード
# Scrape health, not a complete control-plane health check.
up{job="istiod"}
# Istiod xDS build/send error rate, by type.
sum by (type) (rate(pilot_xds_pushes{type=~".*(builderr|senderr)"}[5m]))
# Configuration convergence time, seconds (not push count).
histogram_quantile(0.95,
sum by (le) (rate(pilot_proxy_convergence_time_bucket[5m]))
)
# Recently started Envoy process; uptime is elapsed seconds, not a timestamp.
envoy_server_uptime < 300実プロキシ版はistioctl version、同期/NACK診断はistioctl proxy-statusで確認します。プロセスの経過時間は設定鮮度ではなく、Envoy数値版ゲージは版ラベル分布ではありません。mTLS失敗はmTLSガイドのTLS検証カウンターと証明書を調べます。
メトリクス最適化
高カーディナリティ問題の解決
1. 不要ラベルの除去
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
name: reduce-cardinality
namespace: istio-system
spec:
metrics:
- providers:
- name: prometheus
overrides:
- match:
metric: ALL_METRICS
tagOverrides:
# Remove high cardinality labels
request_id:
operation: REMOVE
user_agent:
operation: REMOVE2. ラベル値の正規化
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
name: normalize-labels
namespace: prod
spec:
metrics:
- providers:
- name: prometheus
overrides:
- match:
metric: REQUEST_COUNT
tagOverrides:
# Normalize HTTP methods (GET, POST, PUT, DELETE, OTHER)
request_method:
value: 'request.method in ["GET", "POST", "PUT", "DELETE"] ? request.method : "OTHER"'Envoy統計の選択
proxyStatsMatcherは作成するEnvoy統計を選び、要求をサンプリングしません。必要な群だけを含め、必要な既存一致を保持し、bootstrap変更後は選択プロキシをロールアウトします。例は前のクエリに必要な統計を有効にします。
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
meshConfig:
defaultConfig:
proxyStatsMatcher:
inclusionRegexps:
- ".*upstream_rq_timeout.*"
- ".*upstream_cx_connect_timeout.*"
- ".*upstream_cx_connect_fail.*"
- ".*upstream_rq_pending_overflow.*"
- ".*circuit_breakers.*"
- ".*outlier_detection.*"
- ".*upstream_cx_(active|overflow).*"
- ".*upstream_rq_(active|retry|pending).*"Prometheus性能調整
デフォルトのスクレイプ間隔は1分です。15s/30sは意図的選択です。既存jobへマージする設定断片です。metric_relabel_configsは各job内で、ラベルだけでなくサンプルを破棄します。選択backendのremote-writeエンドポイント、認証/TLS、永続化を設定する必要があります。
global:
scrape_interval: 30s
evaluation_interval: 30s
remote_write:
- url: http://victoria-metrics:8428/api/v1/write
queue_config:
capacity: 10000
max_shards: 5
min_shards: 1
max_samples_per_send: 5000
scrape_configs:
- job_name: envoy-stats
metrics_path: /stats/prometheus
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels:
- __meta_kubernetes_pod_phase
action: keep
regex: Running
- source_labels:
- __meta_kubernetes_pod_container_name
- __meta_kubernetes_pod_container_port_name
action: keep
regex: istio-proxy;.*-envoy-prom
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_pod_name
target_label: pod
metric_relabel_configs:
- source_labels:
- __name__
regex: istio_tcp_.*
action: dropトラブルシューティング
exec/curl例はcurl入りプロキシイメージが必要です。なければkubectl port-forward pod/<pod-name> 15090:15090(エージェントは15020)を使い、別ターミナルで照会します。ここでのTelemetryはEnvoy用です。ambient L7ポリシーにはwaypoint接続、ztunnel L4には別収集を使います。
メトリクスが収集されない場合
1. Envoyメトリクスエンドポイントの確認
# Check Envoy admin port
kubectl exec -it <pod-name> -c istio-proxy -- curl localhost:15000/stats/prometheus | head -20
# Check metrics filter
istioctl proxy-config bootstrap <pod-name> -o json | jq '.bootstrap.statsConfig'2. Prometheusが対象を検出したか確認
# Check Targets page in Prometheus UI
kubectl port-forward -n istio-system svc/prometheus 9090:9090
# In browser: http://localhost:9090/targets3. Telemetry API設定の検証
# Check Telemetry resources
kubectl get telemetry -A
# Check specific Telemetry details
kubectl describe telemetry <name> -n <namespace>
# Check if reflected in Envoy config
istioctl proxy-config listeners <pod-name> -n <namespace> -o jsonメトリクスラベルがない場合
# 1. Check if Envoy generates correct labels
kubectl exec -it <pod-name> -c istio-proxy -- curl localhost:15000/stats/prometheus | grep istio_requests_total | head -1
# 2. Check Prometheus relabeling rules
kubectl get configmap prometheus-config -n istio-system -o yaml
# 3. Check ServiceMonitor/PodMonitor
kubectl get servicemonitor,podmonitor -n istio-systemメトリクスのカーディナリティ急増
別ターミナルでPrometheusをport-forward後、アクティブ系列とTSDB統計を照会します。メトリクス名を数えることは時系列数ではありません。TSDB状態エンドポイントはラベル/値別カーディナリティも報告します。
curl -fsS http://localhost:9090/api/v1/status/tsdb | jq '.data'
curl -fsSG http://localhost:9090/api/v1/query \
--data-urlencode 'query=count(istio_requests_total)' | jq '.data.result'
curl -fsSG http://localhost:9090/api/v1/query \
--data-urlencode 'query=topk(10, count by (__name__) ({__name__=~"istio_.*"}))' | jq '.data.result'ブレーカーメトリクスが見えない場合
# 1. Check Envoy cluster statistics
istioctl proxy-config cluster <pod-name> --fqdn <service-fqdn> -o json | \
jq '.[] | .circuitBreakers'
# 2. Check directly from Envoy admin
kubectl exec -it <pod-name> -c istio-proxy -- \
curl "localhost:15000/clusters" | grep -A 10 "outbound|80||<service>"
# 3. Verify DestinationRule is correctly applied
istioctl analyze -n <namespace>