リソース競合のトラブルシューティング

このページでは、Google Distributed Cloud 環境でリソースの競合の問題を特定してトラブルシューティングする方法について説明します。

さらにサポートが必要な場合は、Cloud カスタマーケアにお問い合わせください。

概要

Google Distributed Cloud でリソース競合が発生し、コンテナの速度やパフォーマンスが低下したり、コンテナが終了することがあります。これは、コンテナの CPU やメモリの使用量が多い場合に発生することがあります。

CPU とメモリ管理の仕組み

  • CPU:

    • Pod は、Pod 内のコンテナで指定された CPU リクエストに基づいてノードにスケジュールされます。
    • Pod のコンテナは、コンテナで指定された上限を超える CPU を使用できません。
    • コンテナの CPU 使用率は CPU 上限でスロットリングされます。
    • CPU 使用率がノードレベルでスロットリングされると、リクエストに応じてコンテナに CPU サイクルが自動的に割り当てられます。

    詳しくは、リソース リクエストのある Pod のスケジュール設定に関するページをご覧ください。

  • メモリ:

    • Pod は、Pod 内のコンテナで指定されたメモリ リクエストに基づいてノードにスケジュールされます。
    • コンテナは、コンテナで指定された上限を超えるメモリを使用できません。
    • メモリ上限が指定されていない場合、コンテナはノードで使用可能なすべてのメモリを使用することがあります。システムが OOM-Killer(Out Of Memory Killer)をトリガーし、優先度の低い Pod を強制排除する場合があります。

詳細については、Kubernetes の CPU リソースの割り当てに関するページメモリリソースの割り当てに関するページGKE Enterprise の指標をご覧ください。

問題

コンテナが遅くなる

CPU 競合の問題により、コンテナの処理速度が低下することがあります。次のような原因が考えられます。

コンテナの CPU 使用率が高い

コンテナは、CPU リクエストに応じて CPU サイクルを確保できない場合や、コンテナに必要な量よりも少なすぎる CPU リクエストが設定されている場合に遅くなる可能性があります。コンテナの CPU 上限に対する CPU 使用率を確認します。

Google Cloud コンソール > [Monitoring] > [Metrics Explorer] で、MQL エディタから次のクエリを実行します。

  fetch k8s_container
  | metric 'kubernetes.io/anthos/container/cpu/limit_utilization'
  | group_by 1m, [value_limit_utilization_mean: mean(value.limit_utilization)]
  | filter resource.cluster_name == 'CLUSTER_NAME'
  | filter resource.container_name == 'CONTAINER_NAME'
  | filter resource.pod_name == 'POD_NAME'
  | filter resource.namespace_name == 'NAMESPACE_NAME'
  | every 1m

以下のいずれかを行います。

ノードでの CPU 使用率が高い

Pod の個々のコンテナで CPU 上限に対する CPU 使用率が高くない場合は、ノードで実行されているコンテナのセットに割り当てる CPU サイクルがノードに不足している可能性があります。そのため、次の手順に沿って、ノード上の割り当て可能な CPU に対する実際の CPU 使用率を確認します。

  1. 処理速度が遅い Pod のノードを確認します。

    kubectl get pod –kubeconfig CLUSTER_KUBECONFIG --namespace NAMESPACE POD --output wide
    
  2. Google Cloud コンソール > [Monitoring] > [Metrics Explorer] で、MQL エディタから次のクエリを実行します。

    fetch k8s_node
    | metric 'kubernetes.io/anthos/node/cpu/allocatable_utilization'
    | group_by 1m,
        [value_allocatable_utilization_mean: mean(value.allocatable_utilization)]
    | filter resource.cluster_name == 'CLUSTER_NAME'
    | filter resource.node_name == 'NODE_NAME'
    | every 1m
    

    この比率が高い場合(>=0.8)、ノードに十分な CPU サイクルがなく、オーバーサブスクライブされていることを意味します。次の手順に沿って、そのノードの他のすべての Pod の CPU 使用率を確認し、より多くの CPU を使用している別のコンテナがあるかどうかを調べてください。

    1. ノード上のすべての Pod を取得します。
    kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=NODE_NAME
    
    1. 各コンテナの CPU 使用率を確認します。
    fetch k8s_container
    | metric 'kubernetes.io/anthos/container/cpu/limit_utilization'
    | group_by 1m, [value_limit_utilization_mean: mean(value.limit_utilization)]
    | filter resource.cluster_name == 'CLUSTER_NAME'
    | filter resource.container_name == 'CONTAINER_NAME'
    | filter resource.pod_name == 'POD_NAME'
    | filter resource.namespace_name == 'NAMESPACE_NAME'
    | every 1m
    

    ノードに CPU 使用率の高いコンテナが他にもある場合は、動作が遅いコンテナの CPU リクエストと上限を増やします。これにより、Pod が別のノードに再作成され、必要な CPU サイクルが得られます。

