コンテナ ランタイムのトラブルシューティング


このドキュメントでは、Google Kubernetes Engine(GKE)ノードのコンテナ ランタイムで発生する可能性がある一般的な問題のトラブルシューティング手順について説明します。

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

containerd を使用する Windows ノードプールで単純なドライブ文字を含むマウントパスが失敗する

この問題は、containerd バージョン 1.6.6 以降で解決されています。

Windows Server ノードプールを実行している GKE クラスタでバージョン 1.6.6 より前の containerd ランタイムが使用されている場合、コンテナの起動時に次のようなエラーが発生することがあります。

failed to create containerd task : CreateComputeSystem : The parameter is incorrect : unknown

詳しくは、GitHub の問題 #6589 をご覧ください。

解決策

この問題を解決するには、ノードプールを containerd ランタイム バージョン 1.6.6 以降を使用する最新の GKE バージョンにアップグレードします。

containerd を使用する Windows ノードプールで、配列以外の事前エスケープ CMD または ENTRYPOINT コマンドラインを使用するコンテナ イメージが失敗する

この問題は、containerd バージョン 1.6 以降で解決されています。

Windows Server ノードプールを実行している GKE クラスタで containerd ランタイム 1.5.X が使用されている場合、コンテナの起動時に次のようなエラーが発生することがあります。

failed to start containerd task : hcs::System::CreateProcess : The system cannot find the file specified.: unknown

詳しくは、GitHub の問題 #5067GitHub の問題 #6300 をご覧ください。

解決策

この問題を解決するには、ノードプールを containerd ランタイム バージョン 1.6.6 以降を使用する最新の GKE バージョンにアップグレードします。

containerd を使用する Windows ノードプールで、存在しないパスまたは Linux に似たパス(スラッシュ)を含むコンテナ イメージ ボリュームが失敗する

この問題は、containerd バージョン 1.6 以降で解決されています。

Windows Server ノードプールを実行している GKE クラスタで containerd ランタイム 1.5.X が使用されている場合、コンテナの起動時に次のようなエラーが発生することがあります。

failed to generate spec: failed to stat "<volume_path>": CreateFile : The system cannot find the path specified.

詳しくは、GitHub の問題 #5671 をご覧ください。

解決策

この問題を解決するには、ノードプールを containerd ランタイム バージョン 1.6.x 以降を使用する最新の GKE バージョンにアップグレードします。

/etc/mtab: 該当するファイルまたはディレクトリがない

Docker コンテナ ランタイムはデフォルトではこのシンボリック リンクをコンテナ内に設定しますが、containerd ランタイムはこれを行いません。

詳しくは、GitHub の問題 #2419 をご覧ください。

解決策

この問題を解決するには、イメージのビルド中にシンボリック リンク /etc/mtab を手動で作成します。

ln -sf /proc/mounts /etc/mtab

イメージの pull エラー: ディレクトリが存在しない

影響を受ける GKE のバージョン: すべて

kaniko でイメージを作成すると、「ディレクトリがありません」というエラー メッセージが表示され、containerd で pull されないことがあります。このエラーは、イメージが特別な方法でビルドされると発生します(前のコマンドでディレクトリを削除し、次のコマンドでそのディレクトリに同じファイルを再作成した場合に発生します)。

次の Dockerfile の例には、この問題を示す npm が含まれています。

RUN npm cache clean --force
RUN npm install

詳しくは、GitHub の問題 #4659 をご覧ください。

解決策

この問題を解決するには、この問題の影響を受けない docker build を使用してイメージをビルドします。

docker build を使用できない場合は、コマンドを 1 つにまとめます。次の Dockerfile の例では、RUN npm cache clean --forceRUN npm install をまとめています。

RUN npm cache clean --force && npm install

一部のファイル システム指標がなく、指標の形式が異なる

影響を受ける GKE のバージョン: すべて

