Service Mesh (ASM) での HTTP 503 エラーは、通常、接続ライフサイクルミスマッチ、構成変更、またはトラフィックインターセプトの問題が原因で発生します。このガイドでは、各シナリオについて、その根本原因、診断シグナル、およびソリューションを説明します。
根本原因の特定
影響を受ける Pod の Envoy アクセスログをチェックして、応答フラグを見つけます。このフラグは、リクエストが失敗した理由を示します。
kubectl logs <pod-name> -c istio-proxy -n <namespace>応答フラグをシナリオに一致させます。
| 応答フラグ | 症状 | シナリオ |
|---|---|---|
UC | 通常のトラフィック下での断続的な 503、構成変更なし | アイドル接続タイムアウトのミスマッチ |
UC | カスタムメトリック変更直後の短時間の 503 スパイク | メトリックカスタマイズ構成の変更 |
| N/A | mTLS 有効化後の永続的な 503、ヘルスチェック失敗 | mTLS によるヘルスチェックの失敗 |
| N/A | 特定のサービスへのすべてのリクエストが 503 を返す | localhost でリッスンしているアプリケーション |
断続的な 503 のシナリオ
メトリックカスタマイズ構成変更後の短時間の 503 スパイク
カスタムメトリック構成を更新した直後に、少数のリクエストが HTTP 503 を返します。
根本原因
メトリックのカスタマイズ機能は、istio.stats 構成を更新する Envoy フィルターを生成します。この更新は、リスナー検出サービス (LDS) を介して配信され、Envoy リスナーを変更します。リスナー構成が変更されると、既存の接続が終了され、これらの接続上の送信中のリクエストには 503 応答が返されます。
503 はアップストリームサーバーによって送信されるものではありません。クライアント側のサイドカープロキシが、アップストリーム接続のリセットに応じてそれを生成します。
デフォルトのリトライポリシーが役立たない理由
デフォルトのサイドカープロキシリトライポリシーは、以下の条件をカバーします。
"retry_policy": {
"retry_on": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
"num_retries": 2,
"retry_host_predicate": [
{
"name": "envoy.retry_host_predicates.previous_hosts"
}
],
"host_selection_retry_max_attempts": "5",
"retriable_status_codes": [
503
]
}| 条件 | トリガー |
|---|---|
connect-failure | 接続失敗 (接続タイムアウト) |
refused-stream | HTTP/2 REFUSED_STREAM エラー |
unavailable | gRPC unavailable ステータス |
cancelled | gRPC cancelled ステータス |
retriable-status-codes | 応答ステータスコードが retriable_status_codes のコード (デフォルトでは 503) と一致する |
アップストリームの切断と接続のリセットをカバーする reset 条件は含まれていません。それがこのシナリオがトリガーする条件です。
ソリューション: リトライポリシーへの reset の追加
影響を受けるサービスに対して、VirtualService の retryOn フィールドに reset (およびオプションで 503) を追加します。
次の例は、Ratings サービスのリトライを構成します。
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: ratings-route
spec:
hosts:
- ratings.prod.svc.cluster.local
http:
- route:
- destination:
host: ratings.prod.svc.cluster.local
subset: v1
retries:
attempts: 2
retryOn: connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes,reset,503ratings.prod.svc.cluster.local とサブセット v1 を、ご利用のターゲットサービスのホストとサブセットに置き換えます。
Envoy リトライ条件の完全なリストについては、以下をご参照ください。
Router - x-envoy-retry-on (HTTP/2 および HTTP/3 リトライ条件)
x-envoy-retry-grpc-on (gRPC 固有のリトライ条件)
アイドル接続タイムアウトのミスマッチによる断続的な 503
HTTP 503 エラーは、構成変更なしで断続的に発生し、トラフィックが増加すると頻繁に増加します。Envoy アクセスログには、応答フラグ UC (アップストリーム接続の終了) が表示されます。これは通常、インバウンドサイドカープロキシトラフィックに影響します。
根本原因
サイドカープロキシとアプリケーションは、異なるアイドル接続タイムアウト値を持っています。サイドカープロキシのデフォルトのアイドル接続タイムアウトは 1 時間です。
プロキシタイムアウトがアプリケーションタイムアウトよりも長い場合:
アプリケーションが最初にアイドル接続を閉じますが、サイドカープロキシは依然として接続がアクティブであると見なします。その接続に新しいリクエストが到着した場合、プロキシはそれを閉じられた接続に転送し、HTTP 503 (response_flags=UC) を返します。