システム Pod の動作が遅い場合は、Google サポートにお問い合わせください。

vSphere レベルの CPU オーバーサブスクリプション

ノードまたは Pod の CPU 使用率が高くなく、コンテナがまだ遅い場合は、VM が vSphere レベルでオーバーサブスクライブされている可能性があります。そのため、ノードは基盤となる仮想化から想定される CPU サイクルを得られません。

VM がオーバーサブスクライブされているかどうかを確認するには、こちら手順で操作します。オーバーサブスクリプションが検出された場合は、次の方法をお試しください。

  • 一部の VM を他のホストに移動する。
  • ホストの VM あたりの vCPU の数を評価して減らす。
  • GKE Enterprise VM に追加のリソースを割り当てる。
  • コンテナの CPU リクエストと上限を増やす。これにより、Pod が別のノードに再作成され、必要な CPU サイクルが得られます。

Pod で OOMkilled(Out of Memory-Killed)が発生する

Pod で、メモリリーク、またはコンテナのメモリ リクエストと上限の構成により OOMKilled が発生することがあります。次のような原因が考えられます。

コンテナのメモリ使用量が多い

Pod 内のコンテナが割り当てられた合計メモリを過剰に使用した場合、Pod で OOMkilled が発生する可能性があります。コンテナのメモリ上限に対するメモリ リクエストの比率を確認します。

Google Cloud コンソール > [Monitoring] > [Metrics Explorer] で、MQL エディタから次のクエリを実行します。

fetch k8s_container
| metric 'kubernetes.io/anthos/container/memory/limit_utilization'
| filter (metric.memory_type == 'non-evictable')
| group_by 1m, [value_limit_utilization_mean: mean(value.limit_utilization)]
| filter resource.cluster_name == 'CLUSTER_NAME'
| filter resource.container_name == 'CONTAINER_NAME'
| filter resource.pod_name == 'POD_NAME'
| filter resource.namespace_name == 'NAMESPACE_NAME'
| every 1m

以下のいずれかを行います。

ノードのメモリ使用量が多い

ノードで実行中のすべての Pod のメモリ使用量が使用可能なメモリを超えると、Pod で OOMkilled が発生することがあります。そのため、ノードの MemoryPressure 条件が True であるかどうかを確認します。

  1. 次のコマンドを実行して、Conditions セクションを調べます。

    kubectl describe nodes --kubeconfig CLUSTER_KUBECONFIG NODE-NAME
    
  2. MemoryPressure 条件が True の場合は、ノードのメモリ使用率を確認します。

    fetch k8s_node
    | metric 'kubernetes.io/anthos/node/memory/allocatable_utilization'
    | filter (metric.memory_type == 'non-evictable')
    | group_by 1m,
        [value_allocatable_utilization_mean: mean(value.allocatable_utilization)]
    | filter resource.cluster_name == 'CLUSTER_NAME'
    | filter resource.node_name = 'NODE_NAME'
    | every 1m
    

    この比率が高い場合(>= 0.8)、ノードには Pod に割り当てる十分なメモリがないことを意味します。これはおそらく一部のプロセスや他の Pod が多くのメモリを使用していることが原因です。

  3. Google Cloud コンソール > [Monitoring] > [Metrics Explorer] で、MQL エディタを使用して次のクエリを実行し、ノード上のコンテナのメモリ使用量を確認します。

    fetch k8s_node
    | metric 'kubernetes.io/anthos/container_memory_usage_bytes'
    | filter resource.cluster_name == 'CLUSTER_NAME'
    | filter resource.node_name == 'NODE_NAME'
    | group_by 1m,
        [value_container_memory_usage_bytes_mean:
          mean(value.container_memory_usage_bytes)]
    | every 1m
    

    メモリ使用量の多いコンテナがある場合は、コンテナの機能を調べるか、必要に応じてコンテナのメモリ リクエストを増やします

メモリを大量に使用しているのがシステム Pod である場合は、Google サポートにお問い合わせください。

さらに、Google Distributed Cloud の自動スケーリング機能を有効にして、ワークロードの需要に基づいてノードプールのスケールアップとスケールダウンを自動的に行うことができます。

オートスケーラーを有効にする方法をご確認ください。

etcd に関する問題

etcd サーバーの問題により、Anthos clusters on VMware でコンテナ障害が発生することがあります。また、次のような問題が発生する可能性があります。

  • 次の形式の API サーバーログが繰り返される。

    etcdserver: request timed outetcdserver: leader changed

  • 次の形式の etcd ログが繰り返される。

    W | wal: sync duration of 2.466870869s, expected less than 1sW | etcdserver: read-only range request * took too long

次のような原因が考えられます。

CPU スロットリング

