65
47

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

コンテナランタイム事情を整理してみる

Last updated at Posted at 2020-12-20

この記事を書いたきっかけ

最近は商用環境でも利用の進んでいるContainerですが, 最近は「Kubernetesがv1.20でDockerを非推奨とした」という文言が一人歩きして(思わず)話題になりました.

(上記ニュースを知らない方は, 落ち着いて この記事 を読んでください. Dockerは非推奨ではありません.)

公式ブログ

上記ニュースはContainer Runtime周りについての知識の有無でかなり反応が分かれたように見受けられました.

そこでこの記事ではContainer Runtimeについてできるだけ広範に動向・事情をまとめてみます.

なおこの記事ではLinux上のContainerのみ取り扱います.

また, この記事内容は参考文献の内容を整理しただけのものになります. 実際に使用したりソースコードを読んで確認しているわけではありません.

Container Runtimeに関する概念

  1. Container Runtime

    広義には, Container image名やContainer実行に関する各種設定情報を受け取ってContainerを作成・実行・停止・削除するソフトウェア全体を指します.

    狭義には, 広義のContainer Runtimeのコンポーネントのことを指す場合もあります.

    この場合は, 後述する通り, コンテナ実行・停止を責務とするLow level Container RuntimeとContainer imageの管理を責務とするHigh level Container Runtimeに分ける場合もあります.

    また, 外部からコンテナ起動・終了をネットワークやソケット経由で受け付ける, 常駐サービス型と, 利用時に起動されるコマンド型があります.
    (「常駐サービス型」「コマンド型」は本記事での独自の呼び方です)

    ただしすべてのContainer Runtimeが上記のような分類に合致するとは限りません.

  2. Low level Container Runtime

    Containerの実行を責務とするコンポーネントです. Containerの隔離に関するすべてに責任があります.
    コンテナ使用についてOCI Runtime SpecificationなどContainer実行に関する標準に従うものが多く, 今回取り上げるものはすべてコマンド型Runtimeになります.

    代表例がOCIの所有する runc.

  3. High level Container Runtime

    Container imageの管理とLow level Runtimeの呼び出しを責務とするコンポーネントです.

    Container imageの管理としてimageの作成や外部Registryへの保存も行えるものと, 外部のRegistryから取得するのみでそれ自体ではimageを作成できないものもあります.

    Container実行についてLow level Runtimeのインターフェースに依存しますが, 最近では標準仕様であるOCI Runtime Spec.に準拠するものが一般的です.

    High level Runtimeはコンテナ実行の管理自動化やオーケストレーションツールとの連携のために常駐サービス型の実装が多いです. 今回紹介する中で例外はPodmanとなります. High level Runtimeのインターフェースを標準化するKubernetesプロジェクトによるContainer Runtime Interface仕様も常駐サービス型であることを前提としています.

    代表例はCNCFが所有するcontainerd.

Container Runtime

Low level Runtime

runc

OCI Logo

現在はOCIに寄贈され, 最も標準的なOCI準拠Low level Runtimeです.

元々はDockerの内部コンポーネントでしたがOCI設立とContainerフォーマットの標準化の中でDocker社から寄贈されました.

Container内のプロセスを直接ホストカーネル上で実行する設計となっており, Container起動が軽量だとされています. 一方で、セキュリティ目的のプロセス隔離の仕組みとしては隔離性が不十分という見方もあります.

crun

C言語で書かれたOCI Runtime. Go言語とLow level Runtimeのようなソフトウェアは相性が良くないとして, C言語でより効率のよいRuntime実装を目指しています.

リポジトリのREADME.mdでも利用PID数やメモリ使用率でruncとの比較が掲載されています.

runsc(gVisor)

gVisor Logo

Googleが開発する, 軽量なユーザ空間カーネル上でコンテナプロセスを実行するLow level Runtimeです.

アプリケーションのシステムコールを, 独自に開発したユーザ空間カーネル(Sentry, Gofer)を経由して行うことで信頼できないContainer imageを実行する際のContainer内からホストへの攻撃領域(Attack Surface)を減らすことを目的としています.

背景としては, GKEのようなマネージドKubernetesサービスを提供するにあたって, ユーザが稼働するContainer imageのセキュリティを確保することの難しさがあると思われます.

システムコール数について, 2018年の資料によると"50種程度"とされていますが, GitHubの本稿執筆時点のコミットでは, リンク先の配列の要素が59要素あって60種近くなっています. (内容は精査していないので参考程度です)

一般にはこのあと出てくるVMによる隔離やunikernelによる隔離に比べると隔離レベルは低いと考えられていますが, VM隔離と比較するとパフォーマンスが, unikernelと比較すると既存コンテナイメージがそのまま使える点が, それぞれ利点といえます.

