containerd イメージ


このページでは、Containerd(cos_containerd)が含まれている Container-Optimized OSContainerd(ubuntu_containerd)が含まれている Ubuntu を Google Kubernetes Engine(GKE)ノード上で使用するための追加情報を説明します。cos_containerd および ubuntu_containerd イメージを使用すると、GKE クラスタで Containerd をコンテナ ランタイムとして使用できます。Autopilot クラスタの場合、cos_containerd のみがイメージタイプとしてサポートされます。

Containerd について

コンテナ ランタイムは、コンテナの実行と、Kubernetes のコンテナ管理の抽象化を行うソフトウェアです。コンテナにはいくつかの異なるランタイムが存在します。Containerd は業界標準のコンテナ ランタイムであり、Kubernetes によってサポートされ、他の多くのプロジェクトで使用されています。Containerd はレイヤ抽象化の機能を備え、Kubernetes 機能を拡張するための gVisor など、豊富な機能セットの実装を可能にします。Containerd は、Docker ランタイムと比較して、より効率的で安全なリソースとみなされます。

GKE クラスタでの Containerd イメージの使用

新しい GKE クラスタを作成する場合、既存のクラスタに新しいノードプールを作成する場合、または既存のクラスタをアップグレードする場合に、イメージタイプとして cos_containerd または ubuntu_containerd を選択できます。いずれの Containerd イメージにも GKE バージョン 1.14.3 以降が必要です。

ノードイメージの種類を確認する

既存のノードに使用されているイメージの種類を確認するには、Google Cloud Console、gcloud ツールまたは kubectl を使用します。また、このドキュメントの移行スクリプトのサンプルを確認し、すべてのノードプールに対して反復処理を行い、推奨されるノードプールの移行を出力します。

Console

  1. Cloud Console で、Google Kubernetes Engine のページに移動します。

    Google Kubernetes Engine に移動

  2. クラスタのリストで、確認するクラスタの名前をクリックします。

  3. [ノード] タブを選択します。

  4. [ノードプール] セクションで、[イメージの種類] 列の値を確認します。

gcloud

次のコマンドを実行します。CLUSTER_NAME はクラスタの名前に置き換えます。

gcloud container node-pools list \
    --cluster CLUSTER_NAME \
    --format="table(name,version,config.imageType)"

出力は次のようになります。

NAME          NODE_VERSION    IMAGE_TYPE
default-pool  1.19.6-gke.600  UBUNTU_CONTAINERD

詳細については、gcloud container node-pools list API ドキュメントをご覧ください。

kubectl

次の kubectl get nodes コマンドを実行します。

kubectl get nodes -o wide

出力は次のようになります。

# For Docker runtime
NAME         STATUS   VERSION             OS-IMAGE                             CONTAINER-RUNTIME
gke-node-1   Ready    v1.16.15-gke.6000   Container-Optimized OS from Google   docker://19.3.1
gke-node-2   Ready    v1.16.15-gke.6000   Container-Optimized OS from Google   docker://19.3.1
gke-node-3   Ready    v1.16.15-gke.6000   Container-Optimized OS from Google   docker://19.3.1
# For Containerd runtime
NAME         STATUS   VERSION           OS-IMAGE                             CONTAINER-RUNTIME
gke-node-1   Ready    v1.19.6-gke.600   Container-Optimized OS from Google   containerd://1.4.1
gke-node-2   Ready    v1.19.6-gke.600   Container-Optimized OS from Google   containerd://1.4.1
gke-node-3   Ready    v1.19.6-gke.600   Container-Optimized OS from Google   containerd://1.4.1

CONTAINER-RUNTIME がランタイムとそのバージョンを出力します。

Docker ランタイムから Containerd ランタイムへの移行

ほとんどのユーザー ワークロードは、コンテナ ランタイムに依存しません。コンテナ ランタイムは Pod 内でコンテナを実行するものであり、Docker ランタイムが実際に内部で Containerd を使用するため、どちらのランタイムも同じように動作します。