Kubernetes システム コンポーネントの指標に記載されているように、Kubelet の /metrics/cadvisor エンドポイントにより Prometheus の指標が提供されます。そのエンドポイントに依存する指標コレクタをインストールすると、次のような問題が発生することがあります。

  • Docker ノードの指標の形式は k8s_<container-name>_<pod-name>_<namespace>_<pod-uid>_<restart-count> ですが、containerd ノードの形式は <container-id> です。
  • 次のように、containerd ノードには一部のファイル システム指標がありません。

    container_fs_inodes_free
    container_fs_inodes_total
    container_fs_io_current
    container_fs_io_time_seconds_total
    container_fs_io_time_weighted_seconds_total
    container_fs_limit_bytes
    container_fs_read_seconds_total
    container_fs_reads_merged_total
    container_fs_sector_reads_total
    container_fs_sector_writes_total
    container_fs_usage_bytes
    container_fs_write_seconds_total
    container_fs_writes_merged_total
    

解決策

この問題は、cAdvisor をスタンドアロン DaemonSet として使用することで軽減できます。

  1. 名前パターンが vX.Y.Z-containerd-cri の最新の cAdvisor リリースv0.42.0-containerd-cri など)を探します。
  2. cAdvisor Kubernetes Daemonset の手順で DaemonSet を作成します。
  3. インストールされる指標コレクタを参照して、cAdvisor /metrics エンドポイントを使用します。これより、Prometheus コンテナの指標のフルセットが提供されます。

別の方法

  1. モニタリング ソリューションを、コンテナ指標のフルセットを提供する Cloud Monitoring に移行します。
  2. エンドポイントの /stats/summary を使用して Kubelet summary API から指標を収集します。

GKE Windows でコンテナ ランタイムを再起動した後、接続ベースのオペレーションが正しく機能しない

影響を受ける GKE のバージョン: 1.21~1.21.5-gke.1802、1.22~1.22.3-gke.700

containerd ランタイム(バージョン 1.5.4 と 1.5.7-gke.0)を使用する Windows Server ノードプールの GKE クラスタでは、コンテナ ランタイムが強制的に再起動されます。実行中の既存のコンテナにアタッチ オペレーションが行われると、問題が発生し、再度 I/O のバインドができなくなります。この問題によって API 呼び出しが失敗することはありませんが、データの送受信は行われません。たとえば、クラスタの API サーバーを経由する CLI や API のアタッチおよびロギング用のデータが該当します。

解決策

この問題を解決するには、新しい GKE リリースでパッチが適用されたコンテナ ランタイム バージョン(1.5.7-gke.1)にアップグレードします。

Pod に failed to allocate for range 0: no IP addresses available in range set エラー メッセージが表示される

影響を受ける GKE バージョン: 1.24.6-gke.1500 以前、1.23.14-gke.1800 以前、1.22.16-gke.2000 以前

containerd を使用するノードプールを実行している GKE クラスタは、IP リークの問題が発生し、ノード上のすべての Pod IP が使い果たされる可能性があります。影響を受けるノードでスケジュールされた Pod には、次のようなエラー メッセージが表示されます。

failed to allocate for range 0: no IP addresses available in range set: 10.48.131.1-10.48.131.62

この問題の詳細については、containerd の GitHub の問題 #5438GitHub の問題 #5768 をご覧ください。

GKE Dataplane V2 には、この問題をトリガーする可能性がある既知の問題があります。ただし、この問題は実行のスタックなど、他の原因によって発生することもあります。

解決策

この問題を解決するには、GKE Dataplane V2 の GKE Standard クラスタの回避策に記載されている回避策を行います。

プローブがタイムアウトを超過した場合の exec プローブの動作の違い

影響を受ける GKE のバージョン: すべて

containerd イメージに対する exec プローブの動作は、dockershim イメージに対する動作とは異なります。Pod に定義された exec プローブが、dockershim イメージで宣言された Kubernetes timeoutSeconds しきい値を超えると、プローブの失敗として処理されます。containerd イメージでは、宣言された timeoutSeconds しきい値の後に返されたプローブの結果は無視されます。

解決策

GKE では、フィーチャー ゲート ExecProbeTimeoutfalse に設定されており、変更できません。この問題を解決するには、影響を受けるすべての exec プローブの timeoutSeconds しきい値を増やすか、プローブ ロジックの一部としてタイムアウト機能を実装します。

限定公開レジストリに関する問題のトラブルシューティング

