このページでは、Google Distributed Cloud 環境でリソースの競合の問題を特定してトラブルシューティングする方法について説明します。
さらにサポートが必要な場合は、Cloud カスタマーケアにお問い合わせください。概要
Google Distributed Cloud でリソース競合が発生し、コンテナの速度やパフォーマンスが低下したり、コンテナが終了したりすることがあります。これは、コンテナの CPU やメモリの使用量が多い場合に発生することがあります。
CPU とメモリ管理の仕組み
CPU:
- Pod は、Pod 内のコンテナで指定された CPU リクエストに基づいてノードにスケジュールされます。
- Pod 内のコンテナは、コンテナで指定された上限を超える CPU を使用できません。
- コンテナの CPU 使用率は CPU 上限でスロットリングされます。
- CPU 使用率がノードレベルでスロットリングされると、リクエストに応じてコンテナに CPU サイクルが自動的に割り当てられます。
詳しくは、リソース リクエストのある Pod のスケジュール設定方法をご覧ください。
メモリ:
- Pod は、Pod 内のコンテナで指定されたメモリ リクエストに基づいてノードにスケジュールされます。
- コンテナは、コンテナで指定された上限を超えるメモリを使用できません。
- メモリ上限が指定されていない場合、コンテナはノードで使用可能なすべてのメモリを使用することがあります。システムが OOM-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
以下のいずれかを行います。
- この比率が高い場合(>= 0.8)、コンテナの CPU 上限が低く、Kubernetes がコンテナの CPU サイクルをスロットリングして CPU 使用率が上限内に収まるようにしていることを意味します。この問題を解決するには、コンテナの CPU 上限を引き上げます。
- この比率が高くない場合(< 0.8)は、ノードの CPU 使用率が高いかどうかを確認します。
ノードでの CPU 使用率が高い
Pod の個々のコンテナで CPU 使用量に対する CPU 上限の比率が高くない場合は、ノードで実行されているコンテナのセットに割り当てるのに十分な CPU サイクルがノードにない可能性があります。そのため、次の手順に沿って、ノード上の割り当て可能な CPU に対する実際の CPU 使用率を確認します。
処理速度が遅い Pod のノードを確認します。
kubectl get pod –kubeconfig CLUSTER_KUBECONFIG --namespace NAMESPACE POD --output wide
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 を使用している別のコンテナがあるかどうかを調べてください。
- ノード上のすべての Pod を取得します。
kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=NODE_NAME
- 各コンテナの 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 リクエストと CPU 上限を増やします。これにより、Pod が別のノードに再作成され、必要な CPU サイクルが得られます。
システム Pod の動作が遅い場合は、Google サポートにお問い合わせください。
vSphere レベルの CPU オーバーサブスクリプション
ノードまたは Pod の CPU 使用率が高くなく、コンテナがまだ遅い場合は、VM が vSphere レベルでオーバーサブスクライブされている可能性があります。そのため、ノードは基盤となる仮想化から想定される CPU サイクルを得られません。
VM がオーバーサブスクライブされているかどうかを確認するには、こちら手順で操作します。オーバーサブスクリプションが検出された場合は、次の方法をお試しください。
- 一部の VM を他のホストに移動する。
- ホストの VM あたりの vCPU の数を評価して減らす。
- GKE Enterprise VM に追加のリソースを割り当てる。
- コンテナの CPU リクエストと上限を増やす。これにより、Pod が別のノードに再作成され、必要な CPU サイクルが得られます。
Pod で OOMkilled(メモリ不足による終了)が発生する
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
以下のいずれかを行います。
- この比率が高い場合(>= 0.8)は、コンテナのメモリ上限を増やします。
- この比率が高くない場合(< 0.8)は、ノードのメモリ使用量が多いかどうかを確認します。
ノードのメモリ使用量が多い
ノードで実行中のすべての Pod のメモリ使用量が使用可能なメモリを超えると、Pod で OOMkilled が発生することがあります。そのため、ノードの MemoryPressure
条件が True
であるかどうかを確認します。
次のコマンドを実行して、
Conditions
セクションを調べます。kubectl describe nodes --kubeconfig CLUSTER_KUBECONFIG NODE-NAME
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 が多くのメモリを使用していることが原因です。
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 out
とetcdserver: leader changed
次の形式の etcd ログが繰り返される。
W | wal: sync duration of 2.466870869s, expected less than 1s
とW | 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 サーバーで基盤となるディスクの読み書きに時間がかかりすぎているかどうかを確認するには:
etcd ログを取得します。
kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG logs -n ETCD_POD_NAMESPACE ETCD_POD
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
etcd でディスクへの書き込みに時間がかかりすぎているかどうかを検出するには、次のパターンのエントリを探します。
W | wal: sync duration of 2.466870869s, expected less than 1s
etcd ログで、上記のログパターンのいずれかまたは両方が頻繁に発生している場合は、ディスクの速度が低下していることを示しています。次に、データストアとディスクのパフォーマンスを確認します。
etcd 指標を確認するには:
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
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_seconds
のp99
が継続的に 10 ミリ秒を超える場合や、etcd_disk_backend_commit_duration_seconds
のp99
が継続的に 25 ミリ秒を超える場合は、ディスクの速度低下を示しています。次に、データストアとディスクのパフォーマンスを確認します。
VM ディスクに対する読み取り / 書き込みレイテンシ
VM 仮想ディスクに対する読み取り / 書き込みレイテンシを確認する手順は次のとおりです。
速度の遅い etcd Pod のノードを特定します。
kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG get pods -n ETCD_POD_NAMESPACE ETCD_POD -owide
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 timedout
、etcdserver: 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 pod と kubectl top node をご覧ください。
ノードで実行されているコンテナから top コマンドを実行することもできます。
コンテナ内でコマンドを実行する方法は 2 つあります。
管理ワークステーションで kubectl exec を実行して、コンテナでシェルを起動します。シェルでコマンドを実行します。
ノードと SSH 接続を確立します。次に、docker exec を使用して、コンテナでシェルを起動します。シェルでコマンドを実行します。