デベロッパー マシンで Docker を使用する場合や、クラスタ外部で実行され、イメージのビルドと push を行うビルド パイプラインの一部として Docker を使用する場合でも、それ自体は Docker ランタイムに依存しません(これらのアクションはクラスタの外部で発生するため)。

Docker に対して依存関係がある場合には、いくつかのケースが考えられます。たとえば、Docker コマンドを実行する特権 Pod の実行、Kubernetes インフラストラクチャ外のノードでのスクリプトの実行(ssh を使用した問題のトラブルシューティングなど)、同様の権限が付与されているサードパーティ製ツールの使用などです。また、モニタリング ツール内の Docker 固有のログメッセージに応答するように一部のツールが構成されている場合、Docker に間接的な依存関係が存在することがあります。

Docker ランタイムに存在する可能性のある依存関係については、dockershim からの移行をご覧ください。Containerd との互換性を確認するには、クラスタにデプロイするロギングとモニタリング、セキュリティ、継続的インテグレーション ツールを提供しているベンダーに相談することもできます。

まず、Containerd を使用してテスト ノードプールにワークロードをデプロイし、すべてが想定どおりに実行されることを確認するようおすすめします。カナリア クラスタまたはステージング クラスタがある場合は、最初に移行することをおすすめします。異なるマシンタイプへのワークロードの移行で説明されているアプローチを使用して、ノードを段階的に移行することもできます。

ノードイメージの更新

ノードプールを更新して別のイメージを設定することで、Docker ランタイム イメージから Containerd イメージにノードを移行できます。この移行は、Google Cloud Console または gcloud ツールを使用して行うことが可能です。

Console

  1. Cloud Console で、Google Kubernetes Engine のページに移動します。

    Google Kubernetes Engine に移動

  2. 変更するクラスタの名前をクリックします。

  3. [クラスタの詳細] ページで [ノード] タブをクリックします。

  4. [ノードプール] で、変更するノードプールの名前をクリックします。

  5. [ノードプールの詳細] ページで、[ 編集] をクリックします。

  6. [ノード] セクションの [イメージの種類] で、[変更] をクリックします。

  7. オペレーティング システム用の Containerd イメージ バリアントの 1 つを選択します。

  8. [変更] をクリックします。

gcloud

gcloud ツールでノードプールを更新するには、gcloud container clusters upgrade コマンドを使用して --image-type パラメータを指定します。

たとえば、Containerd を使用してノードプールのイメージを Container-Optimized OS に変更するには、次のコマンドを実行します。

gcloud container clusters upgrade CLUSTER_NAME --image-type COS_CONTAINERD \
    --node-pool POOL_NAME

ノードイメージを更新した後で問題があり、Docker イメージ バリアントに戻す必要がある場合は、同じコマンドを使用して、Docker イメージ バリアントを選択します。

詳細については、gcloud container clusters upgrade API ドキュメントをご覧ください。

Containerd ノードで Docker コマンドを実行する

Docker バイナリは現在 Containerd ノードで使用できますが、Containerd への移行後には使用しないことをおすすめします。Docker では、Kubernetes が Containerd ノードで実行するコンテナを管理しません。このため、Docker コマンドや Docker API を使用して、実行中の Kubernetes コンテナの表示や操作を行うことはできません。

Containerd ノードのコンテナで発生した問題のトラブルシューティング

ノードでのデバッグやトラブルシューティングのため、Kubernetes コンテナ ランタイム用にビルドされたポータブル コマンドライン ツール crictl を使用して、Containerd と対話できます。crictl は、コンテナやイメージの表示、ログの読み取り、コンテナでのコマンドの実行などの一般的な機能をサポートします。サポートされている全機能と使用方法については、crictl ユーザーガイドをご覧ください。

権限のある Pod から Docker Engine にアクセスする

現在、権限のある Pod 内からノード上の Docker Engine にアクセスしているユーザーが一部存在します。そのため、ユーザーが Docker に直接依存することがないようにお客様のワークロードを更新することをおすすめします。たとえば、現在 Docker Engine からアプリケーション ログやモニタリング データを抽出している場合は、代わりに GKE システムのアドオンを利用してロギングやモニタリングを行うことをご検討ください。