etcd サーバー Pod や、etcd サーバーが実行されているノードでの CPU スロットリングが原因で、etcd サーバーが遅くなることがあります。CPU の競合の問題を確認するには、コンテナが遅くなるの手順をご覧ください。

ectd サーバー Pod またはノードで CPU 競合が検出された場合は、ユーザー クラスタのコントロール プレーン ノードに CPU を追加します。gkectl update を使用して、ユーザー クラスタの構成ファイルの cpus フィールドを編集します。

etcd Pod の OOMkilled

リソース競合の問題により、etcd Pod で OOMkilled が発生することがあります。Pod で OOMkilled(メモリ不足による終了)が発生するセクションの手順に沿って、etcd サーバー Pod や etcd サーバーが実行されているノードにメモリ競合の問題がないか確認します。

etcd Pod で OOMkill が検出された場合は、ユーザー クラスタのコントロール プレーン ノードで使用可能なメモリを増やします。gkectl update を使用して、ユーザー クラスタの構成ファイルの memoryMB フィールドを編集します。

ディスクの速度低下

etcd サーバー Pod やノードの CPU またはメモリ使用量に問題がない場合、基盤となるデータストアが低速であったり、スロットリングされていると、etcd が遅くなる可能性があります。

次のような問題がないか確認します。

  • etcd サーバーで基盤となるディスクの読み書きに時間がかかりすぎているかどうかを確認するには:

    1. etcd ログを取得します。

      kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG logs -n ETCD_POD_NAMESPACE ETCD_POD
      
    2. etcd でディスクからの読み取りに時間がかかりすぎているかどうかを検出するには、次のパターンのエントリを探します。

      W | etcdserver: read-only range request "key:\"/registry/configmaps/default/clusterapi-vsphere-controller-manager-leader-election\" " with result "range_response_count:1 size:685" took too long (6.893127339s) to execute

    3. etcd でディスクへの書き込みに時間がかかりすぎているかどうかを検出するには、次のパターンのエントリを探します。

      W | wal: sync duration of 2.466870869s, expected less than 1s

    etcd ログで、上記のログパターンのいずれかまたは両方が頻繁に発生している場合は、ディスクの速度が低下していることを示しています。次に、データストアとディスクのパフォーマンスを確認します。

  • etcd 指標を確認するには:

    1. etcd の WAL 同期レイテンシを取得します。

      Google Cloud コンソール > [Monitoring] > [Metrics Explorer] で、MQL エディタから次のクエリを実行します。

      fetch k8s_container::kubernetes.io/anthos/etcd_disk_wal_fsync_duration_seconds
      | every 1m
      | filter resource.cluster_name == 'CLUSTER_NAME'
      | filter resource.pod_name == 'POD_NAME'
      | filter resource.namespace_name == 'NAMESPACE_NAME'
      | percentile 99
      
    2. etcd の書き込みレイテンシを取得します。

      Google Cloud コンソール > [Monitoring] > [Metrics Explorer] で、MQL エディタから次のクエリを実行します。

      fetch k8s_container::kubernetes.io/anthos/etcd_disk_backend_commit_duration_seconds
      | every 1m
      | filter resource.cluster_name == 'CLUSTER_NAME'
      | filter resource.pod_name == 'POD_NAME'
      | filter resource.namespace_name == 'NAMESPACE_NAME'
      | percentile 99
      

    etcd_disk_wal_fsync_duration_secondsp99 が継続的に 10 ミリ秒を超える場合や、etcd_disk_backend_commit_duration_secondsp99 が継続的に 25 ミリ秒を超える場合は、ディスクの速度低下を示しています。次に、データストアとディスクのパフォーマンスを確認します。

VM ディスクに対する読み取り / 書き込みレイテンシ

VM 仮想ディスクに対する読み取り / 書き込みレイテンシを確認する手順は次のとおりです。

  1. 速度の遅い etcd Pod のノードを特定します。

    kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG get pods -n ETCD_POD_NAMESPACE ETCD_POD -owide
    
  2. vSphere にログインし、前の手順で特定した VM を選択します。vSphere で、[Monitor] > [Performance] > [Advanced] に移動し、[View] セクションの [Virtual Disk] を選択して、仮想ディスクの読み取りと書き込みのレイテンシを特定します。

    仮想ディスクの読み取り / 書き込みレイテンシが高い場合:

    • データストアで実行されている他の VM を調べて、1 秒あたりの入出力オペレーション(IOPS)の多いものがないか確認します。VM の IOPS に急上昇が見られる場合は、その VM の機能を評価します。
    • ラボやインフラチームに連絡して、読み取りと書き込みの帯域幅がどの段階でもスロットリングまたは制限されていないことを確認してください。
    • ラボやインフラチームに連絡して、ディスク パフォーマンスストレージ パフォーマンスの問題(存在する場合)を特定します。

