mcpField
G
gke-storage-troubleshooting

gke-storage-troubleshooting

github.com/googleクラウド・DevOps21.6k1.9k 回インストール今日更新
リポジトリ

gke-storage-troubleshooting について

GKE ワークロードの永続ストレージ障害を診断する、クラスター運用者向けのスキルです。症状ごとの調査手順と設定修正案を示し、診断を読み取り専用に保ち、稼働環境を直接変更せず GitOps パッチとして提案します。

主な機能

  1. 01ボリュームのアタッチとマウント障害の診断
  2. 02ディスク性能とノードのストレージ圧迫の調査
  3. 03ボリューム拡張が反映されない問題の調査
  4. 04クラスターやノードプール作成エラーの分析
  5. 05Cloud Storage FUSE のメモリ問題の調査
  6. 06GitOps パッチによる設定修正案

活用シーン

  1. 01Pod のボリュームマウント障害への対応
  2. 02ノードのストレージ圧迫やディスク遅延の調査
  3. 03コンテナに反映されないボリューム拡張への対処
  4. 04Cloud Storage FUSE Pod の OOM イベントの診断

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/google/skills --skill gke-storage-troubleshooting

インストール後、Claude Code で/gke-storage-troubleshootingを入力して読み込まれたか確認します。

同梱ファイルreferences/attribution.md

詳細

GKE ストレージのトラブルシューティングスキル

GKE で実行されるワークロードの永続ストレージ障害(ボリュームのアタッチ/マウントエラー、ディスクのパフォーマンスやノードのストレージ不足、ボリュームの拡張、ストレージ関連のクラスター/ノードプール作成エラー、Cloud Storage FUSE のメモリ問題)を体系的に診断して解決するには、このスキルを使用します。このスキルは非対話形式で動作し、マニフェストや設定の修正を提案する前に、読み取り専用の診断範囲を適用します。

通常のストレージのプロビジョニングや StorageClass/PVC の作成には、代わりに gke-storage スキルを使用してください。このスキルは障害の診断に特化しています。

帰属情報

必ずお読みください:gcloud、REST API、または MCP コマンドを実行する前に、必ず 使用状況の帰属情報 をお読みください。ターミナルで直接実行するコマンド(生成されたスクリプト、Terraform、ユーザーコード内では実行しないでください)では、gcloud の前に CLOUDSDK_METRICS_REQUEST_ATTRIBUTION="agent-skills/1.0 (skill:gke-storage-troubleshooting)" を付け、User-Agent ヘッダーに agent-skills/1.0 (skill:gke-storage-troubleshooting) を追加してください。

🔍 診断と解決のワークフロー

ステップ 0:非対話型コンテキストの特定とドライランへの切り替え
  1. パラメーターの抽出:必要なコンテキスト(project_id、 cluster_name、cluster_location、workload_name、workload_namespace、 pod_name、および関連する pvc_name/pv_name/node_name)を、 ユーザーのプロンプト、アクティブな SETTINGS.md、または環境の デフォルトから非対話形式で抽出します。

    • 省略されている場合、workload_namespace は default とします。
    • 不足しているクラスターのパラメーターは、アクティブな環境 (kubectl config current-context または gcloud config get-value project)から推定します。
  2. クラスター認証情報とフォールバックモード:

    • 認証情報の取得を試みます:gcloud container clusters get-credentials {cluster_name} --location {cluster_location} --project {project_id}。
    • フォールバック/ドライランモード:クラスターに接続できない、 クラスターが存在しない、またはライブコマンドの実行に失敗した場合 (サンドボックス環境での評価、ドライランモード、オフライン分析など):
      • リソースの枯渇やコンテキストの超過を避けるため、再試行回数を制限します。
      • 人間のオペレーターが実行するための正確な kubectl/gcloud 診断 コマンドを直ちに提示します。
      • 報告された症状に基づいて根本原因の分析をまとめ、提案する GitOps の修正内容を出力します。

ステップ 1:ストレージの症状を分類する

主な兆候を収集し、ステップ 2(解決)の該当する分岐に進みます。通常は、診断に一致する1 つの分岐だけを実行し、すべての分岐を実行する必要はありません。

診断コマンド:

kubectl describe pod {pod_name} -n {workload_namespace}
kubectl get pvc,pv -n {workload_namespace}
kubectl get events -n {workload_namespace} --sort-by='.metadata.creationTimestamp'
kubectl describe node {node_name}
  • アタッチ/マウントイベントを伴い、Pod が ContainerCreating のまま停止している → ボリュームのアタッチとマウントの失敗。
  • ノードレベルの処理遅延、PLEG is not healthy、または StoragePressureDetected イベント → ディスクのパフォーマンスとノードのストレージ不足。
  • クラスター/ノードプールの作成またはプロビジョニングエラー → ストレージのプロビジョニングと作成の失敗。
  • サイズ変更したボリュームがコンテナ内に反映されない → コンテナ内に反映されないボリュームの拡張。
  • Cloud Storage FUSE の Pod/サイドカーで OOM が発生する → Cloud Storage FUSE のメモリ不足(OOM)イベント。