イメージをビルドする

Containerd はイメージのビルドをサポートしていません。Kubernetes 自体がこの機能に対応していないからです。

Kubernetes は自身のスコープ外のローカル プロセスで使用されるシステム リソースを認識しないので、Kubernetes コントロール プレーンはリソースを割り当てる際にそれらのプロセスを考慮することができません。その結果、リソース関係の GKE ワークロードが枯渇する可能性があります。また、ノードが不安定になる可能性もあります。こうした理由から、ローカルノード上でコマンドを実行することはおすすめしません。このようなタスクを実施する場合は、個々のコンテナのスコープ外でその他のサービス(Cloud Build など)を利用するか kaniko などのツールを使用して Kubernetes ワークロードの形でイメージをビルドすることをご検討ください。

これらの推奨事項を採用できない場合は、このリスクをご理解のうえ、Docker によるイメージのビルドを進めてください。GKE クラスタでイメージを使用する場合は、その前にイメージをレジストリに push する必要があります。Kubernetes はローカルでビルドされたイメージを認識しないからです。

既知の問題

GKE バージョン 1.19 以降には報告されている問題はありません。

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

ノード自動プロビジョニングでは、サポートされている任意のイメージタイプを持つノードプールの自動スケーリングが可能ですが、新しく作成できるのは、Docker を含む Container-Optimized OS というイメージタイプを持つノードプールだけです。

172.17/16 範囲との競合

影響を受ける GKE のバージョン: 1.14、1.15、1.16、1.17.0 ~ 1.17.17-gke.2800、1.18.0 ~ 1.18.14

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

56 個を超えるレイヤがある画像は Containerd では使用できない

影響を受ける GKE のバージョン: 1.14、1.15、1.16、1.17

画像のレイヤが 56 個を超える場合は、画像をダウンロードできません。次のエラーが発生します。

info.Labels: label key and value greater than maximum size (4096 bytes), key: containerd: invalid argument

詳細については、https://github.com/containerd/containerd/issues/4684 をご覧ください。

この問題は Containerd 1.4.2 で修正されています。Container-Optimized OS 85 にはこの修正が含まれています

GPU 指標が収集されない

影響を受ける GKE のバージョン: 1.14、1.15、1.16、1.17、1.18

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

画像指標にラベルがない

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

画像指標 container_fs_usage_bytescontainer_tasks_state には、imagecontainer_name、名前 namespace などのラベルは表示されません。

Volume が noexec オプションによってマウントされる

影響を受ける GKE のバージョン: 1.14、1.15.0 ~ 1.15.12-gke.17、1.16.0 ~ 1.16.13-gke.400

/var/lib/containerd にマウントされた Volume は、no-exec オプションを指定してマウントされます。これにより、Volume の実行可能ファイルの実行が拒否されます。

Containerd におけるファイル記述子のリーク

影響を受ける GKE のバージョン: 1.14、1.15、1.16、1.17.0~1.17.12

Containerd には、v1.3.0 以降で eventfd リークに関する既知の問題が存在していましたが、v1.3.3 で修正されました。詳細については、https://github.com/containerd/containerd/issues/3949 をご覧ください。

移行スクリプトのサンプル

次のサンプル スクリプトは、使用可能なプロジェクトのすべてのノードプールに対して反復処理を行い、ノードプールごとに、ノードプールを Containerd に移行する必要があるかどうかの提案を出力します。また、このスクリプトは、ノードイメージの更新セクションに記載されているノードプールのバージョンと推奨される移行コマンドも出力します。ノードプール バージョンの既知の問題を確認してください。

スクリプト例: すべてのノードプールを反復処理して Containerd の移行を行う