このセクションでは、containerd のプライベート レジストリ構成のトラブルシューティングについて説明します。

イメージの pull が失敗し、エラー x509: certificate signed by unknown authority が発生する

この問題は、GKE が特定の非公開レジストリ ドメインの証明書を見つけられなかった場合に発生します。このエラーは、次のクエリを使用して Cloud Logging で確認できます。

  1. Google Cloud コンソールの [ログ エクスプローラ] ページに移動します。

    [ログ エクスプローラ] に移動

  2. 次のクエリを実行します。

    ("Internal error pulling certificate" OR
    "Failed to get credentials from metadata server" OR
    "Failed to install certificate")
    

この問題を解決するには、次のことを試してください。

  1. GKE Standard で、次のパスにある構成ファイルを開きます。

    /etc/containerd/hosts.d/DOMAIN/config.toml
    

    DOMAIN は、レジストリの FQDN に置き換えます。

  2. 構成ファイルに正しい FQDN が含まれていることを確認します。

  3. 構成ファイルの secretURI フィールドにある証明書へのパスが正しいことを確認します。

  4. Secret Manager に証明書が存在することを確認します。

証明書が存在しない

この問題は、GKE が Secret Manager から証明書を pull してノードで containerd を構成できなかった場合に発生します。

この問題を解決するには、次のことを試してください。

  1. 影響を受けるノードで Container-Optimized OS が実行されていることを確認します。Ubuntu ノードと Windows ノードはサポートされていません。
  2. 構成ファイルで、secretURI フィールドのシークレットのパスが正しいことを確認します。
  3. クラスタの IAM サービス アカウントに、シークレットにアクセスするための正しい権限があることを確認します。
  4. クラスタに cloud-platform アクセス スコープがあることを確認します。手順については、アクセス スコープを確認するをご覧ください。

安全でないレジストリ オプションがローカル ネットワーク(10.0.0.0/8)に構成されていない

影響を受ける GKE のバージョン: すべて

containerd イメージでは、安全でないレジストリ オプションは、ローカル ネットワーク 10.0.0.0/8 に構成されていません。安全でない非公開レジストリを使用すると、次のようなエラーが発生することがあります。

pulling image: rpc error: code = Unknown desc = failed to pull and unpack image "IMAGE_NAME": failed to do request: Head "IMAGE_NAME": http: server gave HTTP response to HTTPS client

この問題を解決するには、次のことを試してください。

containerd 構成の変更権限がある DaemonSet を構成する

