dockershimからの移行
dockershimから他のコンテナランタイムに移行する際に知っておくべき情報を紹介します。
Kubernetes 1.20でdockershim deprecationが発表されてから、様々なワークロードやKubernetesインストールにどう影響するのかという質問が寄せられています。
この問題をよりよく理解するために、dockershimの削除に関するFAQブログが役に立つでしょう。
dockershimから代替のコンテナランタイムに移行することが推奨されます。
コンテナランタイムのセクションをチェックして、どのような選択肢があるかを確認してください。
問題が発生した場合は、必ず問題の報告をしてください。
そうすれば、問題が適時に修正され、クラスターがdockershimの削除に対応できるようになります。
1 - ノードのコンテナランタイムをDocker Engineからcontainerdに変更する
このタスクでは、コンテナランタイムをDockerからcontainerdに更新するために必要な手順について説明します。
これは、Kubernetes 1.23以前を使用しているクラスターオペレーターに適用されます。
また、dockershimからcontainerdへの移行を行う際の具体的なシナリオ例も含まれています。
代替のコンテナランタイムについては、このページを参照してください。
始める前に
備考: このセクションでは、Kubernetesが必要とする機能を提供するサードパーティープロジェクトにリンクしています。これらのプロジェクトはアルファベット順に記載されていて、Kubernetesプロジェクトの作者は責任を持ちません。このリストにプロジェクトを追加するには、変更を提出する前に
content guideをお読みください。
詳細はこちら。
containerdをインストールします。
詳細についてはcontainerdのインストールドキュメントを参照してください。
特定の前提条件については、containerdガイドを参照してください。
ノードのドレイン
kubectl drain <node-to-drain> --ignore-daemonsets
<node-to-drain>
は、ドレイン対象のノード名に置き換えてください。
Dockerデーモンの停止
systemctl stop kubelet
systemctl disable docker.service --now
containerdのインストール
containerdをインストールする手順の詳細については、ガイドを参照してください。
-
公式のDockerリポジトリからcontainerd.io
パッケージをインストールします。
各Linuxディストリビューション向けにDockerリポジトリを設定し、containerd.io
パッケージをインストールする手順については、Getting started with containerdを参照してください。
-
containerdを設定する:
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
-
containerdを再起動する:
sudo systemctl restart containerd
PowerShellセッションを開始し、$Version
に目的のバージョンを設定します(例: $Version="1.4.3"
)。
その後、次のコマンドを実行します:
-
containerdをダウンロードする:
curl.exe -L https://github.com/containerd/containerd/releases/download/v$Version/containerd-$Version-windows-amd64.tar.gz -o containerd-windows-amd64.tar.gz
tar.exe xvf .\containerd-windows-amd64.tar.gz
-
展開および設定:
Copy-Item -Path ".\bin\" -Destination "$Env:ProgramFiles\containerd" -Recurse -Force
cd $Env:ProgramFiles\containerd\
.\containerd.exe config default | Out-File config.toml -Encoding ascii
# 設定内容を確認します。セットアップによっては、以下を調整する必要があります:
# - sandbox_image(Kubernetesのpauseイメージ)
# - cniのbin_dirおよびconf_dirの場所
Get-Content config.toml
# (オプションだが、強く推奨される)containerdをWindows Defenderのスキャン対象から除外する
Add-MpPreference -ExclusionProcess "$Env:ProgramFiles\containerd\containerd.exe"
-
containerdを起動する:
.\containerd.exe --register-service
Start-Service containerd
containerdをコンテナランタイムとして使用するためのkubeletの設定
/var/lib/kubelet/kubeadm-flags.env
ファイルを編集し、フラグに--container-runtime-endpoint=unix:///run/containerd/containerd.sock
を追加して、containerdランタイムを指定します。
kubeadmを使用しているユーザーは、kubeadm
ツールが各ホストのCRIソケットを、そのホストのノードオブジェクトにアノテーションとして保存していることに注意してください。
これを変更するには、/etc/kubernetes/admin.conf
ファイルが存在するマシン上で次のコマンドを実行します。
kubectl edit no <node-name>
これによりテキストエディタが起動し、ノードオブジェクトを編集できます。
使用するテキストエディタを指定するには、KUBE_EDITOR
環境変数を設定してください。
-
kubeadm.alpha.kubernetes.io/cri-socket
の値を/var/run/dockershim.sock
から、使用したいCRIソケットのパス(例: unix:///run/containerd/containerd.sock
)に変更します。
新しいCRIソケットのパスは、原則としてunix://
で始める必要がある点に注意してください。
-
テキストエディタで変更を保存すると、ノードオブジェクトが更新されます。
kubeletの再起動
ノードが正常であることの確認
kubectl get nodes -o wide
を実行し、先ほど変更したノードのランタイムとしてcontainerdが表示されていることを確認します。
Docker Engineの削除
備考: このセクションでは、Kubernetesが必要とする機能を提供するサードパーティープロジェクトにリンクしています。これらのプロジェクトはアルファベット順に記載されていて、Kubernetesプロジェクトの作者は責任を持ちません。このリストにプロジェクトを追加するには、変更を提出する前に
content guideをお読みください。
詳細はこちら。
ノードが正常に見える場合は、Dockerを削除します。
sudo yum remove docker-ce docker-ce-cli
sudo apt-get purge docker-ce docker-ce-cli
sudo dnf remove docker-ce docker-ce-cli
sudo apt-get purge docker-ce docker-ce-cli
前述のコマンドは、ホスト上のイメージ、コンテナ、ボリューム、またはカスタマイズされた設定ファイルを削除しません。
これらを削除するには、DockerのDocker Engineのアンインストール手順に従ってください。
注意:
Docker Engineのアンインストール手順には、containerdを削除してしまうリスクがあります。コマンドの実行には十分注意してください。
ノードのuncordon
kubectl uncordon <node-to-uncordon>
<node-to-uncordon>
は、以前にドレインしたノードの名前に置き換えてください。
2 - ノードで使用されているコンテナランタイムの確認
このページでは、クラスター内のノードが使用しているコンテナランタイムを確認する手順を概説しています。
クラスターの実行方法によっては、ノード用のコンテナランタイムが事前に設定されている場合と、設定する必要がある場合があります。
マネージドKubernetesサービスを使用している場合、ノードに設定されているコンテナランタイムを確認するためのベンダー固有の方法があるかもしれません。
このページで説明する方法は、kubectl
の実行が許可されていればいつでも動作するはずです。
始める前に
kubectl
をインストールし、設定します。詳細はツールのインストールの項を参照してください。
ノードで使用されているコンテナランタイムの確認
ノードの情報を取得して表示するにはkubectl
を使用します:
kubectl get nodes -o wide
出力は以下のようなものです。列CONTAINER-RUNTIME
には、ランタイムとそのバージョンが出力されます。
# For dockershim
NAME STATUS VERSION CONTAINER-RUNTIME
node-1 Ready v1.16.15 docker://19.3.1
node-2 Ready v1.16.15 docker://19.3.1
node-3 Ready v1.16.15 docker://19.3.1
# For containerd
NAME STATUS VERSION CONTAINER-RUNTIME
node-1 Ready v1.19.6 containerd://1.4.1
node-2 Ready v1.19.6 containerd://1.4.1
node-3 Ready v1.19.6 containerd://1.4.1
コンテナランタイムについては、コンテナランタイムのページで詳細を確認することができます。
3 - dockershim削除の影響範囲を確認する
Kubernetesのdockershim
コンポーネントは、DockerをKubernetesのコンテナランタイムとして使用することを可能にします。
Kubernetesの組み込みコンポーネントであるdockershim
はリリースv1.24で削除されました。
このページでは、あなたのクラスターがどのようにDockerをコンテナランタイムとして使用しているか、使用中のdockershim
が果たす役割について詳しく説明し、dockershim
の削除によって影響を受けるワークロードがあるかどうかをチェックするためのステップを示します。
自分のアプリがDockerに依存しているかどうかの確認
アプリケーションコンテナの構築にDockerを使用している場合でも、これらのコンテナを任意のコンテナランタイム上で実行することができます。このようなDockerの使用は、コンテナランタイムとしてのDockerへの依存とはみなされません。
代替のコンテナランタイムが使用されている場合、Dockerコマンドを実行しても動作しないか、予期せぬ出力が得られる可能性があります。
このように、Dockerへの依存があるかどうかを調べることができます:
- 特権を持つPodがDockerコマンド(
docker ps
など)を実行したり、Dockerサービスを再起動したり(systemctl restart docker.service
などのコマンド)、Docker固有のファイル(/etc/docker/daemon.json
など)を変更しないことを確認すること。
- Dockerの設定ファイル(
/etc/docker/daemon.json
など)にプライベートレジストリやイメージミラーの設定がないか確認します。これらは通常、別のコンテナランタイムのために再設定する必要があります。
- Kubernetesインフラストラクチャーの外側のノードで実行される以下のようなスクリプトやアプリがDockerコマンドを実行しないことを確認します。
- トラブルシューティングのために人間がノードにSSHで接続
- ノードのスタートアップスクリプト
- ノードに直接インストールされた監視エージェントやセキュリティエージェント
- 上記のような特権的な操作を行うサードパーティツール。詳しくはMigrating telemetry and security agents from dockershim を参照してください。
- dockershimの動作に間接的な依存性がないことを確認します。
これはエッジケースであり、あなたのアプリケーションに影響を与える可能性は低いです。ツールによっては、Docker固有の動作に反応するように設定されている場合があります。例えば、特定のメトリクスでアラートを上げたり、トラブルシューティングの指示の一部として特定のログメッセージを検索したりします。そのようなツールを設定している場合、移行前にテストクラスターで動作をテストしてください。
Dockerへの依存について解説
コンテナランタイムとは、Kubernetes Podを構成するコンテナを実行できるソフトウェアです。
KubernetesはPodのオーケストレーションとスケジューリングを担当し、各ノードではkubeletがコンテナランタイムインターフェースを抽象化して使用するので、互換性があればどのコンテナランタイムでも使用することができます。
初期のリリースでは、Kubernetesは1つのコンテナランタイムと互換性を提供していました: Dockerです。
その後、Kubernetesプロジェクトの歴史の中で、クラスター運用者は追加のコンテナランタイムを採用することを希望しました。
CRIはこのような柔軟性を可能にするために設計され、kubeletはCRIのサポートを開始しました。
しかし、DockerはCRI仕様が考案される前から存在していたため、Kubernetesプロジェクトはアダプタコンポーネント「dockershim」を作成しました。
dockershimアダプターは、DockerがCRI互換ランタイムであるかのように、kubeletがDockerと対話することを可能にします。
Kubernetes Containerd integration goes GAブログ記事で紹介されています。