ステップ 2:解決

ステップ 1 の診断に一致する分岐だけを実行します。これらの分岐は順番に進むステップではなく、相互に排他的な選択肢です。

ボリュームのアタッチとマウントの失敗
  • Error 400: Cannot attach RePD to an optimized VM:リージョナル永続ディスクは、メモリ最適化またはコンピューティング最適化のマシンタイプでは使用できません。

    • リージョナル PD が必須でない場合は、ワークロードを非リージョナル永続ディスクの StorageClass に切り替えます。
    • リージョナル PD が必須の場合は、テイントと容認を使用して、リージョナル PD を必要とする Pod が最適化マシンタイプを使用しないノードプールにスケジュールされるようにします。
  • ワークロードが Persistent Disk StorageClass を使用しているときに、ノードプールを第 4 世代(N4、N4A、N4D)のマシンシリーズに変更すると、Pod が Pending / FailedScheduling のままになる:N4/N4A/N4D マシンはPersistent Disk をサポートしていません(Hyperdisk のみをサポートします)。そのため、pd-* StorageClass にバインドされた PVC は、これらのノードにバインドしたり、スケジュールしたりできません。イベントには通常、ボリュームのノードアフィニティまたはトポロジーの競合を伴う FailedScheduling が表示されます。

    • Gen4 ノードプールでは、ワークロードをHyperdisk StorageClass(例:type: hyperdisk-balanced)に切り替えます。
    • 既存の Persistent Disk ボリュームの場合は、データを Hyperdisk ボリュームに移行します。元の PD は Gen4 ノードにアタッチできません。
    • ワークロードで Persistent Disk を使い続ける必要がある場合は、ノード選択を使用して、PD 対応のマシンシリーズ(例:N2)で実行します。これはマシンタイプとディスクタイプの非互換性であり、容量の問題ではないため、ディスクサイズやクォータを増やしても解決しません。
  • コンピュートクラスが VM 世代間でフォールバックする場合(例:N4 を優先し、N2 にフォールバック)、または 1 つの StorageClass で複数世代に対応する必要がある場合に、Hyperdisk を使う Pod がスケジュール不能になる:StorageClass で指定した単一の静的ディスクタイプは、フォールバックリスト内のすべてのマシンシリーズと互換性があるわけではないため、Pod はフォールバック先のノードでボリュームをバインドできません。

    • ディスクタイプの自動選択を使用します。StorageClass の parameters.type に dynamic を設定し、hyperdisk-type、pd-type、disk-type-preference を指定するとともに、use-allowed-disk-topology: "true" を設定します。これにより、GKE はノードごとに互換性のあるディスクタイプを選択し、Pod をそのディスクタイプに対応するノードにのみスケジュールします。こうすると、1 つの動的 StorageClass で複数の VM 世代に対応できます(ドキュメントに記載されている GKE バージョンが必要です)。

      動的 StorageClass の例(GKE 1.35.3-gke.1290000+):

      apiVersion: storage.k8s.io/v1
      kind: StorageClass
      metadata:
        name: dynamic-volume
      provisioner: pd.csi.storage.gke.io
      volumeBindingMode: WaitForFirstConsumer
      allowVolumeExpansion: true
      parameters:
        type: dynamic
        pd-type: pd-balanced
        hyperdisk-type: hyperdisk-balanced
        # PD と Hyperdisk の両方をサポートするノードで優先するストレージ。
        # 省略した場合のデフォルトは hyperdisk-type です。
        disk-type-preference: hyperdisk-type
        # ベストプラクティス:ディスクタイプをサポートするノードにのみ Pod をスケジュールします。
        use-allowed-disk-topology: "true"
      
  • fsGroup の設定が原因でマウントが応答しなくなる:多数のファイルを含むボリュームに securityContext.fsGroup を設定した Pod では、kubelet がすべてのファイルの所有権を再帰的に変更するため、マウントがタイムアウトすることがあります。症状は次のとおりです。

    Unable to attach or mount volumes for pod; skipping pod ... timed out waiting for the condition
    

    Pod のログに Setting volume ownership for ... and fsGroup set というエントリーがあることを確認してから、次のいずれかを実施します。

    • ボリューム内のファイル数を減らします。
    • securityContext.fsGroupChangePolicy: OnRootMismatch を設定し、最上位の権限が一致しない場合にのみ所有権が変更されるようにします。
    • 不要であれば、fsGroup の設定を使用しないようにします。
