Kubernetes1.20から始まったdocker非推奨化の影響について

昨年末にリリースされましたkubernetes1.20から、kubernetes上でのdockerが非推奨化となり、将来的に互換性機能が廃止になるという、衝撃的な情報が飛び込んできました。

しかしながら、一言で非推奨化/廃止といっても「どこまで」に影響するのかは言葉通りでは中々分かり得ないと思います。

本投稿ではkubernetes上の何が非推奨化/廃止となるのか、今後どのような影響があるのかを改めてご紹介したいと思います。

概要

kubernetes1.20から「Dockershim」が非推奨となり、2021年後半のリリースを目標としているkubernetes1.23では完全な廃止が計画されています。

この影響で、kubernetes1.20現在、別途CRIランタイムを導入せず、Dockerのみでkubernetesクラスタを構築している場合、クラスタログに警告が出るようになっています。
現状は警告が出るのみですが、kubernetes1.23以降はDockerのみでのkubernetesクラスタの構築は不可能となり、構築段階でCRIランタイムを導入が必要となります。

Dockershimとは?

Dockershimはkubernetes側の機能であり、kubernetesがDocker上のコンテナランタイムを使用するためのブリッジ機能です。
kubernetesクラスタを構築時にコンテナランタイムを別途導入せず、Dockerのみで構築した場合、kubernetesはこのブリッジ機能を使用して、Docker上のコンテナランタイムである「containerd」を使用し、コンテナを動作させます。

 



なぜ非推奨となるのか

Dockershimはメンテナンスコストが非常に高く、Dockershim自体、一時的な運用として位置づけられていました。
Dockershimを用いてkubernetesがDocker上のコンテナランタイムを使用すること自体、別ツール上の機能を間借りするような通信負荷が発生するため、あまり効率のいい方法ではありませんでした。

そのため、kubernetesに適応したコンテナランタイムが使用できた場合、DockershimにてkubernetesとDockerを連携し運用するよりも、コンテナランタイムの通信負荷、およびサーバ負荷は低くなります。


現在、kubernetesが使用できるコンテナランタイムも選択肢が増え、さらにkubernetesとコンテナランタイム間の通信規約も策定されたため、Dockershimに頼る必要が無くなり、非推奨、廃止が予定されることになりました。

コンテナランタイムの関係性

Dockershimが非推奨化/廃止となる影響を説明する前に、どういった部分に影響が出るのかを認識し易くするため、コンテナ動作におけるコンテナランタイムとランタイム間通信について解説したいと思います。

大分長い解説となるため、すでにご存じの方はスキップをお願いいたします。

コンテナランタイムについて

コンテナランタイムと一言で言っても、内部構造を紐解いた際、低レベルコンテナランタイムと高レベルコンテナランタイムの二つに分解されます。
どちらもコンテナを動作させる上で必要な機能となるため、それぞれ解説したいと思います。

低レベルコンテナランタイム(OCIランタイム)

実際にコンテナの作成削除を行う、コンテナ生成の中核部分を担っているランタイムを低レベルコンテナランタイム(Low level Runtime)と言います。


元々、Docker等のコンテナ管理ツール内のコンテナランタイムの一機能であり、現在のような低レベルと言う位置づけではなかったのですが、後述で説明するOCIにより、標準仕様が定められた結果、コンテナ生成部分を分割し、低レベルコンテナランタイムと位置づけられました。
そのため、低レベルコンテナランタイムはOCIランタイムと呼称されることがあります。

低レベルコンテナランタイムの種類

OCIにて策定した標準仕様によって、低レベルコンテナランタイムは現在、様々存在しています。

その内、代表的なランタイムをいくつかピックアップし、紹介したいと思います。

  • runc
    元々はdocker内のコンテナランタイムの一機能でしたが、docker社よりOCIに寄贈され、現在はdocker以外でも広く利用されている低レベルコンテナランタイムです。
    runcはOCIの標準仕様の準じた低レベルコンテナランタイムのリファレンスモデルとして開発され、Docker上で稼働してきた実績がある低レベルコンテナランタイムです。
    しかしながら、runcはすべてのコンテナが1つのカーネルを共有し動作したり、脆弱性が発見されたりとセキュリティ的に不安要素が残るランタイムであるとも言えます。

  • Kata Container
    OpenStack FoundationよりOCI標準仕様に従って開発された低レベルコンテナランタイムです。
    コンテナセキュリティに対応したランタイムであり、前述のruncのようなすべてのコンテナが1つのカーネルを共有するのではなく、コンテナ向けの軽量仮想化ハイパーバイザを使用し、それぞれ異なるカーネル上での動作を可能にしています。

  • gVisor
    GoogleよりOCI標準仕様に従って開発された低レベルコンテナランタイムです。
    こちらもセキュリティを意識したランタイムであり、gVisorそのものがコンテナ用のカーネルとして機能し、OS上のカーネルアクセスを必要最低限の形で制限します。
    runcは全て許可してしまいますが、gVisorはコンテナのOSカーネルへのアクセスを制限することでセキュリティを担保しています。

