Slide 1

Slide 1 text

Kubernetesをとりまく コンテナランタイムの栄枯盛衰 Presented by @inductor

Slide 2

Slide 2 text

今日の目標 ● コンテナランタイムがどうしてDockerだけじゃないのかを知る ● コンテナランタイムの歴史を知ることで、Kubernetesで動かす アプリケーションの裏側について少しだけ詳しくなる ● ランタイムの選択肢にはどんなものがあって、どんな特徴があるのかを 知ることで、Docker非推奨の話の裏側を少し理解できる

Slide 3

Slide 3 text

2019年の夏... ↓こんな話をしました

Slide 4

Slide 4 text

Kubernetesの特徴(リリース時) ● Google Borgの10年以上に渡る運用知見を集約した基盤のOSS ○ リリース当初はGoogleがメインで開発 ● Docker、etcdを中心とした分散型コンテナ実行基盤 ● APIを起点に、etcdに書かれたステートを正とし あるべき状態を定義されたとおりに基盤上で維持する自立型のシステム ● 管理用のマスター、実行用のミニオンと呼ばれるマシンからなる

Slide 5

Slide 5 text

Kubernetesの特徴(現在) ● Google Borgの10年以上に渡る運用知見を集約した基盤のOSS ○ CNCFがホスティング、コミュニティを主体とした開発体制 ● コンテナランタイム、etcdを中心とした分散型コンテナ実行基盤 ● APIを起点に、etcdに書かれたステートを正とし あるべき状態を定義されたとおりに基盤上で維持する自立型のシステム ● 管理用のコントロールプレーン、実行用のワーカーからなる

Slide 6

Slide 6 text

Kubernetesの特徴(現在) ● Google Borgの10年以上に渡る運用知見を集約した基盤のOSS ○ CNCFがホスティング、コミュニティを主体とした開発体制 ● コンテナランタイム、etcdを中心とした分散型コンテナ実行基盤 ● APIを起点に、etcdに書かれたステートを正とし あるべき状態を定義されたとおりに基盤上で維持する自立型のシステム ● 管理用のコントロールプレーン、実行用のワーカーからなる Dockerが非推奨になったの!? で話題になった1.20.0リリース時のアレ

Slide 7

Slide 7 text

ランタイムのこれまでについて お話していきます

Slide 8

Slide 8 text

Kubernetes初期のランタイムとの関係 ● Google Borgの10年以上に渡る運用知見を集約した基盤のOSS ○ リリース当初はGoogleがメインで開発 ● Docker、etcdを中心とした分散型コンテナ実行基盤 ● APIを起点に、etcdに書かれたステートを正とし あるべき状態を定義されたとおりに基盤上で維持する自立型のシステム ● 管理用のマスター、実行用のミニオンと呼ばれるマシンからなる

Slide 9

Slide 9 text

Kubernetes 1.0 当時の実装 https://github.com/kubernetes/kubernetes/blob/release-1.0/pkg/kubelet/dock ertools/manager.go kubeletのdockertools配下にDockerのための実装があった → 完全にDockerで動くことだけを想定

Slide 10

Slide 10 text

Kubernetes 1.0 当時の実装 https://github.com/kubernetes/kubernetes/blob/release-1.0/pkg/kubelet/dock ertools/manager.go kubeletのdockertools配下にDockerのための実装があった → 完全にDockerで動くことだけを想定 ちょっとだけソースの中身を覗い てみましょう

Slide 11

Slide 11 text

Kubernetes 1.0 当時の実装 https://github.com/kubernetes/kubernetes/blob/release-1.0/pkg/kubelet/dock ertools/manager.go kubeletのdockertools配下にDockerのための実装があった → 完全にDockerで動くことだけを想定 docker周りの実装 rkt周りの実装(!)

Slide 12

Slide 12 text

rktとはなんだったのか ● CoreOS社(Red Hatが2018年に買収)が作ったコンテナランタイム ○ CoreOS社は他にもetcdやコンテナホスト用LinuxディストロCoreOSを開発するなど、 Kubernetesのエコシステムに貢献してきた ○ CoreOS Meetup Tokyo #1 の資料を見ると当時の状況がよくわかって面白い ● Docker社が事実上独占していたコンテナのエコシステムを打破する きっかけになった ○ Dockerはデーモンを配置してノード上に常駐させるモデルなのに対し、 rktはsystemdによる隔 離を応用した”デーモンレス”なコンテナ技術 ○ Dockerとは違いPodのネイティブサポートをするなど、 Kubernetesの仕組みを意識

