すべてをまとめる: トラブルシューティングのシナリオの例


Google Kubernetes Engine(GKE)の個々のトラブルシューティング ツールを理解することは重要ですが、それらを組み合わせて実際の問題を解決する方法を理解することで、知識を深めることができます。

Google Cloud コンソール、kubectl コマンドライン ツール、Cloud Logging、Cloud Monitoring を組み合わせて OutOfMemoryOOMKilled)エラーの根本原因を特定するガイド付きの例に沿って操作します。

この例は、このシリーズで説明するトラブルシューティング手法の実際の適用例を確認したいユーザー(特にプラットフォーム管理者と運用担当者、アプリケーション デベロッパー)にとって有益です。Google Cloud のコンテンツで使用されている一般的なロールとタスクの例の詳細については、一般的な GKE ユーザー ロールとタスクをご覧ください。

シナリオ

GKE で実行される product-catalog という名前のウェブアプリのオンコール エンジニアです。

調査は、Cloud Monitoring から自動アラートを受信したときに開始されます。

Alert: High memory utilization for container 'product-catalog' in 'prod' cluster.

このアラートは、問題が存在することと、その問題が product-catalog ワークロードに関連していることを示します。

Google Cloud コンソールで問題を確認する

まず、ワークロードの概要を確認して、問題を確認します。

  1. Google Cloud コンソールで、[ワークロード] ページに移動し、product-catalog ワークロードでフィルタします。
  2. [Pods] ステータス列を確認します。正常な 3/3 ではなく、値が 2/3 のように異常な状態を示しています。この値は、アプリの Pod のいずれかのステータスが Ready ではないことを示します。
  3. さらに調査するため、product-catalog ワークロードの名前をクリックして詳細ページに移動します。
  4. 詳細ページで、[マネージド Pod] セクションを表示します。すぐに問題が特定されます。Pod の Restarts 列に、異常に高い数値である 14 が表示されています。

再起動回数が多い場合は、問題によってアプリが不安定になっていることが確認できます。また、コンテナがヘルスチェックに失敗しているか、クラッシュしていることが示唆されます。

kubectl コマンドで理由を確認する

アプリが繰り返し再起動していることがわかったので、その理由を調べる必要があります。この場合は、kubectl describe コマンドが役立ちます。

  1. 不安定な Pod の正確な名前を取得します。

    kubectl get pods -n prod
    

    次のような出力が表示されます。

    NAME                             READY  STATUS            RESTARTS  AGE
    product-catalog-d84857dcf-g7v2x  0/1    CrashLoopBackOff  14        25m
    product-catalog-d84857dcf-lq8m4  1/1    Running           0         2h30m
    product-catalog-d84857dcf-wz9p1  1/1    Running           0         2h30m
    
  2. 不安定な Pod の説明を取得して、イベント履歴の詳細を確認します。

    kubectl describe pod product-catalog-d84857dcf-g7v2x -n prod
    
  3. 出力を確認すると、Last State セクションと Events セクションに手がかりが見つかります。

    Containers:
      product-catalog-api:
        ...
        State:          Waiting
          Reason:       CrashLoopBackOff
        Last State:     Terminated
          Reason:       OOMKilled
          Exit Code:    137
          Started:      Mon, 23 Jun 2025 10:50:15 -0700
          Finished:     Mon, 23 Jun 2025 10:54:58 -0700
        Ready:          False
        Restart Count:  14
    ...
    Events:
      Type     Reason     Age                           From                Message
      ----     ------     ----                          ----                -------
      Normal   Scheduled  25m                           default-scheduler   Successfully assigned prod/product-catalog-d84857dcf-g7v2x to gke-cs-cluster-default-pool-8b8a777f-224a
      Normal   Pulled     8m (x14 over 25m)             kubelet             Container image "us-central1-docker.pkg.dev/my-project/product-catalog/api:v1.2" already present on machine
      Normal   Created    8m (x14 over 25m)             kubelet             Created container product-catalog-api
      Normal   Started    8m (x14 over 25m)             kubelet             Started container product-catalog-api
      Warning  BackOff    3m (x68 over 22m)             kubelet             Back-off restarting failed container
    

    出力には、次の 2 つの重要な手がかりが表示されます。

    • まず、Last State セクションには、コンテナが Reason: OOMKilled で終了したことが示されています。これは、メモリ不足になったことを示しています。この理由は Exit Code: 137 によって確認できます。これはメモリ消費量が多すぎるために強制終了されたプロセスの標準的な Linux 終了コードです。
    • 次に、Events セクションにはメッセージ Back-off restarting failed container を含む Warning: BackOff イベントが表示されます。このメッセージは、コンテナが失敗ループに陥っていることを確認するものです。これは、先ほど確認した CrashLoopBackOff ステータスの直接の原因です。

指標を使用して動作を可視化する

kubectl describe コマンドは発生したことを示しますが、Cloud Monitoring では環境の動作を時系列で確認できます。

  1. Google Cloud コンソールで、[Metrics Explorer] に移動します。
  2. container/memory/used_bytes 指標を選択します。
  3. 出力を特定のクラスタ、Namespace、Pod 名にフィルタします。

グラフには、メモリ使用量が着実に増加し、コンテナが OOM で強制終了して再起動すると、急激にゼロに低下するという明確なパターンが示されています。この視覚的な証拠は、メモリリークまたはメモリ上限の不足のいずれかを示しています。

ログで根本原因を見つける

これで、コンテナのメモリが不足していることはわかりましたが、その原因はまだ特定できていません。根本原因を特定するには、ログ エクスプローラを使用します。

  1. Google Cloud コンソールで、[ログ エクスプローラ] に移動します。
  2. クエリを作成して、最後のクラッシュの直前の特定のコンテナのログをフィルタします(kubectl describe コマンドの出力で確認できます)。

    resource.type="k8s_container"
    resource.labels.cluster_name="example-cluster"
    resource.labels.namespace_name="prod"
    resource.labels.pod_name="product-catalog-d84857dcf-g7v2x"
    timestamp >= "2025-06-23T17:50:00Z"
    timestamp < "2025-06-23T17:55:00Z"
    
  3. ログには、クラッシュの直前にメッセージの繰り返しパターンが見られます。

    {
      "message": "Processing large image file product-image-large.jpg",
      "severity": "INFO"
    },
    {
      "message": "WARN: Memory cache size now at 248MB, nearing limit.",
      "severity": "WARNING"
    }
    

これらのログエントリは、アプリが大きな画像ファイルをメモリに完全に読み込んで処理しようとしており、最終的にコンテナのメモリ上限に達したことを示しています。

検出結果

これらのツールを併用することで、問題の全体像を把握できます。

  • モニタリング アラートで問題が発生したことが通知されました。
  • Google Cloud コンソールには、問題がユーザーに影響している(再起動)ことが示されています。
  • kubectl コマンドで、再起動の正確な理由(OOMKilled)を特定しました。
  • Metrics Explorer に、メモリリークのパターンが時系列で表示されています。
  • ログ エクスプローラで、メモリの問題の原因となっている特定の動作が明らかになりました。

これで、ソリューションを実装する準備が整いました。アプリコードを最適化して大きなファイルをより効率的に処理するか、短期的な修正として、ワークロードの YAML マニフェストでコンテナのメモリ上限(具体的には spec.containers.resources.limits.memory 値)を引き上げることができます。

次のステップ