コンテナネットワークの障害 (断続的な DNS タイムアウト、TCP リセット、Nginx 499/502/503/504 エラー、レイテンシースパイクなど) は、一時的で再現が困難なため、特定が非常に困難です。Container Service for Kubernetes (ACK) KubeSkoop (旧称 ACK Net Exporter) は、eBPF を使用して各ノードから Pod ごとのネットワークメトリックを直接収集するオープンソースのネットワーク監視およびトラブルシューティングスイートであり、手動のパケットキャプチャや推測なしに根本原因を特定できます。
このトピックでは、マネージド ACK クラスターに KubeSkoop をインストールし、監視を設定し、Pod ごとのメトリックを使用して 4 つの一般的なネットワーク障害タイプを診断する方法について説明します。
仕組み
KubeSkoop は DaemonSet として実行され、すべてのノードに 1 つのエージェントを配置します。各エージェントは eBPF を使用してノードから低レベルのネットワークデータを収集し、Pod ごとに集約します。エージェントは、ポート 9102 の HTTP エンドポイントを介して Prometheus メトリックと異常イベントを公開します。
KubeSkoop は以下をサポートしています。
詳細なネットワーク監視
接続診断
パケットキャプチャ
レイテンシープロビング
次の図は、KubeSkoop のコアアーキテクチャを示しています。
前提条件
開始する前に、以下があることを確認してください。
マネージド ACK クラスター
ACK コンソールへのアクセス
ARMS コンソールへのアクセス (Prometheus ダッシュボードに必要)
ACK KubeSkoop のインストールと設定
ACK KubeSkoop アドオンのインストール
ACK コンソールにログインします。左側のナビゲーションウィンドウで、[クラスター]をクリックします。
[クラスター] ページで、クラスターの名前をクリックします。 左側のナビゲーションウィンドウで、[アドオン] をクリックします。
[アドオン]ページで[ACK KubeSkoop]を検索し、アドオンを見つけて[インストール]をクリックします。
[ACK KubeSkoop コンポーネントのインストール] ページで、[確認] をクリックします。
KubeSkoop アドオンの設定
KubeSkoop は、ack-kubeskoop 名前空間の kubeskoop-config という名前の ConfigMap を介して設定されます。変更はすぐに有効になり、再起動は不要です。
オプション 1: kubectl を使用して編集
kubectl edit cm kubeskoop-config -n ack-kubeskoopオプション 2: コンソールを使用して編集
ACK コンソールにログインします。左側のナビゲーションウィンドウで、[クラスター] をクリックします。
クラスターの名前をクリックします。左側のナビゲーションウィンドウで、[設定] > [ConfigMap] を選択します。
「ConfigMap」ページで、[名前空間] を [ack-kubeskoop] に設定し、「kubeskoop-config」を検索して、[操作] 列の [編集] をクリックします。
[編集] パネルで、パラメーターを更新し、[OK] をクリックします。
次の表に、サポートされているパラメーターを示します。
| パラメーター | 説明 | デフォルト値 |
|---|---|---|
debugmode | デバッグモードを有効にします。true に設定すると、DEBUG レベルのログ、デバッグインターフェイス、および Go pprof と gops 診断ツールが提供されます。 | false |
port | メトリック HTTP エンドポイントのポート。 | 9102 |
enableController | コントローラーコンポーネントを有効にします。これは Kubernetes API と対話して監視および管理タスクを実行します。 | true |
controllerAddr | KubeSkoop コントローラーコンポーネントのアドレス。 | dns:kubeskoop-controller:10263 |
metrics.probes | 収集するプローブタイプのリスト。各プローブはメトリックカテゴリにマッピングされます。デフォルトのプローブ: conntrack、qdisc、netdev、io、sock、tcpsummary、tcp、tcpext、udp、rdma。完全なプローブのリファレンスについては、「プローブ、メトリック、およびイベント」をご参照ください。 | 説明をご参照ください |
ARMS Prometheus ダッシュボードの設定
ARMS コンソールにログインし、左側のナビゲーションウィンドウで[統合管理]をクリックします。
[統合管理] ページで、[統合の追加] をクリックします。KubeSkoop を検索し、[ACK KubeSkoop ネットワークモニタリング] をクリックします。
「[ACK KubeSkoop ネットワーク監視]」ダイアログボックスで、ACK クラスターを選択し、「[統合名]」を入力して、「[OK]」をクリックします。
「ACK コンソール」にログインします。クラスター名をクリックします。左側のナビゲーションウィンドウで、[運用] > [Prometheus モニタリング] を選択します。
「[その他]」タブをクリックします。KubeSkoop によって作成されたノードおよびPodのモニタリングダッシュボードがダッシュボードリストに表示されます。