Standard クラスタの場合は、次の手順を試してください。特権コンテナはセキュリティ リスクであるため、この回避方法は Autopilot では使用できません。環境がインターネットに公開されている場合は、このソリューションをデプロイする前にリスク許容度を考慮します。いずれの場合も、限定公開レジストリに TLS を構成し、代わりに Secret Manager オプションを使用することを強くおすすめします。

  1. 次のマニフェストを確認します。

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: insecure-registries
      namespace: default
      labels:
        k8s-app: insecure-registries
    spec:
      selector:
        matchLabels:
          name: insecure-registries
      updateStrategy:
        type: RollingUpdate
      template:
        metadata:
          labels:
            name: insecure-registries
        spec:
          nodeSelector:
            cloud.google.com/gke-container-runtime: "containerd"
          hostPID: true
          containers:
            - name: startup-script
              image: registry.k8s.io/startup-script:v2
              imagePullPolicy: Always
              securityContext:
                privileged: true
              env:
              - name: ADDRESS
                value: "REGISTRY_ADDRESS"
              - name: STARTUP_SCRIPT
                value: |
                  set -o errexit
                  set -o pipefail
                  set -o nounset
    
                  if [[ -z "$ADDRESS" || "$ADDRESS" == "REGISTRY_ADDRESS" ]]; then
                    echo "Error: Environment variable ADDRESS is not set in containers.spec.env"
                    exit 1
                  fi
    
                  echo "Allowlisting insecure registries..."
                  containerd_config="/etc/containerd/config.toml"
                  hostpath=$(sed -nr 's;  config_path = "([-/a-z0-9_.]+)";\1;p' "$containerd_config")
                  if [[ -z "$hostpath" ]]; then
                    echo "Node uses CRI config model V1 (deprecated), adding mirror under $containerd_config..."
                    grep -qxF '[plugins."io.containerd.grpc.v1.cri".registry.mirrors."'$ADDRESS'"]' "$containerd_config" || \
                      echo -e '[plugins."io.containerd.grpc.v1.cri".registry.mirrors."'$ADDRESS'"]\n  endpoint = ["http://'$ADDRESS'"]' >> "$containerd_config"
                  else
                    host_config_dir="$hostpath/$ADDRESS"
                    host_config_file="$host_config_dir/hosts.toml"
                    echo "Node uses CRI config model V2, adding mirror under $host_config_file..."
                    if [[ ! -e "$host_config_file" ]]; then
                      mkdir -p "$host_config_dir"
                      echo -e "server = \"https://$ADDRESS\"\n" > "$host_config_file"
                    fi
                    echo -e "[host.\"http://$ADDRESS\"]\n  capabilities = [\"pull\", \"resolve\"]\n" >> "$host_config_file"
                  fi
                  echo "Reloading systemd management configuration"
                  systemctl daemon-reload
                  echo "Restarting containerd..."
                  systemctl restart containerd

    .spec.containers.env フィールドで、ADDRESS 変数の REGISTRY_ADDRESS 値を、ローカル HTTP レジストリのアドレス(DOMAIN_NAME:PORT の形式)に置き換えます。たとえば、次のようにします。

    containers:
    - name: startup-script
      ...
      env:
      - name: ADDRESS
        value: "example.com:5000"
    
  2. DaemonSet をデプロイします。

    kubectl apply -f insecure-registry-ds.yaml
    

DaemonSet は、安全でないレジストリをすべてのノードの containerd 構成に追加します。

containerd が特権 Pod のデバイス マッピングを無視する

影響を受ける GKE のバージョン: すべて

特権 Kubernetes Pod の場合、コンテナ ランタイムは、volumeDevices.devicePath から渡されたデバイス マッピングを無視し、ホスト上のすべてのデバイスを /dev 下のコンテナで使用可能にします。

ノードで I/O の負荷が高くなると containerd が shim プロセスをリークする

影響を受ける GKE のバージョン: 1.25.0~1.25.15-gke.1040000、1.26.0~1.26.10-gke.1030000、1.27.0~1.27.6-gke.1513000、1.28.0~1.28.3-gke.1061000

GKE ノードで I/O の負荷が高くなると、Pod の削除時に containerd が containerd-shim-runc-v2 プロセスの削除に失敗し、プロセスリークが発生する可能性があります。ノードでリークが発生すると、そのノード上の Pod 数よりも多くの containerd-shim-runc-v2 プロセスがノード上に表示されます。また、余分な PID だけでなく、メモリと CPU の使用量が増加する可能性があります。詳細については、GitHub の問題「IO 高負荷が原因で発生する shim のリークの修正」をご覧ください。

この問題を解決するには、次のバージョンにノードをアップグレードします。

  • 1.25.15-gke.1040000
  • 1.26.10-gke.1030000
  • 1.27.6-gke.1513000
  • 1.28.3-gke.1061000

containerd を実行している Pod で IPv6 アドレス ファミリーが有効になっている

影響を受ける GKE バージョン: 1.18、1.19、1.20.0~1.20.9

containerd で実行されている Pod では、IPv6 イメージ ファミリーが有効になっています。dockershim イメージではすべての Pod の IPv6 が無効になりますが、containerd イメージでは無効になりません。たとえば、localhost は最初に IPv6 アドレス ::1 に解決されます。通常、これは問題ではありませんが、場合によっては予期しない動作が発生する可能性があります。

解決策

この問題を解決するには、127.0.0.1 などの IPv4 アドレスを明示的に使用するか、Pod で実行されているアプリケーションを両方のアドレス ファミリーで動作するように構成します。

ノード自動プロビジョニングで Docker を含む Container-Optimized OS ノードプールのみがプロビジョニングされる

影響を受ける GKE バージョン: 1.18、1.19、1.20.0~1.20.6-gke.1800

