ステータス: ドラフト (2026-10-13)、公式ドキュメント基準 + 一部実測。 構造とデフォルト値は、公式ドキュメントとGitHubリポジトリを2026-10-13に開いて確認しました(k3s v1.37.1+k3s1、RKE2 v1.37.1+rke2r1、k0s v1.36.4+k0s.1がその日の最新安定版)。「実測」と付いた値は、TT Labコースの実習VMで直接構築してみた結果です(2026-08〜09、バージョンを併記)。 作成規則: 実測データが基本であり、測定できなかったものは「未測定」、ドキュメントから見つからなかったものは「未確認」と表示します。
目次
1. なぜ3つを一緒に見るのか
Kubernetesを自分で構築しようとするチームが最初に目にする名前が、k3s、RKE2、k0sです。3つとも「バイナリを1つダウンロードしてサービスとして登録すればクラスターが起動する」という同じ約束をします。そのため、見た目は似ています。
しかし、運用を始めると違いが表面化します。障害が発生したときにログをどこで見ればよいのか、 etcdctl を使用できるのか、最初からイングレスがデプロイされているのか、ノード一覧にコントロールプレーンが表示されるのかがすべて異なります。この違いは機能リストではなく、 設計とデフォルト値から生じます。この記事では、その設計を図で比較します。セキュリティと運用は 第2部で、選び方は 第3部で扱います。
2. 出身と目標
| k3s | RKE2 | k0s | |
|---|---|---|---|
| 最初に作成した場所 | Rancher (現在はSUSE) | Rancher (SUSE) | Mirantis |
| 別名 | — | RKE Government | — |
| CNCF | Sandbox (2020-08-19採択) | CNCFプロジェクトではない(認証済みディストリビューションリストにのみ存在) | Sandbox (2025-01-19採択) |
| ターゲット | エッジ・IoT・ARMボード・CI・開発 | セキュリティ・コンプライアンス、特に米国連邦政府部門 | インストールと運用の摩擦をなくした汎用ディストリビューション |
| 2026-10-13 最新安定版 | v1.37.1+k3s1 (2026-09-30) | v1.37.1+rke2r1 (2026-09-30) | v1.36.4+k0s.1 (2026-09-19) |
3つのディストリビューションの性格を1行ずつまとめるとこうなります。
- k3s は「小さくすること」が目標です。ストレージのREADMEには、複数のコンポーネントを1つのプロセスで動作させることでメモリを削減し、アップストリームのKubernetesからツリー内ストレージドライバーとクラウドプロバイダーを取り除いたと説明されています。アップストリームのコードに対する独自パッチは1,000行未満であるとし、フォークではなくディストリビューションであることを強調しています。
- RKE2 は、k3sのインストールおよび運用方式に、旧RKE1の「アップストリームのKubernetesに近づける」という方針を組み合わせたものです。目標は明確です。管理者がほとんど手を加えなくてもCISベンチマークを通過し、FIPS 140-2をサポートし、ビルドプロセスでTrivyによるCVEの継続的なスキャンを行います。Dockerに依存していたRKE1は2025-07-31にサポートが終了しており、SUSEはRKE2やk3sへ移行するよう案内しています。
- k0s は「ゼロ」を掲げています。ホームページが謳うゼロは3つあります。摩擦のないインストール(Zero Friction)、ホストカーネル以外に依存関係のない単一バイナリ(Zero Deps)、Apache 2ライセンスによる無料(Zero Cost)です。よく引用される「zero overhead」という表現は公式ページで見つかりませんでした(未確認)。
3. コントロールプレーンはどのように起動するか
最大の違いは、 コントロールプレーンのコンポーネントをどのような形で起動するのかという点です。
k3s: 1つのプロセスにまとめる
k3s server 1つが、kube-apiserver、スケジューラー、コントローラーマネージャー、kubelet、kube-proxy、flannel、ネットワークポリシーコントローラー、kine、helm-controllerを 同じプロセス内で 動かします。READMEがメモリ削減の主な理由として挙げる設計です。コンポーネントごとに個別に保持するべきランタイムとキャッシュを一度だけ使用するためです。
containerdとruncはバイナリに同梱されてきますが、実行は個別に行われます。k3sのソース(pkg/agent/containerd)を見ると、k3sがcontainerdを別プロセスとして起動していることがわかります。
運用においてこの構造が意味することは以下の通りです。
- ログが1か所に集まります。
journalctl -u k3s1つの中にapiserverとkubeletのログが混ざって出力されます。 crictl psでコントロールプレーンのコンテナを見つけることはできません。そもそもコンテナではないからです。- kubeadmで習得した「
/etc/kubernetes/manifestsの静的ポッドの修正」は通用しません。フラグはk3sの設定ファイルや--kube-apiserver-argのような引数で渡します。
RKE2: kubeletが静的ポッドとして起動する
rke2 server プロセスは直接コントロールプレーンを動かしません。行うことは監督です。containerdを起動し、それが終了すれば自らも終了し、kubeletを起動し、停止すれば再起動させます。そして、etcd、kube-apiserver、コントローラーマネージャー、スケジューラーの 静的ポッドのマニフェストを /var/lib/rancher/rke2/agent/pod-manifests/ に書き込みます。kubeletがそのマニフェストを読み込んでコンテナとして起動します。kubeadmと同じ形です。
kubelet・containerd・kubectlなどの実行ファイルは rke2-runtime イメージの中に含まれており、初回起動時にそのイメージから取り出して展開します。CNI・CoreDNS・イングレス・metrics-serverなどのアドオンは、内蔵のhelm-controllerがHelmチャートとしてインストールします。
この構造には1つ罠があります。 systemctl stop rke2-server は静的ポッドを停止しません。 TT LabのRKE2実習(v1.36.4+rke2r1)でサービスを停止した後も、rootとして動作するetcdコンテナがそのまま残っていました(実測)。ノードを完全に停止させるには、インストール物に含まれる rke2-killall.sh を使用します。この違いが実際にどのようなインシデントを引き起こすのかについては、第2部で見ていきます。
k0s: 個別に起動し、コントローラーはノードではない
k0sは、コントロールプレーンのコンポーネントをコンテナとしてではなく、 それぞれ独立したプロセス(ドキュメントの表現では「naked」プロセス)として起動し、k0sバイナリがそれらのプロセスを監督します。etcd、kube-apiserver、スケジューラー、コントローラーマネージャー、konnectivity-serverが個別に起動します。これらの実行ファイルはk3sバイナリの中に含まれており、初回の実行時に /var/lib/k0s/bin に展開されます。
最も目立つ違いは、 コントローラーノードにはkubeletもコンテナランタイムもデフォルトで存在しない点です。そのため、コントローラーはワークロードを受け取らず、 kubectl get nodes にも表示されません。APIサーバーがワーカーのkubeletやポッドに通信する必要があるときは、Konnectivityトンネルを介します(エージェントの8132ポート)。
この分離を解除したいときに使用するフラグが2つあります。
--enable-worker: コントローラーがワーカーの役割も兼ねます。FAQではテスト・開発・PoC目的でのみ推奨しています。--single: 1台のノード構成モードです。--enable-workerを含みますが、複数のノードに必要な機能を無効化するため、 後からノードを増やすことはできません。
また、k0sはコントロールプレーンのコンポーネントをrootではなく専用のシステムユーザーとして動作させます。ドキュメントには k0s install がこのシステムユーザーを作成するという点までしか記載されておらず、ユーザー名はソース(pkg/constant/constant.go、v1.36.4+k0s.1タグ)から確認しました。etcdは etcd、APIサーバーは kube-apiserver、スケジューラーは kube-scheduler、Konnectivityは konnectivity-server のユーザーです。コントローラーマネージャーのユーザーは確認できませんでした(未確認)。
3つの構造を一言で
| k3s | RKE2 | k0s | |
|---|---|---|---|
| コントロールプレーンの形態 | 1つのプロセス | kubeletが起動する静的ポッド | コンポーネントごとに独立したプロセス |
| コンテナランタイム | containerd・runcバンドル | containerdバンドル(ランタイムイメージから取り出し) | containerd・runcバンドル |
| サーバー(コントローラー)がワークロードを受け取るか | 受け取る | 受け取る | デフォルトでは受け取らない |
| コントロールプレーンのログ | k3sサービスログ1つ | ポッドログ(/var/log/pods) |
k0sサービスログ |
| アドオンのインストール方式 | マニフェストフォルダー + helm-controller | helm-controller | 内蔵マニフェスト、Helm拡張は選択 |
4. ストレージとHA
k3s: SQLiteで始めてetcdに移行できる
k3sサーバー1台のデフォルトストレージは SQLite です。APIサーバーはetcdとしか通信できないため、中間層に kine が介在し、etcd APIを模倣しながら背後ではSQLiteに書き込みます。軽量ですがサーバーを増やすことができず、etcdのツールも使用できません。TT Labの実習(v1.35.8+k3s1)でSQLiteの状態で k3s etcd-snapshot save を実行すると、 etcd datastore disabled により拒否されました(実測)。
HAへの移行方法は2つあります。
- 内蔵etcd。 最初のサーバーを
--cluster-initとして起動し、残りのサーバーを同じトークンで参加させます。奇数台、最低3台が必要です。SQLiteで動作していたサーバーも--cluster-initとして再起動すればetcdに移行します。実習では再起動から12秒でAPIが復旧し、state.dbがstate.db.migratedに名前が変わり、移行前に作成したConfigMapのUIDがそのまま残っていました(実測、v1.35.8+k3s1)。 - 外部DB。 2台以上のサーバーが同一のMySQL・MariaDB・PostgreSQL・etcdを参照します。ドキュメントが認定しているバージョンは、etcd 3.5.21、MySQL 8.0·8.4、MariaDB 10.11·11.4、PostgreSQL 15.12·16.7·17.3です(2026-10-07更新ドキュメント)。この場合も、SQL DBの前でkineがetcd APIを模倣します。
いずれの場合も、サーバー群の前に 固定登録アドレス(L4ロードバランサー、ラウンドロビンDNS、仮想IPのいずれか)を配置します。
RKE2: 最初からetcd
RKE2は、特に設定を行わない場合、 内蔵etcd です。HA構成ではサーバーを奇数の3台にすることを推奨しており、サーバーでもデフォルトでワークロードを受け付けるため、 サーバー3台、エージェント0台が最小限のHA構成となります。ノードは固定登録アドレスの 9345ポートで参加し、APIには6443ポートを使用します。
SQLiteも使用可能ですが、ドキュメントには「実験的」と記載されており、1台のサーバーでのみ利用可能です。外部SQL DBはkineを経由して使用できます(ドキュメントで検証済みのバージョンは etcd 3.6.7、MySQL 8.4.8、MariaDB 11.4.10、PostgreSQL 18.3)。ただし、そのバックアップ手順は「実験的」な手順として案内されています。
k0s: 複数台ならetcd、1台ならSQLite
k0sのストレージ設定(spec.storage.type)は etcd と kine のいずれかで、デフォルトの生成設定はetcdです。ドキュメントとREADMEの機能一覧には、デフォルト値が「複数ノードはetcd、1ノードはSQLite」と記載されており、kineの後ろにMySQLやPostgreSQLを配置することも可能とされています。
--single これがSQLiteになることはハンズオンで確認済みです。 --single で構築したk0sで k0s etcd member-list を実行すると、 wrong storage type: kine として拒否されます(実測値)。etcdを扱うには --enable-worker として構築する必要があります。
HA構成は コントローラー3台または5台が推奨されています。2台でもk0sの観点ではHAですが、etcdのクォーラムの観点ではHAではないとドキュメントで指摘されています。コントローラーの前段には、6443(API)・8132(Konnectivity)・9443(k0s参加API)をすべてのコントローラーに転送するTCPロードバランサーが必要です。外部ロードバランサーがない場合は、次の2つのいずれかを選択できます。
- CPLB(Control Plane Load Balancing): コントローラー間でkeepalivedにより仮想IPを共有します。
--singleとは併用できません。 - NLLB(Node-Local Load Balancing): ワーカーごとに小さなロードバランサー(デフォルトはEnvoy)を配置し、コントローラーへ振り分けます。デフォルトでは無効になっています。
5. デフォルトで含まれるもの
インストール直後に何がすでに稼働しているかが、3者の間で最も大きく異なる点です。
| 構成要素 | k3s (v1.37 ドキュメント) | RKE2 (v1.36~1.37 ドキュメント) | k0s (v1.36 ドキュメント) |
|---|---|---|---|
| CNI | flannel(VXLAN) | canal(flannel VXLAN + Calicoポリシー) | kube-router |
| CNIの選択肢 | flannelバックエンドの変更、または無効化して直接インストール | cilium、calico、flannel、none、multus(補助) | calico、custom |
| NetworkPolicy | 内蔵コントローラー(kube-routerベース) | canalのCalico | kube-router |
| イングレス | Traefik v3 | v1.36以降の新規クラスターはTraefik、それ以前はingress-nginx | なし |
| サービス LoadBalancer | ServiceLB(klipper-lb) | ServiceLBはあるが デフォルトで無効 | バンドルなし(ドキュメントに明示的な記載は未確認) |
| ストレージクラス | local-path | なし(実測値) | なし(CSIで直接導入) |
| DNS | CoreDNS | CoreDNS(+オートスケーラー) | CoreDNS |
| metrics-server | あり | あり | あり |
| デフォルトCIDR(ポッド・サービス) | 10.42/16 · 10.43/16 | 10.42/16 · 10.43/16(実測値) | 10.244/16 · 10.96/12 |
RKE2のイングレスはバージョンによって仕様が異なるため注意が必要です。ingress-nginxのサポート終了が2026年3月に控えているため、RKE2ではv1.36以降の新規クラスターにおけるデフォルトがTraefikに変更されました。サービスのドキュメントではv1.36でingress-nginxが非推奨(deprecated)として残り、v1.37で削除されると記載されていますが、v1.37のリリースノートにはTraefikと併用するマイグレーション用の組み合わせのみが残ると記載されています(2026-10-13確認)。 すでに稼働しているクラスターは、アップグレードしてもそれまで使用していたイングレスが維持されます。 そのため、「RKE2のイングレスは何なのか」という問いに対する答えは、クラスターを最初に作成したバージョンを知る必要があります。TT Labのハンズオン用VM(v1.36.4+rke2r1)でも、デフォルトのイングレスクラスはtraefik、CNIはcanal、ストレージクラスはなしでした(実測値)。
これに対してk3sは、「すべて詰め込んでおいて、不要なら無効化してもらう」という方針です。 --disable に traefik, servicelb, local-storage, metrics-server, coredns を指定できます。よくある間違いは、 kubectl delete でTraefikを削除することです。k3sは起動するたびにデフォルト構成要素のマニフェストを再適用するため、再起動するとTraefikが復活します。ハンズオンでは、 systemctl restart の実行後、わずか20秒でTraefikのDeploymentが復活しました(実測値、v1.35.8+k3s1)。無効化するには、すべてのサーバーに --disable を同時に指定する必要があります。
k0sは「何も含めず、ユーザーに選択させる」という方針です。READMEのスコープセクションには、イングレス、サービスメッシュ、ストレージはバンドルされていないと記載されており、MetalLBやTraefil、OpenEBSなどは例としてのみ紹介されています。実際にサービスをデプロイするクラスターにおいては、このアプローチの方がメリットがあります。デフォルトで含まれている機能は、何らかの理由でそれに依存している場合に初めて存在に気づくものであり、その時点から不要なものを排除する方が手間がかかるためです。
6. CIDRは似て非なるもの
最後の行が、思いがけないトラブルを引き起こします。k0sのデフォルトCIDR(ポッド 10.244/16、サービス 10.96/12)は、標準的なKubernetesでよく使用される値と同じです。サービスCIDRはkubeadmのデフォルト値であり、ポッドCIDRはflannelのサンプルで広く普及した値です。そのため、k0sを別のKubernetes上のVM内にデフォルト設定で構築すると、外側のクラスターから提供されたDNSサーバーのアドレス(外側のサービスCIDRである 10.96/12 内のアドレス)を、内側のk0sが自分のサービスIPとして誤認してしまいます。TT Labのハンズオン教材を作成する際にも実際にこの現象が発生しました(実測値)。DNSが機能せずCNIイメージの取得に失敗し、CNIがないためCoreDNSが起動しないというデッドロックに陥りましたが、画面に表示されるエラーはイメージ取得のタイムアウトのみでした。
k3sやRKE2の 10.42 / 10.43 は非標準であるため、偶然にもこの問題が回避されます。「k3sではうまくいった」という経験は設計によるものではなく偶然にすぎないという点を覚えておけば、ディストリビューションを変更する際に同じ罠を避けることができます。CIDRは初期作成時に決定されるものであり、3つのディストリビューションのいずれにおいても、作成後の変更は困難です。
TTの一言。 3つとも「単一のバイナリ」であるため双子のようによく似ていますが、中身を開けてみると、1つは一体型、1つは静的ポッド型、もう1つは完全に分離型です。障害発生時にログをどこで探すべきかも異なるため、最初に構築する際は、全体像のアーキテクチャ図を必ず頭に入れておきましょう。
参考
すべてのドキュメントは2026年10月13日に閲覧しました。docs.k3s.io および docs.rke2.io のページは2026年10月7日更新と表示されており、docs.k0sproject.io の stable は v1.36.4+k0s.1 バージョンです。
- k3s ドキュメント: https://docs.k3s.io/、アーキテクチャ https://docs.k3s.io/architecture、データストア https://docs.k3s.io/datastore、内蔵 etcd HA https://docs.k3s.io/datastore/ha-embedded、外部 DB HA https://docs.k3s.io/datastore/ha、ネットワーク https://docs.k3s.io/networking/basic-network-options、デフォルトサービス https://docs.k3s.io/networking/networking-services、パッケージ構成要素 https://docs.k3s.io/installation/packaged-components
- k3s リポジトリ: https://github.com/k3s-io/k3s (README,
pkg/agent/containerd/containerd.go)、CNCF プロジェクトページ https://www.cncf.io/projects/k3s/ - RKE2 ドキュメント: https://docs.rke2.io/、アーキテクチャ https://docs.rke2.io/architecture、内蔵 etcd https://docs.rke2.io/datastore/embedded、外部 DB https://docs.rke2.io/datastore/external、HA https://docs.rke2.io/install/ha、ネットワーク https://docs.rke2.io/networking/basic_network_options、デフォルトサービス https://docs.rke2.io/networking/networking_services、v1.37 リリースノート https://docs.rke2.io/release-notes/v1.37.X
- RKE1 サポート終了のお知らせ (SUSE): https://suse.com/c/rke-end-of-life-by-july-2025-replatform-to-rke2-or-k3s
- k0s ドキュメント: https://docs.k0sproject.io/stable/、アーキテクチャ https://docs.k0sproject.io/stable/architecture/、構成 https://docs.k0sproject.io/stable/configuration/、HA https://docs.k0sproject.io/stable/high-availability/、CPLB https://docs.k0sproject.io/stable/cplb/、NLLB https://docs.k0sproject.io/stable/nllb/、ネットワーク https://docs.k0sproject.io/stable/networking/、FAQ https://docs.k0sproject.io/stable/troubleshooting/FAQ/
- k0s リポジトリ: https://github.com/k0sproject/k0s (README,
pkg/constant/constant.go)、ホームページ https://k0sproject.io/、CNCF プロジェクトページ https://www.cncf.io/projects/k0s/ - 実測値: TT Lab「Kubernetesディストリビューション — 自力で構築する」コースのハンズオンVM記録 (k3s v1.35.8+k3s1、RKE2 v1.36.4+rke2r1、k0s v1.36.4+k0s.0、2026-09-15 など)