for project in  $(gcloud projects list --format="value(projectId)")
do
  echo "ProjectId:  $project"
  for clusters in $( \
    gcloud container clusters list \
      --project $project \
      --format="csv[no-heading](name,location,autopilot.enabled)")
  do
    IFS=',' read -r -a clustersArray <<< "$clusters"
    cluster_name="${clustersArray[0]}"
    cluster_zone="${clustersArray[1]}"
    cluster_isAutopilot="${clustersArray[2]}"

    if [ "$cluster_isAutopilot" = "True" ]; then
      echo "  Cluster: $cluster_name (autopilot) (zone: $cluster_zone)"
      echo "    Autopilot clusters are running Containerd."
    else
      echo "  Cluster: $cluster_name (zone: $cluster_zone)"
      for nodepools in $( \
        gcloud container node-pools list \
          --project $project \
          --cluster $cluster_name \
          --zone $cluster_zone \
          --format="csv[no-heading](name,version,config.imageType)")
      do
        IFS=',' read -r -a nodepoolsArray <<< "$nodepools"
        nodepool_name="${nodepoolsArray[0]}"
        nodepool_version="${nodepoolsArray[1]}"
        nodepool_imageType="${nodepoolsArray[2]}"

        nodepool_minorVersion=${nodepool_version:0:4}

        echo "    Nodepool: $nodepool_name, version: $nodepool_version ($nodepool_minorVersion), image: $nodepool_imageType"

        suggestedImageType="COS_CONTAINERD"

        if [ "$nodepool_imageType" = "UBUNTU" ]; then
          suggestedImageType="UBUNTU_CONTAINERD"
        fi

        tab=$'\n      ';
        nodepool_message="$tab Please update the nodepool to use Containerd."
        nodepool_message+="$tab Make sure to consult with the list of known issues https://cloud.google.com/kubernetes-engine/docs/concepts/using-containerd#known_issues."
        nodepool_message+="$tab Run the following command to upgrade:"
        nodepool_message+="$tab "
        nodepool_message+="$tab gcloud container clusters upgrade '$cluster_name' --project '$project' --zone '$cluster_zone' --image-type '$suggestedImageType' --node-pool '$nodepool_name'"
        nodepool_message+="$tab "

        # see https://cloud.google.com/kubernetes-engine/docs/concepts/node-images
        if [ "$nodepool_imageType" = "COS_CONTAINERD" ] || [ "$nodepool_imageType" = "UBUNTU_CONTAINERD" ]; then
          nodepool_message="$tab Nodepool is using Containerd already"
        elif [ "$nodepool_imageType" = "WINDOWS_LTSC" ] || [ "$nodepool_imageType" = "WINDOWS_SAC" ]; then
          nodepool_message="$tab Containerd is not currently available for Windows nodepools"
        elif [ "$nodepool_minorVersion" \< "1.14" ]; then
          nodepool_message="$tab Upgrade nodepool to the version that supports Containerd"
        fi
        echo "$nodepool_message"
      done
    fi # not autopilot
  done
done

# Sample output:
#
# ProjectId:  my-project-id
#  Cluster: autopilot-cluster-1 (autopilot) (zone: us-central1)
#    Autopilot clusters are running Containerd.
#  Cluster: cluster-1 (zone: us-central1-c)
#    Nodepool: default-pool, version: 1.18.12-gke.1210 (1.18), image: COS
#
#       Please update the nodepool to use Containerd.
#       Make sure to consult with the list of known issues https://cloud.google.com/kubernetes-engine/docs/concepts/using-containerd#known_issues.
#       Run the following command to upgrade:
#
#       gcloud container clusters upgrade 'cluster-1' --project 'my-project-id' --zone 'us-central1-c' --image-type 'COS_CONTAINERD' --node-pool 'default-pool'
#
#    Nodepool: pool-1, version: 1.18.12-gke.1210 (1.18), image: COS
#
#       Please update the nodepool to use Containerd.
#       Make sure to consult with the list of known issues https://cloud.google.com/kubernetes-engine/docs/concepts/using-containerd#known_issues.
#       Run the following command to upgrade:
#
#       gcloud container clusters upgrade 'cluster-1' --project 'my-project-id' --zone 'us-central1-c' --image-type 'COS_CONTAINERD' --node-pool 'pool-1'
#
#  Cluster: another-test-cluster (zone: us-central1-c)
#    Nodepool: default-pool, version: 1.20.4-gke.400 (1.20), image: COS_CONTAINERD
#
#      Nodepool is using Containerd already
#

次のステップ