Slide 13

Slide 13 text

rktとはなんだったのか ● CoreOS社(Red Hatが2018年に買収)が作ったコンテナランタイム ○ CoreOS社は他にもetcdやコンテナホスト用LinuxディストロCoreOSを開発するなど、 Kubernetesのエコシステムに貢献してきた ○ CoreOS Meetup Tokyo #1 の資料を見ると当時の状況がよくわかって面白い ● Docker社が事実上独占していたコンテナのエコシステムを打破するきっかけに なった ○ Dockerはデーモンを配置してノード上に常駐させるモデルなのに対し、 rktはsystemdによる隔 離を応用した”デーモンレス”なコンテナ技術 ○ Dockerとは違いPodのネイティブサポートをするなど、 Kubernetesの仕組みを意識 https://kubernetes.io/blog/2016/07/rktnetes-brings-rkt-container-engine-to-kubernetes/

Slide 14

Slide 14 text

rktとはなんだったのか ● CoreOS社(Red Hatが2018年に買収)が作ったコンテナランタイム ○ CoreOS社は他にもetcdやコンテナホスト用LinuxディストロCoreOSを開発するなど、 Kubernetesのエコシステムに貢献してきた ○ CoreOS Meetup Tokyo #1 の資料を見ると当時の状況がよくわかって面白い ● Docker社が事実上独占していたコンテナのエコシステムを打破するきっかけに なった ○ Dockerはデーモンを配置してノード上に常駐させるモデルなのに対し、 rktはsystemdによる隔 離を応用した”デーモンレス”なコンテナ技術 ○ Dockerとは違いPodのネイティブサポートをするなど、 Kubernetesの仕組みを意識 https://kubernetes.io/blog/2016/07/rktnetes-brings-rkt-container-engine-to-kubernetes/ https://speakerdeck.com/ytaka23/mao-demowakaru-rkt-plus-kubernetes-number-ichigayageek

Slide 15

Slide 15 text

Kubernetes 1.3: rktをランタイムとして採用 ● これまでDockerだけを前提に作られていたkubeletやランタイム周りの仕組みを 外部注入可能な形に置き換えるきっかけに ● コンテナイメージの署名やコンテナケイパビリティの制限をデフォルトで実装した 「secure by default」な実装 ● UNIX哲学に基づいたシンプルなプロセスモデル ○ Dockerdがないのでrkt process = pod process ● 当時としてはまだ新しかったユーザー名前空間の採用やSELinuxへの対応、軽 量VMへの対応など夢がてんこ盛り

Slide 16

Slide 16 text

Kubernetes 1.3: rktをランタイムとして採用 ● これまでDockerだけを前提に作られていたkubeletやランタイム周りの仕組みを 外部注入可能な形に置き換えるきっかけに ● コンテナイメージの署名やコンテナケイパビリティの制限をデフォルトで実装した 「secure by default」な実装 ● UNIX哲学に基づいたシンプルなプロセスモデル ○ Dockerdがないのでrkt process = pod process ● 当時としてはまだ新しかったユーザー名前空間の採用やSELinuxへの対応、軽 量VMへの対応など夢がてんこ盛り systemdによるisolation (その他kvm等も選べる)

Slide 17

Slide 17 text

Kubernetes 1.3: rktをランタイムとして採用 ● これまでDockerだけを前提に作られていたkubeletやランタイム周りの仕組みを 外部注入可能な形に置き換えるきっかけに ● コンテナイメージの署名やコンテナケイパビリティの制限をデフォルトで実装した 「secure by default」な実装 ● UNIX哲学に基づいたシンプルなプロセスモデル ○ Dockerdがないのでrkt process = pod process ● 当時としてはまだ新しかったユーザー名前空間の採用やSELinuxへの対応、軽 量VMへの対応など夢がてんこ盛り flyと呼ばれる分離とオーバー ヘッドが少ないシンプルなモー ドもあった

Slide 18

Slide 18 text