ディスクのパフォーマンスとノードのストレージ圧迫
  • ディスクのパフォーマンスが低い(task dockerd:... blocked for more than 300 seconds、PLEG is not healthy、または低速な fs: disk usage スキャンなどの症状):ノードのブートディスクは、OS、コンテナイメージ、 オーバーレイファイルシステム、ディスクベースの emptyDir ボリュームで共有されており、 同じ種類のすべてのディスクでパフォーマンスが共有されます。

    • これは一般に、200 GB 未満の標準永続ディスクを使用するノードに影響します。 ディスクサイズを大きくするか、SSD に切り替えてください。特に本番環境では重要です。
    • emptyDir を頻繁に使用するワークロードがあるノードプールでは、 一時ストレージ用の Local SSD を有効にしてください。
  • ディスク操作の遅延による Pod 作成の失敗:影響を受けるノードバージョン(修正済みパッチリリースより前の GKE 1.18~1.23)では、 k8s_node container-runtime のログに failed to reserve container name ... is reserved for ... と表示されます(containerd issue #4604)。

    • PodSpec で restartPolicy: Always または OnFailure を指定し、 ブートディスクの IOPS を増やして緩和してください(ディスクを大きくするか、より高速なディスクタイプを使用します)。
    • 恒久的な修正は containerd 1.6.0 以降です。これが含まれる GKE バージョンにアップグレードしてください。
  • StoragePressureDetected(ノードのストレージ圧迫が高い):ノードの状態 StoragePressureRootFileSystem が True になります(例:Disk /dev/nvme0n1 usage 89% exceeds threshold 85%)。原因は、過剰な emptyDir への書き込み、大容量のイメージのプル、またはログの蓄積です。

    • 影響を受けるノードで df -h を実行して使用状況を確認します( /mnt/stateful_partition と一時マウントを重点的に確認してください)。
    • ブートディスクの大容量化、一時ストレージ用の Local SSD の追加、 適切な ephemeral-storage のリクエストと上限の設定、未使用のファイル/イメージ/ログの削除によって対処します。
ストレージのプロビジョニングと作成の失敗
  • The selected machine type ... has a fixed number of local SSD(s):EphemeralStorageLocalSsdConfig/ LocalNvmeSsdBlockConfig で指定された Local SSD の数が、マシンタイプに含まれる固定数と一致していません。

    • マシンタイプに一致する Local SSD の数を指定してください。 第 3 世代のマシンシリーズでは、Local SSD の count フラグを省略すると、 正しい値が自動的に設定されます。
  • Hyperdisk Storage Pools:クラスターまたはノードプールの作成が失敗する:ZONE_RESOURCE_POOL_EXHAUSTED(または同様の Compute Engine リソースエラー)が発生する場合、対象ゾーンに要求された Hyperdisk Balanced ディスクまたはマシンタイプの容量がありません。

    • 同じリージョン内で、容量があり、Hyperdisk Balanced Storage Pools を利用できる別のゾーンを選択してください。ストレージプールはゾーン単位であるため、新しいゾーンでプールを削除して再作成し、その後、そこでクラスター/ノードプールを作成してください。
ボリュームの拡張がコンテナに反映されない

ボリュームの拡張は、必ず PersistentVolumeClaim を通じて行う必要があります。 PersistentVolume を直接編集すると、コンテナのファイルシステムが以前のサイズのままになることがあります。

  1. 変更した PersistentVolume オブジェクトはそのままにしておきます。

  2. PersistentVolumeClaim を編集し、spec.resources.requests.storage に現在の PersistentVolume サイズより大きい値を設定します。

  3. kubelet が PV、PVC、コンテナのファイルシステムを自動的にリサイズします。Pod 内で次のコマンドを実行して確認してください。

    kubectl exec {pod_name} -n {workload_namespace} -- df -h
    
Cloud Storage FUSE のメモリ不足 (OOM) イベント

Pod が Cloud Storage FUSE CSI ドライバーに関連して高いメモリ使用量や OOM キルを経験する場合:

  1. Cloud Storage FUSE CSI ドライバーのサイドカーコンテナで Cloud Profiler を構成して、CPU/メモリのスナップショットを有効にします。

  2. Cloud Logging で OOM イベントを特定し、Pod でフィルタリングします:

    jsonPayload.involvedObject.name="{pod_name}"
    jsonPayload.involvedObject.kind="Pod"
    OOMKilled
    

    サイドカーマウンターまたは GCSFuse プロセスが OOM になった場合、Pod 名はワークロード Pod の名前です。ノードドライバーが OOM になった場合は gcsfusecsi-node-* です。

  3. Pod UID (jsonPayload.involvedObject.uid) とタイムスタンプを抽出し、OOM タイムスタンプの {pod_name}_{pod_uid} サービスバージョンを使用して、Cloud Profiler で一致するスナップショットを分析します。


ステップ 3: GitOps による修正案の提示

読み取り専用の診断境界を徹底します: kubectl edit、kubectl patch、または kubectl apply によるライブ変更を適用してはいけません。代わりに、修正された StorageClass、PersistentVolumeClaim、PodSpec (securityContext、restartPolicy)、またはノードプール構成を、ユーザーの GitOps パイプライン (たとえば、Config Sync、Argo CD、Flux) を通じて適用するためのレビュー可能なパッチとして提示します。

参考資料

コメント