高レベルコンテナランタイム

kubernetesやdockerからの各種コマンドによる指示を、低レベルコンテナランタイムに連携する役割を担っているランタイムを高レベルコンテナランタイム(High level Runtime)と言います。


こちらもDocker等のコンテナ管理ツール内のコンテナランタイムの一機能でありましたが、OCIが標準仕様を定めたことにより、コンテナ管理機能として分割され、高レベルコンテナランタイムとして位置づけられました。
高レベルコンテナランタイムはコンテナイメージを管理する役割も担っており、どのレジストリからどのイメージを取得し管理するかなども実施しています。
後述で説明しますkubeletと高レベルコンテナランタイムの通信規約であるCRIを用いるため、CRIランタイムと呼称されることがあります。

高レベルコンテナランタイムの種類

高レベルコンテナランタイムも現在様々存在します。

その内、代表的なランタイムをいくつかピックアップし、紹介したいと思います。

  • containerd
    元々Docker内部で機能していたコンテナランタイムでしたが、標準的なランタイム実装を実現するためにDocker社よりCNCFに寄贈されました。
    dockershimを用いてkubernetesが利用してきたのがこのcontainerdで、dockerからの移行を考えた場合、containerdを利用するのが現実的ではないかと思います。
    CNCFのランドスケープ上ではGraduatedに位置づけているため、現行の高レベルコンテナランタイムでは最も安定しているのではないかと思います。
    containerdはデフォルトでは低レベルコンテナランタイムとしてruncを利用していますが、構築時の設定により、他の低レベルコンテナランタイムを使用することが可能です。

  • CRI-O
    kubernetesのコンテナランタイムとして軽量コンテナランタイムとしての位置づけの元、Redhat主導で開発されたランタイムです。
    CNCFのランドスケープ上ではincubatingであるため、まだCNCFのTOCに認定はされていません。
    kubernetesを非常に意識しており、kubernetesのメジャー、マイナーバージョンアップと連動して開発が行われており、kubernetes上で動作する高レベルコンテナランタイムとして安定性を高めた作りとなっています。
    こちらも低レベルコンテナランタイムとしてはデフォルトでruncを利用していますが、同じく構築時の設定により、他の低レベルコンテナランタイムに変更することが可能です。

  • rkt
    CoreOS社より開発されたコンテナランタイムで、立ち位置的には高レベルコンテナランタイムであると言えます。
    曖昧な言い回しになってしまいますが、rktは低レベルコンテナランタイムと高レベルコンテナランタイムを内包した作りとなっており、少しだけ毛色の違うランタイムであると言えます。
    最大の特徴はDockerコンテナ以外に、CoreOSコンテナが使用できる点にあると言え、DockerはCoreOS上のコンテナを稼働させられないのに対し、rktはどちらも対応できるというメリットがあります。

コンテナランタイム間の通信規約

kubeletやDockerから高レベルコンテナランタイム、高レベルコンテナランタイムから低レベルコンテナランタイムに通信を行う際、それぞれの区分にて通信規約が規定されています。
この規定に従うことで、開発企業や開発団体が異なるコンテナランタイム間であったとしても統一的な通信I/Fが確立されており、より拡張性のあるコンテナ環境を提供することが可能となっています。


上記それぞれの区分にて定義している内容が異なっており、kubeletから高レベルコンテナランタイムへの通信I/Fを規定したものがCRI、高レベルコンテナランタイムから低レベルコンテナランタイムへの通信I/Fの規定を行っているものがOCI内で規定されたOCI Runtime Specificationとなります。

OCI(Open Container Initiative)

OCIとは2015年6月にdocker社やcoreos社、その他複数の企業により設立されたコンテナのランタイムとイメージ関連のオープンな業界標準を作成するオープンソース団体で、現在はLinux Faundation傘下にいます。


2017年7月にOCIにて「OCI v1.0」が策定され、以下の項目に対する標準仕様が確立されました。

  • OCI Runtime Specification
    コンテナランタイムの標準仕様であり、2021年現在の主要なコンテナランタイムはこの標準仕様に準拠しています。
    Linux以外のwindowsやvirtualMachine上のコンテナの仕様についても定められており、ファイルシステムやNamespaceなどが定められています。

  • OCI Image Format Specification
    コンテナイメージの標準仕様であり、イメージのindexやマニフェスト、ファイルシステムレイアウトなどの仕様が定められています。

  • OCI Distribution Specification
    コンテナイメージの配布に際する標準仕様であり、レジストリでのプッシュ、プルの動作の仕様などが定められています。

上記仕様を準拠することにより、低レベルコンテナランタイムと高レベルコンテナランタイムとの間の通信インターフェイスが仕様に沿ったものとなり、どのような高レベルコンテナランタイムからでも低レベルコンテナランタイムを利用することが可能となっています。