Kubernetes 1.3: rktをランタイムとして採用 ● これまでDockerだけを前提に作られていたkubeletやランタイム周りの仕組みを 外部注入可能な形に置き換えるきっかけに ● コンテナイメージの署名やコンテナケイパビリティの制限をデフォルトで実装した 「secure by default」な実装 ● UNIX哲学に基づいたシンプルなプロセスモデル ○ Dockerdがないのでrkt process = pod process ● 当時としてはまだ新しかったユーザー名前空間の採用やSELinuxへの対応、軽 量VMへの対応など夢がてんこ盛り flyと呼ばれる分離とオーバー ヘッドが少ないシンプルなモー ドもあった systemdでプロセスを管理 (Podの初期化など) APIサービス経由で任意の コマンド実行したり https://speakerdeck.com/surbaniak/meetup-london-2016-rkt-plus-kubernetes

Slide 19

Slide 19 text

Kubernetes 1.3: rktをランタイムとして採用 ● これまでDockerだけを前提に作られていたkubeletやランタイム周りの仕組みを 外部注入可能な形に置き換えるきっかけに ● コンテナイメージの署名やコンテナケイパビリティの制限をデフォルトで実装した 「secure by default」な実装 ● UNIX哲学に基づいたシンプルなプロセスモデル ○ Dockerdがないのでrkt process = pod process ● 当時としてはまだ新しかったユーザー名前空間の採用やSELinuxへの対応、軽 量VMへの対応など夢がてんこ盛り flyと呼ばれる分離とオーバー ヘッドが少ないシンプルなモー ドもあった systemdでプロセスを管理 (Podの初期化など) APIサービス経由で任意の コマンド実行したり https://speakerdeck.com/surbaniak/meetup-london-2016-rkt-plus-kubernetes よさそうでは?

Slide 20

Slide 20 text

Kubernetes 1.5: CRIの登場 ● これまでDockerに依存していた部分を、(Kubernetesにとって)コンテナを動かす ための仕組み、すなわち「CRI(Container Runtime Interface)」として仕様を定 義 ○ ノード上にDaemonを配置 ○ イメージとコンテナを操作するための gRPCサービス(サーバーの存在が前提 ) ○ ランタイムを外部ソケット通信にすることで Kubernetes側とライフサイクルを切り離し

Slide 21

Slide 21 text

なぜCRI? ● ランタイムに依存するコードがKubernetes内部に多かった ○ rktにしてもDockerにしても、それぞれが持つ APIを呼び出すためのコード ○ 各ランタイムのバージョンに依存する修正が発生すると、 Kubernetesに変更が発生 ○ 各ランタイム自体(特にDocker)はKubernetesだけを対象にしてないので、容赦なしに変更を加 えてバージョンアップしてくる ● 外部コンポーネント化することで関心を分離しないとメンテナンスが大変 ○ Kubeletは各ノードにいるので、 gRPC over UNIX Socketな構成が都合よかった ○ 結局DockerもMoby projectを発表し、containerdがのちにCRIランタイムとして台頭

Slide 22

Slide 22 text

こまったrktくん ● デーモンレスなプロセスモデル ○ KubernetesがCRIを発表したので、なくなく CRIに対応せざるを得ない状況に ● ランタイムでの再実装が不要なgRPCによる命令型のAPIモデル ○ rktはsystemdでPod(プロセス)を立ち上げてハイ終わりなモデルなので厳しい ● rktletとか作っていろいろ頑張るも、2019年にはプロジェクトの凍結が発表され た ○ CNCFプロジェクトとしては (自分が知る限りは)いまだ唯一の”Archived”プロジェクト https://www.cncf.io/blog/2019/08/16/cncf-archives-the-rkt-project/

Slide 23

Slide 23 text

こまったrktくん ● デーモンレスなプロセスモデル ○ KubernetesがCRIを発表したので、なくなく CRIに対応せざるを得ない状況に ● ランタイムでの再実装が不要なgRPCによる命令型のAPIモデル ○ rktはsystemdでPod(プロセス)を立ち上げてハイ終わりなモデルなので厳しい ● rktletとか作っていろいろ頑張るも、2019年にはプロジェクトの凍結が発表され た ○ CNCFプロジェクトとしては (自分が知る限りは)いまだ唯一の”Archived”プロジェクト https://www.cncf.io/blog/2019/08/16/cncf-archives-the-rkt-project/

Slide 24

Slide 24 text