一方で, 一部のシステムコールは実装されていないので, アプリケーションが必要としているシステムコールが実装されていない場合はアプリケーションが機能しません. 公式ページでよく使われるアプリケーションに関するテスト結果を公開されています.

また, 「既存のものを危険だというのはFUDしているのでは?」という批判1もありました. ただ批判の中でも触れられている通り, gVisor自体が問題なのではなく, gVisor発表当初の「通常のContainer(おそらくruncによるもの)は危険」という説明がマーケティング上はFUDにあたるのでは, ということです. 実際, ホストとの隔離レベルを向上する方法はKataContainerによる仮想化技術の利用や, SELinux / seccomp / AppArmor などの既存のセキュリティ技術を用いる方法もあります. gVisorだけではなくほかのContainer runtimeも同様ですが, セキュリティを目的に導入する場合は導入する際のトレードオフについてよく検討し, プロジェクトの求めるセキュリティレベルやトレードオフが受け入れ可能か総合的に判断する必要があります.

runnc(Nabla Containers)

Nabla Container Logo

unikernel技術を用いてContainerとホストの隔離レベルの向上を狙ったLow level Runtimeです.

unikernelについて詳しくは立ち入りませんが, 基本的なアイディアは汎用OSを使用せずにアプリケーションとOS機能を静的にリンクしてOS部分も含めたマシンイメージ全体を最適化することです.

このunikernel向けに既存アプリケーションをportingし, unikernalアプリケーション用のsandboxをContainerとして稼働することでsandboxからのシステムコールを限定することができ, 結果としてContainerとホストの隔離レベルを向上することができます.

システムコール数について, gVisorと同じく2018年の資料によると7種類と述べられており, 公式サイトにも

A containerized application can avoid making a Linux system call if it links to a library OS component that implements the system call functionality. Nabla containers use library OS (aka unikernel) techniques, specifically those from the Solo5 project, to avoid system calls and thereby reduce the attack surface. Nabla containers only use 7 system calls; all others are blocked via a Linux seccomp policy.

と書かれています. (強調追加は筆者)

このRuntimeでアプリケーションを稼働させるにはアプリケーションを専用の環境で再コンパイルする必要があり, その意味で既存Container imageはそのままでは動きません. (OCI標準とは別のレベルの問題だと思われます)

仮想マシンによる隔離に比べて軽量・高速な起動が期待できますが, イメージの再作成など手間がかかることが難点です.

kata-runtime(Kata Containers)

Kata Containers Logo

VMハイパーバイザーと連携してContainer起動時にVMを起動してその中でContainerを実行することで, Containerとホストの隔離レベルをVMと同様のレベルとするLow level Runtime.

intel主導のClear ContainersプロジェクトとCaaSを提供していたhyper社(?)のhyper.shプロジェクトが合流してできたプロジェクトで, パフォーマンス(Clear Containersが注力)と複数ハイパーバイザーへの対応(hyper.shが注力)の両方を取り込んでいるとされる.

2018年のベンチマークではVMが起動されるフェーズであるPodの起動とContainerの停止でruncより時間がかかるようです.

High level Runtime

containerd

containerd Logo

もともとDocker社が開発していたHigh level Runtime.

CNCFに寄贈され独立したプロジェクトとして扱われると同時に, mobyプロジェクト内で開発が継続されています.

常駐サービス型のContainer Runtimeであり, CRIに対応するプラグインを内包しているためdockerdを介さずにCRI互換Runtimeとして利用可能です.

また, Low level RuntimeとしてOCI互換なRuntimeを使用可能です. ほとんどのLow level Runtimeの使用方法のドキュメント(Getting Startedなど)でcontainerdを使用する方法が案内されています.

Dockerも現在でも裏側でcontainerdを使っているため、実際はほとんどの利用者が利用しているのではないでしょうか.

CRIよりも豊富な機能を呼び出すためのCLIとしてctrコマンドが用意されており, dockerなしでの利用も可能です.

cri-o

cri-o Logo

containerdが, その開発経緯からCRIには不要な機能も備えていることから, CRIの実装を中心において, それ以外の機能を含まない最小限なHigh level Runtimeとして開発されています.

containerdと同じく呼び出し元はCRIに対応し, 呼び出し先はOCI互換となっています.

containerdがdockerの様々な機能をサポートするため多機能なのに対して, サポートする機能をCRIに絞っているので軽量な代替Runtimeになっている, とされます.

Container稼働時に一つのContainerごとにconmon(container monitoring)と呼ばれるプロセスでContainerを監視する(logのハンドリングや終了コードの保存など)など, Containerの実行方法でもcontainerd(docker)との違いはあります.

podman

podman Logo

珍しいコマンド型のHigh level Runtimeです.