コンテナランタイムとしてContainerdに切り替えることで、中間マージンを排除することができます。
これまでと同じように、Containerdのようなコンテナランタイムですべてのコンテナを実行できます。
しかし今は、コンテナはコンテナランタイムで直接スケジュールするので、Dockerからは見えません。
そのため、これらのコンテナをチェックするために以前使っていたかもしれないDockerツールや派手なUIは、もはや利用できません。
docker ps
やdocker inspect
を使用してコンテナ情報を取得することはできません。
コンテナを一覧表示できないので、ログを取得したり、コンテナを停止したり、docker exec
を使用してコンテナ内で何かを実行したりすることもできません。
備考:
Kubernetes経由でワークロードを実行している場合、コンテナを停止する最善の方法は、コンテナランタイムを直接経由するよりもKubernetes APIを経由することです(このアドバイスはDockerだけでなく、すべてのコンテナランタイムに適用されます)。
この場合でも、イメージを取得したり、docker build
コマンドを使用してビルドすることは可能です。
しかし、Dockerによってビルドまたはプルされたイメージは、コンテナランタイムとKubernetesからは見えません。
Kubernetesで使用できるようにするには、何らかのレジストリにプッシュする必要がありました。
4 - dockershimからテレメトリーやセキュリティエージェントを移行する
Kubernetes 1.20でdockershimは非推奨になりました。
dockershimの削除に関するFAQから、ほとんどのアプリがコンテナをホストするランタイムに直接依存しないことは既にご存知かもしれません。
しかし、コンテナのメタデータやログ、メトリクスを収集するためにDockerに依存しているテレメトリーやセキュリティエージェントはまだ多く存在します。
この文書では、これらの依存関係を検出する方法と、これらのエージェントを汎用ツールまたは代替ランタイムに移行する方法に関するリンクを集約しています。
テレメトリーとセキュリティエージェント
Kubernetesクラスター上でエージェントを実行するには、いくつかの方法があります。エージェントはノード上で直接、またはDaemonSetとして実行することができます。
テレメトリーエージェントがDockerに依存する理由とは?
歴史的には、KubernetesはDockerの上に構築されていました。
Kubernetesはネットワークとスケジューリングを管理し、Dockerはコンテナをノードに配置して操作していました。
そのため、KubernetesからはPod名などのスケジューリング関連のメタデータを、Dockerからはコンテナの状態情報を取得することができます。
時が経つにつれ、コンテナを管理するためのランタイムも増えてきました。
また、多くのランタイムにまたがるコンテナ状態情報の抽出を一般化するプロジェクトやKubernetesの機能もあります。
いくつかのエージェントはDockerツールに関連しています。
エージェントはdocker ps
やdocker top
といったコマンドを実行し、コンテナやプロセスの一覧を表示します。
またはdocker logsを使えば、dockerログを購読することができます。
Dockerがコンテナランタイムとして非推奨になったため、これらのコマンドはもう使えません。
Dockerに依存するDaemonSetの特定
Podがノード上で動作しているdockerd
を呼び出したい場合、Podは以下のいずれかを行う必要があります。
例: COSイメージでは、DockerはそのUnixドメインソケットを/var/run/docker.sock
に公開します。
つまり、Pod仕様には/var/run/docker.sock
のhostPath
ボリュームマウントが含まれることになります。
以下は、Dockerソケットを直接マッピングしたマウントを持つPodを探すためのシェルスクリプトのサンプルです。
このスクリプトは、Podの名前空間と名前を出力します。
grep '/var/run/docker.sock'
を削除して、他のマウントを確認することもできます。
kubectl get pods --all-namespaces \
-o=jsonpath='{range .items[*]}{"\n"}{.metadata.namespace}{":\t"}{.metadata.name}{":\t"}{range .spec.volumes[*]}{.hostPath.path}{", "}{end}{end}' \
| sort \
| grep '/var/run/docker.sock'
備考:
Podがホスト上のDockerにアクセスするための代替方法があります。
例えば、フルパスの代わりに親ディレクトリ
/var/run
をマウントすることができます(
この例 のように)。
上記のスクリプトは、最も一般的な使用方法のみを検出します。
ノードエージェントからDockerの依存性を検出する
クラスターノードをカスタマイズし、セキュリティやテレメトリーのエージェントをノードに追加インストールする場合、エージェントのベンダーにDockerへの依存性があるかどうかを必ず確認してください。
テレメトリーとセキュリティエージェントのベンダー
様々なテレメトリーおよびセキュリティエージェントベンダーのための移行指示の作業中バージョンをGoogle docに保管しています。
dockershimからの移行に関する最新の手順については、各ベンダーにお問い合わせください。