rktの意思を継ぐもの、OCID(CRI-O)とPodman ● Red Hatが2016年に発表したOCIDは現在CRI-Oという名前で現役で活躍 ○ Linuxケイパビリティの制限やセキュリティ周りの対応など、 rktでも培われたいくつかの思想が 垣間見える ○ Red Hat OpenShift 4からはデフォルトのランタイムに採用 ● デーモンレスなコンテナランタイム「Podman」 ○ Red Hatを主体としたオープンソースプロジェクトとして現在も鋭意開発中 ○ Docker Compose互換な実装やネットワークへの対応、ユーザー名前空間の実装など、デーモ ンを使わずによく頑張ってるなと思う

Slide 25

Slide 25 text

rktの意思を継ぐもの、OCID(CRI-O)とPodman ● Red Hatが2016年に発表したOCIDは現在CRI-Oという名前で現役で活躍 ○ Linuxケイパビリティの制限やセキュリティ周りの対応など、 rktでも培われたいくつかの思想が 垣間見える ○ Red Hat OpenShift 4からはデフォルトのランタイムに採用 ● デーモンレスなコンテナランタイム「Podman」 ○ Red Hatを主体としたオープンソースプロジェクトとして現在も鋭意開発中 ○ Docker Compose互換な実装やネットワークへの対応、ユーザー名前空間の実装など、デーモ ンを使わずによく頑張ってるなと思う ● 手元のDockerを置き換えるPodman ● Kubernetesのために作られたランタイムとしてのCRI-O それぞれの違いを理解して使い分けてみるのも良いかもし れません

Slide 26

Slide 26 text

閑話休題: Dockerをやめるのはどうなのか

Slide 27

Slide 27 text

Dockerが持つ主な3つのサービス ● ランタイムサービス ○ Containerdが管理するコンテナを動かすためのコア ● ネットワークサービス ○ docker network 配下のAPI ● ボリュームサービス ○ docker volume 配下のAPI

Slide 28

Slide 28 text

Kubernetesが使うDockerの機能... ● ランタイムサービス ○ Containerdが管理するコンテナを動かすためのコア ● ネットワークサービス ○ docker network 配下のAPI ● ボリュームサービス ○ docker volume 配下のAPI つかう つかわない

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

Kubernetesが持つ複数のインターフェース ● CRI ○ ランタイム ● CNI ○ ネットワーク ● CSI ○ ストレージ ● CPI ○ クラウドプロバイダー Dockerはどのレイヤとも被りうる・・・

Slide 31

Slide 31 text

Dockershimの存在 https://jaco.udcp.info/entry/2020/12/03/172843 CRIの登場により CRI -> Docker API変換のため のDockershimが登場

Slide 32

Slide 32 text

CRI対応済みランタイム ● Containerd ○ Dockerの裏側で動くランタイムサービス ○ DockerネイティブなAPIとCRIの両方をサポート ● CRI-O ○ Kubernetesのためのランタイム仕様である CRIを満たすべく作られたランタイム ● Docker(with Dockershim) ○ DockershimがなけりゃただのDocker

Slide 33

Slide 33 text

コンテナランタイムの役割(Docker) dockerd docker pull docker run REST API containerd gRPC runC OCI(containerd内でJSON のコンフィグを渡しながらバ イナリを直接実行) OCI High level runtime Low level runtime

Slide 34

Slide 34 text

コンテナランタイムの役割(Kubernetes) Kubernetes kubectl run kubectl apply REST API containerd CRI (gRPC) kube-apiserverとかetcdとか kubeletとかいろいろ含む ※CRIは各ノード上のkubeletが喋る runC OCI(containerd内でJSON のコンフィグを渡しながらバ イナリを直接実行) OCI High level runtime Low level runtime

Slide 35

Slide 35 text

コンテナランタイムの役割(Kubernetes) Kubernetes kubectl run kubectl apply REST API containerd CRI (gRPC) kube-apiserverとかetcdとか kubeletとかいろいろ含む ※CRIは各ノード上のkubeletが喋る runC OCI(containerd内でJSON のコンフィグを渡しながらバ イナリを直接実行) OCI High level runtime Low level runtime CRI: Kubernetesレイヤで動くランタイム OCI: Linux kernelレイヤで動くランタイム

Slide 36

Slide 36 text