ノードの自動プロビジョニングでは、サポートされている任意のイメージタイプを使用してノードプールの自動スケーリングを行うことができますが、Container-Optimized OS with Docker イメージタイプを使用して作成できるのは、新しいノードプールのみです。

解決策

この問題を解決するには、GKE クラスタをバージョン 1.20.6-gke.1800 以降にアップグレードします。これらの GKE バージョンでは、デフォルトのイメージタイプをクラスタに設定できます。

172.17/16 の IP アドレス範囲と競合する

影響を受ける GKE のバージョン: 1.18.0~1.18.14

172.17/16 IP アドレス範囲は、containerd が有効なノード VM の docker0 インターフェースが占有します。その範囲から送受信されたトラフィックは正しくルーティングされない可能性があります(たとえば、172.17/16 内の IP アドレスを持つ VPN 接続ホストには、Pod が接続できない可能性があります)。

GPU 指標が収集されない

影響を受ける GKE のバージョン: 1.18.0~1.18.18

1.18.18 より前の GKE バージョンでランタイムとして Containerd を使用している場合、GPU 使用状況の指標は収集されません。

解決策

この問題を解決するには、クラスタを GKE バージョン 1.18.18 以降にアップグレードします。

config.mediaTypeapplication/octet-stream に設定されているイメージは containerd で使用できません

影響を受ける GKE のバージョン: すべて

config.mediaType"application/octet-stream" に設定されているイメージは containerd で使用できません詳しくは、GitHub の問題 #4756 をご覧ください。これらのイメージは Open Container Initiative の仕様と互換性がなく、不適切とみなされます。これらのイメージは Docker と連携して下位互換性を提供しますが、containerd ではこれらのイメージはサポートされません。

症状と診断

ノードログのエラー例:

Error syncing pod <pod-uid> ("<pod-name>_<namespace>(<pod-uid>)"), skipping: failed to "StartContainer" for "<container-name>" with CreateContainerError: "failed to create containerd container: error unpacking image: failed to extract layer sha256:<some id>: failed to get reader from content store: content digest sha256:<some id>: not found"

通常、イメージ マニフェストはホストされているレジストリ内にあります。マニフェストを取得したら、config.mediaType を調べて、この問題が発生するかどうかを確認します。

"mediaType": "application/octet-stream",

解決策

containerd コミュニティでこのようなイメージをサポートしないことが決定されたため、containerd のすべてのバージョンがこの問題の影響を受けます。修正はまだありません。Docker バージョン 1.11 以降を使用してコンテナ イメージを再ビルドし、config.mediaType フィールドが "application/octet-stream" に設定されていないことを確認する必要があります。

CNI 構成が初期化されていない

影響を受ける GKE のバージョン: すべて

アップグレードやサイズ変更などの操作中に GKE がノードの作成に失敗します。

症状と診断

Google Cloud コンソールのエラーの例:

Error: "runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized".

このエラーは、次のような状況で発生する可能性があります。

  • ログファイルでノードのブートストラップ中に、GKE が CNI 構成をインストールしているとき。
  • DaemonSet コントローラ コマンドをインターセプトして Pod を作成するカスタム Webhook にエラーがある場合、Google Cloud コンソールのノードエラー ステータスとして。これにより、GKE は netd Pod または calico-node Pod を作成できなくなります。netd Pod または calico-node Pod が正常に起動してもエラーが解消されない場合は、サポートにお問い合わせください。

解決策

この問題を解決するには、次のことを試してください。

  • GKE が CNI 構成のインストールを完了するまで待ちます。
  • 正しく構成されていない Webhook を削除します。手順は次のとおりです。

    1. Webhook を一覧表示します。

          $ kubectl get mutatingwebhookconfigurations
          $ kubectl get validatingwebhookconfigurations
      
    2. 構成エラーのある Webhook を削除します。

          kubectl delete mutatingwebhookconfigurations WEBHOOK_NAME
          kubectl delete validatingwebhookconfigurations WEBHOOK_NAME
      

    WEBHOOK_NAME は、構成エラーがあり、削除する Webhook の名前に置き換えます。

  • システム Pod を無視するように Webhook を構成します。

次のステップ

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