詳細については、「Alibaba Cloud Prometheus Service の使用方法」をご参照ください。
KubeSkoop メトリックへの手動アクセス
KubeSkoop は、各エージェント Pod のポート 9102 で Prometheus 形式のメトリックを公開します。メトリックを直接クエリするには、次の手順を実行します。
KubeSkoop エージェント Pod とそのノード IP のリストを取得します。
kubectl get pod -n ack-kubeskoop -o wide | grep kubeskoop-agent予想される出力:
kubeskoop-agent-2chvw 1/1 Running 0 43m 172.16.16.xxx 中国 (杭州).172.16.16.xxx <none> <none> kubeskoop-agent-2qtbf 1/1 Running 0 43m 172.16.16.xxx 中国 (杭州).172.16.16.xxx <none> <none> kubeskoop-agent-72pgf 1/1 Running 0 43m 172.16.16.xxx 中国 (杭州).172.16.16.xxx <none> <none>エージェントからすべてのメトリックを取得します。
172.16.16.xxxを前のステップの IP に置き換えます。curl http://172.16.16.xxx:9102/metrics
メトリックは次の形式に従います。
kubeskoop_netdev_rxbytes{k8s_namespace="",k8s_node="cn-hangzhou.172.16.16.xxx",k8s_pod=""} 2.970963745e+09各メトリックには k8s_namespace、k8s_node、および k8s_pod のラベルが付けられているため、Prometheus クエリで名前空間、ノード、または Pod でフィルタリングできます。
一般的なネットワーク問題のトラブルシューティング
次のセクションでは、各障害タイプで監視するメトリックと、それらを解釈する方法について説明します。
DNS タイムアウトのトラブルシューティング
コンテナ環境における DNS タイムアウトには、通常、次の 3 つの根本原因のいずれかがあります。
DNS サーバーの応答が遅く、クライアント側のタイムアウトに間に合わない。
送信者が DNS クエリパケットを迅速にディスパッチできない。
サーバーは時間内に応答するが、メモリ不足などのリソース制約により送信者が応答を破棄する。
ほとんどのクラウドネイティブワークロードは CoreDNS に依存しているため、アプリケーション Pod と CoreDNS Pod の両方で次のメトリックを監視してください。
| メトリック | 測定内容 |
|---|---|
kubeskoop_pod_udpsndbuferrors | ネットワーク層を介して UDP パケットを送信する際のエラー |
kubeskoop_pod_udpincsumerrors | UDP パケットを受信する際のチェックサムエラー |
kubeskoop_pod_udpnoports | __udp4_lib_rcv |
kubeskoop_pod_udpinerrors | UDP パケットを受信する際のエラー |
kubeskoop_pod_udpoutdatagrams | ネットワーク層を介して UDP によって正常に送信されたパケット |
kubeskoop_pod_udprcvbuferrors | アプリケーション層にデータをコピーする際にソケット受信キューが不十分なことによるエラー |
Nginx Ingress 499/502/503/504 エラーのトラブルシューティング
これらの 4 つのステータスコードはそれぞれ、異なる障害レイヤーを指しています。
| ステータスコード | 意味 | 一般的な原因 |
|---|---|---|
499 | Nginx が応答する前にクライアントが TCP 接続を閉じました | Nginx が処理中にクライアント側のタイムアウトに達しました。確立後にサーバーが接続をゆっくり処理する。アップストリームのバックエンドが遅い |
502 | Nginx がアップストリームから有効な応答を取得できませんでした | バックエンドの DNS 解決に失敗しました (Kubernetes Service を使用する際によく発生します)。アップストリームとの接続確立に失敗しました。アップストリームのリクエストまたは応答が大きすぎるため、メモリ割り当ての失敗を引き起こす |
503 | すべてのアップストリームサーバーが利用できません | 利用可能なバックエンドがない。Ingress limit-req 設定によってトラフィックがスロットルされました |
504 | Nginx がアップストリームを待機中にタイムアウトしました | アップストリームバックエンドからの応答が遅延しました |
まずベースライン情報を収集します。 KubeSkoop メトリックをチェックする前に、以下を収集します。
Nginx
access_log、特にrequest_time、upstream_connect_time、およびupstream_response_time問題発生時の Nginx
error_logエントリ設定されている場合の Liveness および readiness プローブのステータス
接続障害が疑われる場合は、これらのメトリックの変更を確認します。
| メトリック | 測定内容 |
|---|---|
kubeskoop_tcpext_listenoverflow | LISTEN 状態のソケットでのハーフコネクションキューオーバーフロー |
kubeskoop_tcpext_listendrops | LISTEN ソケットから SYN_RECV ソケットを作成する際の失敗 |
kubeskoop_netdev_txdropped | 伝送エラーにより NIC (ネットワークインターフェースカード) によって破棄されたパケット |
kubeskoop_netdev_rxdropped | 受信エラーにより NIC によって破棄されたパケット |
kubeskoop_tcp_activeopens | Pod が SYN パケットで TCP ハンドシェイクを開始する回数 (失敗した接続もこのカウンターをインクリメントします) |
kubeskoop_tcp_passiveopens | Pod が TCP ハンドシェイクを完了し、ソケットを割り当てる回数 (正常に確立された接続と同等) |
kubeskoop_tcp_retranssegs | TCP Segmentation Offload (TSO) 後に計算された単一 Pod 内の再送セグメントの合計 |
kubeskoop_tcp_estabresets | 単一 Pod 内で TCP 接続が異常終了した回数 |
kubeskoop_tcp_outrsts | 単一 Pod 内で TCP によって送信されたリセットパケット |
kubeskoop_conntrack_invalid | 接続追跡 (conntrack) エントリを確立できないが、パケットは破棄されない回数 |
kubeskoop_conntrack_drop | conntrack エントリを確立できなかったために破棄されたパケット |
Nginx の応答が遅い場合 (たとえば、request_time が長いが upstream_response_time が短い場合) は、キューの蓄積を確認します。
| メトリック | 測定内容 |
|---|---|
kubeskoop_tcpsummary_tcpestablishedconn | ESTABLISHED 状態の現在の TCP 接続 |
kubeskoop_pod_tcpsummarytcptimewaitconn | TIME_WAIT 状態の現在の TCP 接続 |
kubeskoop_tcpsummary_tcptimewaitconn | ESTABLISHED TCP 接続の送信キュー内の合計バイト数 |
kubeskoop_tcpsummary_tcprxqueue | ESTABLISHED TCP 接続の受信キュー内の合計バイト数 |
kubeskoop_tcpext_tcpretransfail | EBUSY 以外のエラーを返した再送パケット。再送失敗を示します |
TCP リセットのトラブルシューティング
TCP リセットは、アプリケーションでは「connection reset by peer」エラー (Nginx のような C ベースのアプリケーションでよく発生します) または「Broken pipe」エラー (TCP 接続ラッパーを使用する Java または Python アプリケーションでよく発生します) として現れます。
クラウドネイティブ環境における一般的な原因:
TCP メモリ不足などのサーバー側のリソース枯渇により、プロアクティブなリセットがトリガーされる。
ロードバランシングまたは Kubernetes Service が、エンドポイント選択または conntrack 状態の異常により、予期しないバックエンドにトラフィックを転送する。
セキュリティポリシーが接続を閉じる。
NAT 環境または高い同時実行性下で、Protection Against Wrapped Sequence Numbers (PAWS) またはシーケンス番号のラップアラウンドが発生する。
長期間ビジネス通信がなかったため、TCP キープアライブが期限切れになる。
まず、リセット発生時のクライアントとサーバー間のネットワークトポロジーをマッピングします。 次に、次のメトリックを確認します。
| メトリック | 測定内容 |
|---|---|
kubeskoop_tcpext_tcpabortontimeout | キープアライブ、ウィンドウプローブ、または再送試行の最大数を超過したために送信されたリセット |
kubeskoop_tcpext_tcpabortonlinger | TCP Linger2 オプションが有効な場合に FIN_WAIT2 状態の接続を再利用するために送信されたリセット |
kubeskoop_tcpext_tcpabortonclose | TCP 接続が閉じられたときに未読データが存在したために送信されたリセット |
kubeskoop_tcpext_tcpabortonmemory | tw_sock または tcp_sock リソースの割り当て中にメモリ不足のために送信されたリセット |
kubeskoop_tcpext_tcpabortondata | Linger または Linger2 オプションが有効な場合に高速接続再利用のために送信されたリセット |
kubeskoop_tcpext_tcpackskippedsynrecv | SYN_RECV 状態のソケットが ACK で応答しなかった回数 |
kubeskoop_tcpext_tcpackskippedpaws | PAWS メカニズムが修正をトリガーしたにもかかわらず、ウィンドウ外 (OOW) レート制限のために ACK が送信されなかった回数 |
kubeskoop_tcp_estabresets | 単一 Pod 内で TCP 接続が異常終了した回数 |
kubeskoop_tcp_outrsts | 単一 Pod 内で TCP によって送信されたリセットパケット |
ネットワークレイテンシージッターのトラブルシューティング
コンテナネットワークにおける断続的なレイテンシースパイクには、明らかでない原因があることがよくあります。症状はネットワーク遅延として現れますが、根本原因はしばしばオペレーティングシステムのスケジューリングまたはリソースの問題です。
一般的な原因:
RT スケジューラによって管理されるリアルタイムプロセスが長時間実行されすぎ、ビジネスプロセスまたはネットワークカーネルスレッドを枯渇させる。
ワークロードが、高レイテンシーのクラウドディスク I/O や断続的な RDS ラウンドトリップタイム (RTT) スパイクなど、時折遅い外部呼び出しを経験する。
CPU または NUMA ノード間の不均一な負荷により、一部の CPU の遅延を引き起こす。
conntrack 確認操作などのステートフルなカーネルメカニズム、または多数の孤立ソケットがソケットルックアップを遅くする。
原因を絞り込むために、次のメトリックを監視してください。
| メトリック | 測定内容 |
|---|---|
kubeskoop_io_ioreadsyscall | プロセスがファイルシステム読み取り操作 (read、pread) を実行する回数 |
kubeskoop_io_iowritesyscall | プロセスがファイルシステム書き込み操作 (write、pwrite) を実行する回数 |
kubeskoop_io_ioreadbytes | プロセスがファイルシステム (通常はブロックデバイス) から読み取るバイト数 |
kubeskoop_io_iowritebytes | プロセスがファイルシステムに書き込むバイト数 |
kubeskoop_tcpext_tcptimeouts | ACK されず再送された SYN パケット (輻輳回避状態が回復、損失、または障害に入っていない場合にインクリメントされます) |
kubeskoop_tcpsummary_tcpestablishedconn | ESTABLISHED 状態の現在の TCP 接続 |
kubeskoop_tcpsummary_tcptimewaitconn | TIME_WAIT 状態の現在の TCP 接続 |
kubeskoop_tcpsummary_tcptxqueue | ESTABLISHED TCP 接続の送信キュー内の合計バイト数 |
kubeskoop_tcpsummary_tcprxqueue | ESTABLISHED TCP 接続の受信キュー内の合計バイト数 |
kubeskoop_softnet_processed | 単一 Pod 内のすべての CPU によって処理された NIC バックログからのパケット |
kubeskoop_softnet_dropped | 単一 Pod 内のすべての CPU によって破棄されたパケット |
お客様事例
次のケースは、ACK KubeSkoop が実際の運用上の問題を特定し解決するためにどのように使用されたかを示しています。
ケース 1: 断続的な DNS タイムアウト
問題: PHP アプリケーションを実行しているお客様が、断続的な DNS 解決タイムアウトを経験しました。DNS サービスは CoreDNS で、設定されたアップストリームリゾルバーはパブリックプロバイダーを指していました。
調査結果: エラー発生時:
kubeskoop_udp_noportsが 1 増加しました。kubeskoop_packetloss_totalが 1 増加しました。
両方の変更は絶対値としては小さいものでした。
根本原因: パブリック DNS サーバーの応答が遅かった。PHP アプリケーションがクライアント側で既にタイムアウトした後で応答が到着しました。小さなメトリックの増加は、体系的ではなく偶発的なパケット遅延と一致していました。
ケース 2: Java アプリケーションにおける断続的な接続障害
問題: お客様の Tomcat サービスが断続的に利用できなくなり、各停止は約 5 ~ 10 秒間続きました。
調査結果: ログ分析により、各インシデント発生時にガベージコレクション (GC) の一時停止が発生していることが確認されました。KubeSkoop をデプロイした後、GC イベント中に kubeskoop_tcpext_listendrops が大幅に増加しました。
根本原因: GC 中、リクエスト処理が遅くなり、接続が迅速に解放されませんでした。受信接続リクエストが蓄積され続け、リッスンソケットのバックログがいっぱいになり、オーバーフローを引き起こしたため、kubeskoop_tcpext_listendrops の急増がトリガーされました。
解決策: お客様は Tomcat の接続バックログパラメーターを調整し、問題を解決しました。
ケース 3: Redis への断続的な RTT スパイク
問題: お客様は、合計応答時間が 300 ミリ秒を超える断続的な Redis リクエストを観測しましたが、必要に応じて問題を再現できませんでした。
調査結果: KubeSkoop をデプロイした後、レイテンシー発生時に kubeskoop_virtcmdlatency_latency が増加しました。
バケット
le=15(しきい値約 36 ミリ秒) が増加し、少なくとも 1 つの呼び出しが 36 ミリ秒を超えたことを示しています。バケット
le=18(しきい値約 200 ミリ秒) が増加し、200 ミリ秒を超える呼び出しを示しています。
根本原因: バッチ Pod の作成と削除中にトリガーされたカーネル仮想化呼び出しが CPU コアを占有し、プリエンプトできなかったため、お客様の断続的なレイテンシーを引き起こしました。
ケース 4: Nginx Ingress の断続的なヘルスチェック失敗
問題: Nginx Ingress のヘルスチェックが断続的に失敗し、ビジネスリクエストの失敗を伴いました。
調査結果: 各障害発生時:
kubeskoop_tcpsummary_tcprxqueueとkubeskoop_tcpsummary_tcptxqueueの両方が増加しました。kubeskoop_tcpext_tcptimeoutsが増加しました。kubeskoop_tcpsummary_tcptimewaitconnが減少し、kubeskoop_tcpsummary_tcpestablishedconnが増加しました。
カーネルと接続確立パスは正常に見えましたが、ユーザー空間プロセスは受信キューからパケットを消費せず、送信キューをフラッシュしませんでした。
根本原因: cgroup CPU スロットリングが断続的に Ingress プロセスのスケジューリングを妨げ、パケット処理と送信の両方を停止させました。
解決方法: 顧客は、CPU バーストの有効化に従って Nginx Ingress Pod で CPU バーストを有効化し、これにより速度制限が解消されました。
次のステップ
プローブ、メトリック、およびイベント — すべての KubeSkoop プローブとそれらが公開するメトリックの完全なリファレンス
Alibaba Cloud Prometheus Service の使用 — お使いの ACK クラスター向けに Prometheus モニタリングをセットアップします
CPU Burst の有効化 — 高遅延感度のワークロードにおける cgroup による速度制限を防ぐための CPU Burst の設定