プロキシタイムアウトがアプリケーションタイムアウトよりも短い場合:
プロキシが最初に接続を閉じ、次のリクエストのために新しい接続を作成します。この場合、503 エラーは発生しません。

ソリューション 1: DestinationRule での idleTimeout の設定
DestinationRule で idleTimeout を設定することにより、アイドルタイムアウトを調整します。この設定は、インバウンドおよびアウトバウンドのサイドカープロキシトラフィックの両方に適用されます。クライアントがサイドカープロキシを持たない場合でも機能します。
idleTimeout をアプリケーションのアイドルタイムアウトよりもわずかに短い値に設定します。短すぎる値は、総接続数を増加させます。
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: <your-service-idle-timeout>
spec:
host: <your-service-host>
trafficPolicy:
connectionPool:
tcp:
idleTimeout: 30m<your-service-idle-timeout> と <your-service-host> をご利用のサービス名とホストに置き換えます。ご利用のアプリケーションのアイドルタイムアウトに基づいて 30m を調整します。アプリケーションの値よりもわずかに短く設定してください。
ソリューション 2: VirtualService でのリトライの設定
リトライは新しい接続をトリガーし、古い接続の問題を解決します。「メトリックカスタマイズ構成変更後の短時間の 503 スパイク」と同じリトライ構成に従ってください。
非冪等リクエスト (POST など) のリトライは高リスク操作であり、重複操作を引き起こす可能性があります。これらのリクエストタイプのリトライを有効にする前に、慎重に評価してください。
サイドカーライフサイクルの構成ミスによる Pod 再起動中の断続的な 503
Pod が再起動するたびに、HTTP 503 エラーが短時間発生します。
根本原因
サイドカープロキシコンテナのライフサイクルが構成ミスです。プロキシは、アプリケーションが接続のドレインを完了する前にシャットダウンしたり、アプリケーションが準備完了になる前にトラフィックの受信を開始したりする可能性があります。
ソリューション
ご利用のアプリケーションの起動およびシャットダウンシーケンスに合わせて、サイドカープロキシコンテナのライフサイクルを構成します。詳細については、「サイドカープロキシのライフサイクル」をご参照ください。
永続的な 503 のシナリオ
localhost でリッスンしているアプリケーション
他の Pod から特定のアプリケーションへのすべてのリクエストが HTTP 503 を返します。
根本原因
アプリケーションは、localhost (127.0.0.1)ではなく 0.0.0.0 にバインドされます。サイドカープロキシはトラフィックをアプリケーションのポートに転送しますが、アプリケーションはループバックアドレス以外のアドレスからの接続を拒否します。
ソリューション
サイドカープロキシと他の Pod がそれに到達できるように、アプリケーションを 0.0.0.0 にバインドします。詳細については、「localhost でリッスンしているクラスターアプリケーションを他の Pod に公開する」をご参照ください。
mTLS 有効化後のヘルスチェックの失敗
サイドカーインジェクション後、Pod ヘルスチェック (liveness および readiness プローブ) が継続的に失敗し、HTTP 503 ステータスコードが報告されます。
根本原因
ASM で mutual TLS (mTLS) が有効になっている場合、サイドカープロキシは、kubelet ヘルスチェックリクエストを含む、Pod へのすべての受信トラフィックをインターセプトします。kubelet が Istio 発行の TLS 証明書を欠いているため、mTLS ハンドシェイクを完了できず、すべてのヘルスチェックが失敗します。
ソリューション
kubelet がアプリケーションに直接到達できるように、ヘルスチェックポートをサイドカートラフィックインターセプトから除外します。詳細については、「サイドカーインジェクション後に有効なヘルスチェック情報が表示されないのはなぜですか?」をご参照ください。