OCIは、コンテナイメージフォーマットとランタイムに関するオープンコンテナの仕様を定義するための業界共同の取り組みです。
本ブログは英語版からの翻訳です。オリジナルはこちらからご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。
#概要
OCIには、イメージ仕様とランタイム仕様の2つの仕様があります。
ここでは、これらの仕様が何をカバーし、どのように相互作用するかを説明しています。
OCIイメージはどこかからダウンロードされ(Dockerハブと考えてください)、OCIランタイムファイルシステムバンドルに展開されます。その時点から、OCIランタイムによってOCIランタイムバンドルが実行されます。ランタイム仕様では、「ファイルシステムバンドル」を実行する方法を定義しています。
#イメージ仕様書(image-spec)
イメージ仕様は、manifest、イメージインデックス、ファイルシステムレイヤのセット、設定からなる OCI コンテナイメージのアーカイブフォーマットを定義します。この仕様の目的は、コンテナイメージを構築し、輸送し、実行するための準備をするための相互運用可能なツールを作成できるようにすることです。
コンテナイメージは、トップレベルでは単なるtarballであり、展開後は以下のようなレイアウト
となります。
├── blobs
│ └── sha256
│ ├── 4297f0* (image.manifest)
│ └── 7ea049 (image.config)
├── index.json
└── oci-layout
レイアウトは、それらが何であるか、そしてそれらがどのように関連しているか(参照されているか)の仕様がなければ、それほど有用ではありません。
index.json
がエントリポイントで、それはprimary a manifest
を含んでおり、単一のコンテナイメージで使用されるすべての "リソース "をリストアップしています。
マニフェスト
には主にconfig
とlayers
が含まれています。
これを図にすると大体こんな感じです。
configには、特に1) ランタイムバンドルのランタイムconfigureファイルに変換されるイメージの設定、2) ランタイムバンドルのルートファイルシステムを構成するレイヤー、3) イメージの履歴に関するメタデータが含まれています。
layersは最終的なrootfs
ファイルシステムを構成するものです。最初のレイヤーがベースで、他のすべてのレイヤーはベースへの変更のみを含んでいます。次のセクションでは、レイヤーの仕様がどのようなものかを詳しく見てみましょう。
####Layers
Layersについては、この仕様では基本的に2つのことを定義しています。
1、Layersをどのように表現するか。
- ベースのLayersでは、すべてのコンテンツを tar
化します。
- ベースではないLayersでは、そのベースと比較したチェンジセットを tar
します。
- したがって、最初に変更を検出してチェンジセットを形成し、このLayersの表現としてチェンジセットを tar
します。
2、すべてのLayersを統合する方法。
すべてのチェンジセットをベースLayersの上に適用します。これで rootfs
ができあがります。
#ランタイム仕様
イメージがディスクファイルシステム上のランタイムバンドルに解凍されると、実行可能なものができあがります。この時にランタイム仕様書が起動します。ランタイム仕様は、コンテナの構成、実行環境、およびライフサイクルを指定します。
コンテナの設定には、コンテナの作成と実行に必要なメタデータが含まれています。これには、実行するプロセス、環境変数、使用するリソース制約、サンドボックス機能などが含まれます。コンフィギュレーションの中には、Linux、Windows、Solaris、仮想マシンに特化したものなど、すべてのプラットフォームに共通するものもありますが、Linuxのみというようにプラットフォームに特化したものもあります。
ランタイム仕様では、コンテナのライフサイクルも定義しています。コンテナが作成されてから存在しなくなるまでの一連のイベントです。
###コンテナのライフサイクル
コンテナにはライフサイクルがあり、その本質は以下の状態図のようにモデル化することができます。
pause
やpaused
など、他にもいくつかのアクションや状態を入れることができますが、これらは基本的なものです。
状態図は従来のものですが、一つだけ重要なことがあります。コンテナの仕様ではネットワークの設定方法は定義されていませんが、実際にはHooks
に依存してネットワークを適切に設定します。
#コンテナの設定
コンテナのコンフィグには、コンテナを作成して実行するために必要なコンフィグが含まれていることは先に述べました。ここでは、コンテナとは何かを理解するために、設定のいくつかをもう少し詳しく見ていきます。
1、Root
コンテナのルートファイルシステムを定義します。
2、Mounts
ルートファイルシステムにマウントできる追加ファイルシステムを指定します。これは、ローカルのホストディレクトリやCephのような分散ディレクトリをバインドしてマウントすることができます。
3、Process
コンテナ内で実行したいプロセスに関連する全てのものを指定します。環境変数やプロセスへの引数などが含まれます。
Linuxプロセスの場合は、プロセスのセキュリティ面に関するものを追加で指定することができ、ここでは能力、rlimits、selinuxラベルなどを指定することができます。
1、Hooks
ここはコンテナのライフサイクルにフックアップして、ネットワークの設定やクリーンアップなどを行うことができる場所です。
2、Linux の名前空間
Linuxプラットフォームでは、多くの設定が名前空間の設定に特化しています。実は、名前空間はコンテナ技術の基礎となるものです。別の言い方をすれば、名前空間なしにコンテナは存在しないということです。Linux には 7 種類の名前空間があり、それらはすべて OCI ランタイム仕様でサポートされています。
Namespace | Domain / Description |
---|---|
PID | Process IDs |
Mount | Mount points |
Network | Network devices, stacks, ports, etc. |
User | User and group IDs |
IPC | System V IPC, POSIX message queues |
UTS | Hostname and NIS domain name |
3、アノテーション
コンテナが何をどのように実行すべきかに加えて アノテーションによって、コンテナにラベルを付けることができます。いくつかのプロパティに基づいてコンテナベースにラベルを付けて選択する機能は、コンテナオーケストレーションプラットフォームの基本的な要件です。
#イメージ、コンテナ、プロセス
コンテナは、(コンテナの)イメージから作成されます。1つのImageから複数のコンテナを作成することができます。また、コンテナをリパックして、通常はベースとなるImageを変更して新しいImageを作成することもできます。
コンテナを取得した後は、そのコンテナの中で処理を実行することができます。最も注目すべきは、一度コンテナ化したアプリは自己完結型になり、ホスト環境に影響を与えないので、「どこでも(TM)動く」はずです。
ここでは、Image、Container、Processという様々な概念の関係性を説明します。
#DockerとKubernetes
Dockerはコンテナを業界のトレンドにしており、Dockerをコンテナ、コンテナをDockerと考える人はたくさんいます。ここではDockerは間違いなく称賛に値する。しかし、技術的な観点から見ると、Dockerは最も広く使われているコンテナ実装です。Dockerの実装のアーキテクチャは、バージョンごとに非常に速く進化しています。執筆時点では以下のようになっています。
図は[github]Org/project
の形式に沿っています。ほとんどのコンポーネントはDockerに由来していますが、現在は異なるGitHubの組織やプロジェクトに属しています。一番上にあるのは私たちが日常的に使っているDockerコマンドツールで、Docker Inc.から商用提供されています。Dockerツールはmobyというオープンソースプロジェクトに依存していますが、mobyではoci runtime仕様のリファレンス実装であるruncを使用しています。
###コンテナオーケストレーション
1つか2つのコンテナだけが必要な場合は、Dockerで十分でしょう。しかし、何十個も何千個ものコンテナを運用したい場合には、解決すべき問題がもっとたくさんあります。いくつか挙げてみましょう。
1、スケジューリング:どのホストにコンテナを置くか?
2、更新:コンテナイメージをどのように更新するか?
3、スケーリング:より多くの処理能力が必要なときに、どのようにしてコンテナを追加するか?
それがコンテナオーケストレーションシステムの仕事です。そしてKubernetesもその一つですが、今のところ最も有力なのは議論の余地がないと思います。しかし、ここではKubernetesについて深く掘り下げることはせず、コンテナランタイムがコンテナオーケストレーションプラットフォームにどのようにフィットするのかという観点から簡単に触れてみたいと思います。
以下の図は、Kubernetesがコンテナランタイムとどのように相互作用するかを示しています。
Kubernetesでは、Container Runtime Interfaceを使ってランタイムの実装をデカップリングしています。簡単に言うと、CRIはコンテナの作成、起動、停止、削除を行うためのインターフェースを定義しています。これにより、Kubernetes用のプラガブルなコンテナランタイムが可能になり、特定のランタイムに固執する必要がなくなります。現在、cri-containerd
やcri-o
などいくつかの実装がありますが、いずれも最終的にはoci/runc
を使用することになります。
#まとめ
OCIコンテナイメージとランタイム仕様の概要です。それぞれの仕様の責任と、それらがどのように連携しているかをカバーしています。ランタイム仕様のコンテナライフサイクルとプライマリ構成について説明します。そして、Dockerとruncの関係を紹介し、コンテナオーケストレーションとコンテナランタイムがどのように適合するかを簡単に紹介して記事を締めくくります。
Alibaba Cloud上のコンテナについて詳しく知りたい方は、https://www.alibabacloud.com/product/container-service をご覧ください。
または、Alibaba CloudのオープンソースのリッチコンテナエンジンであるPouchContainerをチェックしてみてください。
アリババクラウドは日本に2つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