ここまでのまとめ ● Kubernetesは当初、アプリケーションをコンテナで動かすために 事実上唯一の選択肢だったDockerを採用(Dockerに寄せた実装) ● コミュニティの成長とともに、さまざまな実装、アイデア、選択肢が 増えてきた ● Kubernetesコア(kubelet)における実装及びメンテナンスコストを抑える ための仕組みとしてCRI(Container Runtime Interface)を考案、現在の スタンダードとなった ● 分離の過程でOCIという団体、仕様が生まれ、イメージやコンテナを 動かすための低いレベルでの仕組みが標準化された

Slide 37

Slide 37 text

ここから先は時間と体力があれば 軽くやります

Slide 38

Slide 38 text

CRIとOCI、各ランタイムの違いをもう少し ● CRIランタイム ○ KubernetesからのgRPC命令を受け付けるサーバープロセス ○ 各ノード上にプロセスとして動いている (systemd status containerd/cri-o すると見れる) ○ コンテナの作成や起動そのものは OCIランタイムにおまかせ ● OCIランタイム ○ ただのバイナリファイル ○ Linuxのcgroups/namespaceと対話してコンテナを生成 /削除する役割 ○ ただし!!バイナリファイルは実行したらおわりで、その後コンテナのプロセスの 面倒をみる役割が必要(なんで???) ■ Runtime Shimというやつを使う ■ とても良い入門資料 : https://speakerdeck.com/moricho/deep-dive-into-runtime-shim

Slide 39

Slide 39 text

OCIランタイムの役割

Slide 40

Slide 40 text

OCIランタイムの分離レベル ● OCIランタイムの役割は ○ ホスト上で動くコンテナ (プロセス)や、隔離に使う名前空間などの作成と削除 ○ 分離の方法は一つではなく、 Linuxの名前空間を使う方法もあれば、コンテナを動かすための VMを作成してその上でアプリケーションを動かすような方法もある ■ OCIの仕様を満たしていればわりとなんでもよい

Slide 41

Slide 41 text

OCIランタイム ● runC ○ 何も考えてなけりゃみんなが使ってる ○ Dockerなどで使われる最も基本形 (Linux namespace + cgroups on host) ● gVisor ○ Googleが作ったサンドボックスランタイム ○ ゲストカーネルを動かしてコンテナに提供。コンテナはホストに直接悪いことができない ● Kata container ○ Intelのプロジェクトが発端のランタイム ○ KVMを立ち上げて分離するので起動オーバーヘッドが大きい代わりに分離レベルが高い ● Firecracker ○ 今回はややこいので説明なし

Slide 42

Slide 42 text

runCの仕組み ホストマシン Linuxカーネル コンテナ コンテナ コンテナ runC Docker & CRI ファイルシステムの展開 プロセスの初期化 イメージの管理

Slide 43

Slide 43 text

gVisorの仕組み ホストOS (ホストカーネル) コンテナ コンテナ コンテナ gVisorのゲストカーネル runSC

Slide 44

Slide 44 text

Kata containersの仕組み ホストOS (ホストカーネル) KVM (qemu) KVM (qemu) KVM (qemu) Kata runtime コンテナ コンテナ コンテナ ホストカーネルを利用して KVMベースのマシンを起動

Slide 45

Slide 45 text

分離レベルを気にしないといけない理由は何? ● runCはカーネルを呼べる権限を剥奪されるとホスト全体に影響がある ● マルチテナントなどのユースケースでは分離レベルの高いほかのランタイムを 使うことも考慮すべき ● Kubernetesでは、1クラスター上で複数のランタイムを使える機能がある ○ RuntimeClass ■ Podで指定できる ■ 神資料↓ ■ https://speakerdeck.com/makocchi/lets-learn-about-kubernetes-runtime-class ■ https://blog.inductor.me/entry/2021/04/30/022505

Slide 46

Slide 46 text

まとめ ● Kubernetesは当初、アプリケーションをコンテナで動かすために 事実上唯一の選択肢だったDockerを採用(Dockerに寄せた実装) ● コミュニティの成長とともに、さまざまな実装、アイデア、選択肢が 増えてきた ● Kubernetesコア(kubelet)における実装及びメンテナンスコストを抑える ための仕組みとしてCRI(Container Runtime Interface)を考案、現在の スタンダードとなった ● 分離の過程でOCIという団体、仕様が生まれ、イメージやコンテナを 動かすための低いレベルでの仕組みが標準化された ● さまざまな要件に答えるために複数の違うアプローチを取ったランタイムがコミュニティ から提供されている

Slide 47

Slide 47 text

おわり!!!!!