詳しくは、リソースのスケーリングに関するベスト プラクティスをご覧ください。

API サーバーの問題

API サーバーとの通信中に Google Distributed Cloud のコンテナでレイテンシが発生した場合、または Kubectl コマンドが失敗するか、応答に時間がかかりすぎる場合は、API サーバーに問題があることを示している可能性があります。

次のような原因が考えられます。

大量の API リクエスト

API サーバーへのリクエストの頻度と量が過剰な場合、API サーバーの応答が遅くなることがあります。API サーバーがリクエストのスロットリングを開始した後も、応答時間が遅いままである場合があります。このため、API サーバーに対する API リクエストのレートを確認します。

Google Cloud コンソール > [Monitoring] > [Metrics Explorer] で、MQL エディタから次のクエリを実行します。

fetch k8s_container::kubernetes.io/anthos/apiserver_request_total
| filter resource.cluster_name == 'CLUSTER_NAME'
| filter resource.pod_name == 'APISERVER_POD_NAME'
| filter resource.namespace_name == 'NAMESPACE_NAME'
| align rate(1m)
| every 1m
| group_by [metric.verb]

API リクエストが予期せず増加した場合は、Cloud Audit Logging を使用して、API サーバーに頻繁にクエリを実行している可能性のある Pod を特定します。

  • システム Pod の場合は、Google サポートにお問い合わせください。
  • ユーザー Pod の場合は、さらに調査して、API リクエストが想定どおりかどうかを判断します。

CPU スロットリング

API サーバーに対するリクエスト率が高いと、CPU スロットリングが発生する可能性があります。この場合、API サーバー Pod やノードでの CPU の競合が原因で、API サーバーが遅くなることがあります。

コンテナが遅くなるセクションを参照して、Pod やノードに CPU 競合の問題がないか確認します。

API サーバー Pod の OOMkilled

リソース競合の問題により、API サーバー Pod で OOMkilled が発生することがあります。Pod で OOMkilled(メモリ不足による終了)が発生するセクションの手順に沿って、Pod やノードにメモリ競合の問題がないか確認します。

etcd のレスポンスが遅い

API サーバーは etcd クラスタとの通信を利用して、クライアントへの読み取り / 書き込みリクエストを処理します。etcd が遅い場合や応答しない場合、API サーバーも遅くなります。

API サーバーのログを取得して、etcd の問題が原因で API サーバーが遅くなっているのかどうかを確認します。

kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG logs -n APISERVER_NAMESPACE APISERVER_POD_NAME

繰り返し発生するログ(etcdserver: request timedoutetcdserver: leader changed など)が見られる場合は、etcd に関する問題の手順に沿ってディスク関連の問題を解決してください。

クラスタが指標をエクスポートしない

このドキュメントでこれまでに説明した手法では、クラスタから Google Cloud プロジェクトに指標がエクスポートされることを前提としています。

クラスタが指標をエクスポートしていない場合は、コマンドラインを使用してリソース競合を調査できます。ここでは、管理ワークステーションで実行して指標を表示できるコマンドについて説明します。

ノードの指標を表示する:

kubectl --kubeconfig CLUSTER_KUBECONFIG get --raw \
    /apis/metrics.k8s.io/v1beta1/nodes/NODE_NAME | jq

次のように置き換えます。

  • CLUSTER_KUBECONFIG: クラスタの kubeconfig ファイルのパス
  • NODE_NAME: ノードの名前

Pod の指標を表示する:

kubectl --kubeconfig CLUSTER_KUBECONFIG get --raw \
    /apis/metrics.k8s.io/v1beta1/namespaces/NAMESPACE/pods/POD_NAME | jq

次のように置き換えます。

  • NAMESPACE: Pod の Namespace
  • POD_NAME: Pod の名前

すべてのノードの指標を表示する:

kubectl --kubeconfig CLUSTER_KUBECONFIG top node

Namespace 内のすべての Pod の指標を表示する:

kubectl --kubeconfig CLUSTER_KUBECONFIG top pod --namespace NAMESPACE

Namespace 内のすべての Pod のコンテナの指標を表示する:

kubectl --kubeconfig CLUSTER_KUBECONFIG top pod --containers --namespace NAMESPACE

詳細については、kubectl top podkubectl top node をご覧ください。

ノードで実行されているコンテナから top コマンドを実行することもできます。

コンテナ内でコマンドを実行する方法は 2 つあります。

  • 管理ワークステーションで kubectl exec を実行して、コンテナでシェルを起動します。シェルでコマンドを実行します。

  • ノードと SSH 接続を確立します。次に、docker exec を使用して、コンテナでシェルを起動します。シェルでコマンドを実行します。

次のステップ

さらにサポートが必要な場合は、Cloud カスタマーケアにお問い合わせください。