OCIにて標準仕様を定めた後、Docker内のランタイムも前述のcontainerdとruncに機能分割されたため、現行のDockerは分割されたcontainerdとruncを使用しています。
Docker内でのcontainerdとruncの通信もOCIが定めた通信規約が使用されています。

CRI(container runtime interface)

CRIとは、kubernetesv1.5にてαリリースされたkubeletとコンテナランタイムとの通信I/Fを規定したものです。
CRIはあくまでkubernetesとコンテナランタイム間の通信規約であり、Docker等では用いられません。


CRIが規定される以前は各コンテナランタイムがkubeletと連携させようとした場合、コンテナランタイム開発側がkubeletの内部仕様を完全に理解しなければならず、kubernetesに適用させる際の参入障壁は高くなっていました。
CRIが規定されたことにより、各コンテナランタイムはkubeletとコンテナランタイムを繋ぐCRI pluginを構成することにより、kubeletの内部仕様を理解せずとも、kubeletとの通信を実装することが可能となりました。


このCRIが規定されたことにより、Dockershimが廃止されたとしても、問題なくkubernetesはコンテナランタイムと通信することが可能となったのです。

コンテナランタイム間通信の関係性

CRI、OCIを通じた高レベルコンテナランタイムと低レベルコンテナランタイムのランタイム間通信の関係性は以下の通りです。


kubeletと高レベルコンテナランタイムとの通信はCRIによる統一的な通信I/Fの規定によって通信が確立されています。

また、高レベルコンテナランタイムと低レベルコンテナランタイムとの通信はOCIによる統一的な通信I/Fの規定によって、通信が確立されています。
なお、各通信の制御はProtocol BuffersとgRPC APIを用い、それぞれプラグインを作成することで実現されています。

今後の影響

あくまで「コンテナを管理・動作させる機能」をDocker上の物を使用せず、他のコンテナランタイムを導入して使用するということに変わるだけであり、Dockerにて作成されたイメージやローカル上のDockerRegistyやDockerHub上のイメージ使用に影響はありません。
kubernetesがコンテナを動作させるためにDockerを使用することは無くなりますが、コンテナランタイムが専用の物に変更されるだけであるため、これまで通りの操作でコンテナ生成管理を行うことができます。


上記図のようにkubernetes 1.23まではDocker上のコンテナランタイムを利用するような構築ができましたが、Dockershimが廃止になるので、v1.23以降は必然的にCRIランタイムを導入し、kubernetesクラスタを構築することになります。

発生しうる影響

発生しうる影響としては

  1. 新規にkubernetesクラスタを構築する際、CRIランタイム、OCIランタイムのインストールと適用を念頭に置かないといけない
  2. kubernetesのバージョンをv1.23以降にアップグレードする際に、使用するランタイムを変更しなけらばならないため、kubeletの設定ファイルの変更が必要になる

等が考えられ、環境や案件の状況によっては適用対応が必要となります。


なお、これまで高レベルコンテナランタイムと低レベルコンテナランタイムの二つに分割し説明してきましたが、高レベルコンテナランタイム(CRIランタイム)のみインストールすれば、低レベルコンテナランタイムが付随するものや、それぞれインストールしなければならなかったり等、ランタイムごとに形式が異なる場合があります。

導入を進める場合、各ランタイムの形式も視野に入れる必要があるため、その点については注意が必要です。

各クラウドベンダの対応

各主流クラウドベンダkubernetesサービスであるEKS・AKS・GKEの対応状況を以下の表にまとめます。

各社共通して、最新バージョン等で対応しているため、過去のk8sバージョンを使用している場合、それぞれ適用対応が必要となります。

サービス名 対応状況 対応CRI 対応内容
EKS 条件付きで対応済み containerd 以下3つのどれかを対応することで適用可能
・EKS最適化されたAMIでにてWokerNodeを構築
・BottlerocketのAMIにてWokerNodeを構築
・カスタムAMIを作成し手動で適用させる
AKS 対応済み containerd kubernetes1.19以降のバージョンで構築されたクラスタの場合、デフォルトで適用
GKE 対応済み containerd GKEノードバージョンが1.19以降の場合、デフォルトで適用

後書き

今回はkubernetes1.20にて最もインパクトがあった更新であろう、Dockerの非推奨化についてどのような影響があるかを調べてみました。

文字だけ見ると影響が大きそうに見えたこの更新ですが、内部構造を理解してみれば、開発者側には全く影響はないことがご認識頂けたかと思います。

ですが、クラスタ管理者にとっては考えなければならない変更点ではあるため、今年半ばまでには対応、ないし変更計画を立て、v1.23がきたとしても焦らないように心がける必要があるかと思います。


本内容を説明するに辺り、非常に長い文章となってしまいましたが、ここまでお読みいただきありがとうございました!

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です