常駐サービスプロセスを作らず, コマンド実行プロセスによって処理を行います. それでもOCI互換Container imageの取得や管理を行ってOCI Runtime specに従ってLow level Runtimeを呼び出すことでコンテナを管理するため, High level Runtimeに分類しています.

Container開発ツールとしてのdockerコマンドの代替を目指しており, alias docker=podman とするだけで移行できる(CLIインターフェースレベルで互換性がある)ことが一つの特徴です.

コマンド型High level Runtimeのため, 常駐サービス型Runtimeとのインターフェース仕様である CRIは実装していません.

その他

docker (dockerd)

docker Logo

「ContainerといえばDocker」といって過言でないDocker社の製品.

Container実行やContainer imageの管理はrunc/containerdを用いる.

dockerd自体はDockerfileの解釈やvolume/networkなどのリソース管理を担当している. swarm modeなどを使うとContainer runtimeというよりもContainer orchestratorの性格が強くみえる.

デファクトスタンダードだけに様々な立場から問題点を指摘されることがありますが, 徐々に解消されつつあります. 最近では(といってももう2019年の話ですが)dockerd自体をユーザ権限で実行することができるようになるなどかなり基本的な部分についても改善がなされている.

dockerd自体はCRI互換ではありませんが, これまではCRIをdockerd向けに翻訳するdockershimコンポーネントを(歴史的経緯から)Kubernetesコミュニティがメンテナンスし, kubeletに組み込んできました. KubernetesコミュニティはCRI互換High level Runtimeがすでに十分あることやcontainerd自身がCRIを実装していることなどからdockershimをKubernetes v1.23で削除すること, それに向けてv1.20にてdockershimの利用を非推奨とすることにしました. この経緯からわかるように, Container開発のためにdockerを用いることは非推奨になっておらず, ほとんどの開発者にとってのDockerは引き続き利用できます. また, Docker社とMirantis社(Docker社からDocker Enterprise事業を2019年11月に買収した)はdockershimに相当するコンポーネントを開発・サポートしていくと発表しています.

rkt

rkt Logo

rkt2はかなり早い時期3から開発された, Dockerとは非互換のContainerフォーマットを用いるコンテナランタイムです. 2018年4月16日の v1.30.0 リリースを最後にリリースは止まっており, 2020年2月24日にGitHub上でEnd of projectが宣言されました. もはやKubernetesなどほとんどのContainer orchestratorでサポートされていませんが, 現在のContainer周辺に大きく影響する取り組みが行われていた, 重要なプロジェクトだと考えるので紹介します.

rktのContainer仕様をもとにApp ContainerとしてContainerフォーマットの標準化をOCIに先行して4行っていました. 結局OCIへ合流したためv1.0.0には到達しませんでした.

また, rktではContainer imageへの署名と検証をデフォルトで実施するようになっておりSecure-by-defaultになっています.

rktは常駐サービスなしにコマンド型で動作する点も特徴です(現在のpodmanに似た動作). なおKubernetesと連携する場合はCRIを実装したrktletというサービスが常駐して必要に応じてrktを呼び出していました.

そのほかのContainer runtimeとの比較も公式サイトに掲載されています.

Firecracker

Firecracker Logo

公式サイトでも

Firecracker is a virtual machine monitor (VMM) that uses the Linux Kernel-based Virtual Machine (KVM) to create and manage microVMs.

と書かれているように, Firefracker自体は単なるContainer runtimeとして分類しがたいのでここで紹介します. (つまるところ, 筆者がよく知らない)

FirecrackerはAmazon Web ServiceがAWS LambdaやAWS Fargateなどを提供するために使用しているとされます.

Kata Container(kata-runtime)のハイパーバイザーとして動作することも可能な一方, kata-runtimeの代わりにfirecracker-containerdを用いて動作することもできます.

参考文献

おわりに

数で勝負だったので仕方ないんですがたくさん調べることがあって大変でした.

もう少し, 参考にした素晴らしい資料のように, いろいろな概念についてわかりやすい図を追加したりしたほうがよかった.

実際に使ってみた記事も書きたい.

  1. KataContainerの作者によるもの

  2. GitHubのREADME.mdによると pronounced like a "rocket" とのことなのであえてカタカナで書くと"rkt container"は「ロケットコンテナ」と読むようです.

  3. GitHubでの初期リリース(v0.0.0)が2014年11月27日で, v1.0.0も2016年2月5日です. なお docker/engine リポジトリのリリースを見ると v1.0.0 は2014年6月9日でcontainrdのv1.0.0も2017年12月13日です.

  4. GitHub上の履歴ではappc/specの初期リリースが2014年12月12日なのに対してopencontainers/runtime-specの初期リリースは2015年12月18日, opencontainers/image-specは2016年5月7日です.

65
47
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
65
47

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?