TT Lab
ブログ

한국어 English 日本語 中文

はじめる
ブログ

ブログ

k3s・RKE2・k0sのセキュリティと運用:CIS・FIPSのデフォルト値、アップグレード、エアギャップ、バックアップ

ステータス:下書き(2026-10-13)、公式ドキュメント基準+一部実測。 セキュリティのデフォルト値と運用手順は、2026-10-13時点の公式ドキュメントを開いて確認しました。「実測」はTT Labコースの実習VMで遭遇した結果であり、バージョンを併記しています。3つのディストリビューションに同じ検証ツール(kube-benchなど)を実行して合格数を比較する実験は行っていません(未実測)。 作成規則:実測データが基本であり、測定できなかったものは「未実測」、ドキュメントで見つからなかったものは「未確認」と表示します。

目次

1. セキュリティのデフォルト値一覧

第1部で見た構造の違いは、セキュリティにおいてさらに大きく広がります。まずは表で確認します。

項目 k3s RKE2 k0s
CISベンチマーク デフォルトで多くの項目をパス、残りはハードニングガイドに従って手動設定 profile: cis により大部分が自動適用、ホストの準備はオペレーターの責任 kube-benchの k0s-1.0 ベンチマークをいくつかの例外を除いてパスするとドキュメントに記載
FIPS 140 公式ドキュメントで見つからず(未確認) FIPS 140-2、Go BoringCryptoビルド オープンソース版は対象外、商用契約でのみ提供
SELinux k3s-selinux ポリシー、 --selinux で有効化 rke2-selinux ポリシー、RPMインストール時は自動 ワーカーのcontainerdで有効化する手順あり
ポッドセキュリティ(PSA)デフォルト 別途設定しない場合はKubernetesのデフォルト(privileged) デフォルトはprivileged、cisプロファイルの場合はrestricted k0s自体のデフォルト値はドキュメントになし(未確認)
コントロールプレーンの実行ユーザー 単一プロセス デフォルトはroot、cisプロファイルの場合はetcdを etcd ユーザーに変更 etcd・apiserver・scheduler・konnectivityをそれぞれ別々のユーザーで実行
その他 監査ログ・シークレット暗号化は手動で有効化 ビルドパイプラインでTrivyによるCVEスキャンを実施 テレメトリーがデフォルトで有効(実測、v1.36.4)

表だけを見るとRKE2が優れているように見えますが、3つのディストリビューションが目指すものが異なるだけです。それぞれのディストリビューションが何を自動で行い、何をオペレーターに委ねるかが核心です。

2. k3s:大部分は適用済み、残りはガイド通りに

k3sのハードニングガイドは、デフォルト設定だけでも多くのCISコントロールをパスするが、すべてではないという前提から始まります。k3sはホストOSを変更しないため、ホスト側の設定はオペレーターが行います。ガイドが要求するのは大体以下の通りです。

ガイドにすべて従っても、人間が判断しなければならない項目がいくつか残るとドキュメントに明記されています。FIPSはドキュメントに見当たりませんでした。 docs.k3s.io/security/fips は404であり、セキュリティセクションのリストにもありませんでした(2026-10-13)。FIPSが必要な場合は、k3sではなくRKE2を見るべきだと解釈するのが安全です。

SELinuxはサポートされています。インストールスクリプトが互換性のあるシステムで k3s-selinux RPMをインストールし、 --selinux フラグまたは設定ファイルで有効にします。ただし、SELinux環境下ではデータディレクトリを変更する --data-dir はサポートされていません。

3. RKE2:1行で有効化するが、ホストの準備が必要

RKE2のセキュリティデフォルト値は profile: cis の1行に集約されています。Kubernetesのバージョンに応じたCISベンチマークに従い(ガイド基準でv1.35以上はCIS v2.0)、有効にすると次のような動作が発生します。

オペレーターに委ねられる作業は2つあります。成果物に含まれるCIS用のsysctlファイルを /etc/sysctl.d/ に配置すること、そして etcd システムユーザーを作成することです。自動修正せずに停止する方針をとっている理由は、ディストリビューションがホストの設定を勝手に変更すると、同じホスト上の他のソフトウェアを壊してしまう可能性があるためです。

実測:稼働中のクラスターでcisを有効にすると起きること

TT LabのRKE2実習(v1.36.4+rke2r1、2026-09-15)において、デフォルトプロファイルで稼働していたサーバーに profile: cis を追加して再起動しました。順番に次のような現象が発生しました(実測)。

  1. missing required: user: unknown user etcd により起動が拒否されました。予想通りの挙動です。
  2. systemctl stop で停止させ、etcdユーザーとsysctlを準備して再起動したところ、今度はetcdがデータベースファイルを開けずにパニック(panic)を起こしました。
  3. 原因は第1部で確認した静的ポッドでした。 systemctl stop の後もrootとして稼働し続ける古いetcdコンテナが残っており、新しく起動したRKE2が送信したデフラグ要求をその古いetcdが受け取り、dbファイルをroot所有者として再書き込みしてしまいました。その結果、 etcd ユーザーとして起動した新しいetcdはそのファイルを開くことができませんでした。
  4. rke2-killall.sh で残っていたコンテナまで停止させてから起動したところ、9秒でAPIの準備が完了し、RKE2がデータディレクトリの所有権を自動的に修正しました。

PSA側にも罠がありました。デフォルトプロファイルにおけるPSAの設定ファイルはenforce privilegedであり、特権ポッドがそのまま起動していました。cisに変更した後は同じマニフェストは新しい名前空間で拒否されましたが、 すでに起動していた特権ポッドはRunningのまま でした(実測)。PSAは作成要求のみを検証するためです。プロファイルを有効化した日は何事もなく過ごせますが、そのポッドを再デプロイする日にブロックされます。

教訓は2つあります。cisプロファイルは 最初に構築する際 に有効化します。後から有効化する必要がある場合は、サービスを停止するだけでなく、静的ポッドまで停止してから有効化します。

FIPSとSELinux

RKE2のFIPS 140-2サポートは、GoコンパイラのBoringCryptoモジュール(NIST認証番号4407)でビルドされたバイナリによって提供されます。ドキュメントには140-2のみ記載されており、140-3言及はありませんでした(未確認)。CNIのうちFIPS用にリビルドされるのはcanalであると記載されていますが、同じページのコンポーネントリストにはCalicoもあり、ドキュメント内で矛盾する部分があります。FIPS監査を控えている場合は、採用するCNIをSUSEに直接確認することをお勧めします。

SELinuxには rke2-selinux ポリシーと selinux: true が必要であり、RPMでインストールする場合は両方とも自動的に処理されます。tarballインストールの場合は手動で行います。

4. k0s:ユーザーを分離し、残りを揃える

k0sは別のアプローチでセキュリティに挑みます。第1部で見たように、コントロールプレーンのコンポーネントをプロセスごとに異なるシステムユーザーで実行し、コントローラーノードにはkubeletやコンテナランタイムが存在しないため、ワークロードがコントロールプレーンの隣に配置されることはありません。

CISドキュメントには、kube-benchの k0s-1.0 ベンチマークでチェックすると、デフォルト状態でいくつかの例外を除いてパスすると記載されています。例外として挙げられているのは、EventRateLimit、AlwaysPullImages(エアギャップ環境と競合)、監査ログと監査ポリシー、暗号化プロバイダー、protect-kernel-defaults、kubeletサービスファイルの項目などです。合格・不合格の数はドキュメントに記載されていません。

FIPSはオープンソースプロジェクトの範囲外です。2025-12にマージされた変更(PR #6777)でREADMEからFIPSへの言及が削除され、その理由として説明されています。ホームページには「要望と商用契約」がある場合に提供すると記載されています。

PSAは spec.api.extraArgs を使用してAdmissionConfigurationを渡す方法が案内されています。例のデフォルト値はprivilegedですが、k0s自体のデフォルトレベルを直接記述した文は見つかりませんでした(未確認)。

もう1つ、 テレメトリーがデフォルトで有効になっています。 TT Labの実習VM(v1.36.4+k0s.0)において、 k0s config create のデフォルト出力にtelemetryが有効であることが示されました(実測)。外部へメトリクスを送信してはならない環境の場合は、設定で無効化してから開始します。

5. インストール

k3s RKE2 k0s
デフォルトインストール get.k3s.io スクリプト get.rke2.io スクリプト(tarballまたはRPM) get.k0s.sh で取得し、 k0s install controller
複数ノードを一度に ノードごとにスクリプト+トークン ノードごとにスクリプト+トークン k0sctl:設定ファイル1つでSSH経由でインストール・参加
kubeconfig /etc/rancher/k3s/k3s.yaml /etc/rancher/rke2/rke2.yaml k0s kubeconfig admin で取得
kubectl 同時にインストール /var/lib/rancher/rke2/bin(デフォルトのPATH外) k0s kubectl(別途インストールなし)

k3sとRKE2は「スクリプトをノードごとに実行する」という同じモデルです。実習において、k3sはインストールの所要時間が8秒、ノードのReadyまでが11秒でした(実測、v1.35.8+k3s1、VM起動後から計測)。

k0sの差別化要因はk0sctlです。ホストのリストと役割を記述した k0sctl.yaml を1つ用意し、 k0sctl apply を実行するとSSHで各ホストにログインしてインストールと参加を行います。ノードの追加は可能ですが、削除はk0sctlでは行えないとドキュメントに記載されています。

RKE2のインストールスクリプトには、環境に依存する部分が1つあります。 /usr/local が読み取り専用であるか、別のマウントポイントである場合は、 /opt/rke2 に展開します。実習VMはルートディスクが小さく、インストーラー(128M、実測)がルートをほぼ満杯にしそうになったため、 INSTALL_RKE2_TAR_PREFIX で配置場所を指定する必要がありました。

6. アップグレード

① k3s · RKE2 — system-upgrade-controller 의 Plan 둘 Plan: server channel 또는 version Plan: agent prepare 로 server 를 기다림 서버를 하나씩(concurrency 1) (cordon) → 바이너리 교체 → 재시작 서버가 다 끝난 뒤 시작 동시에 몇 대씩 할지 정한다 수동이면 설치 스크립트를 판을 지정해 다시 돌린다. 실측(k3s 1.34→1.35): 교체 11초, 노드 Ready 12초, 파드 그대로 ② k0s — autopilot 의 Plan 하나 Plan: autopilot (이름이 반드시 autopilot) k0supdate: 바이너리 교체 · airgapupdate: 이미지 번들 교체 컨트롤러를 하나씩 매번 전부 /ready 인지 확인 그다음 워커 기본 동시성 1 k0sctl 로 SSH 를 건너 바깥에서 올리는 길도 있다. 공통: 컨트롤 플레인 먼저. k3s·RKE2 문서는 마이너 판 건너뛰기를 금한다.
図:k3s・RKE2のsystem-upgrade-controllerとk0s autopilotのアップグレード順序

k3sとRKE2 は同じツールを使用します。手動の場合は、バージョン(INSTALL_K3S_VERSION など)やチャネルを指定してインストールスクリプトを再実行します。この際、初回インストール時に渡した引数を再度指定しないと失われてしまうため、設定はコマンドライン引数よりも設定ファイルに記述する方が安全です。自動化の場合は system-upgrade-controller に Plan を配置します。サーバー用 Plan がサーバーを1台ずつアップデートし、エージェント用 Plan は prepare の段階でサーバー用 Plan が終了するのを待ってから開始します。Plan に channel を指定すると新しいバージョンに追従し、 version を指定するとそのバージョンに固定されます。両方のドキュメントとも、マイナーバージョンをスキップしないよう記載されています。

検証において、k3s v1.34.11 を v1.35.8 にスクリプトでアップデートした際は11秒、ノードの Ready まで12秒であり、実行中の Pod は UID・コンテナID・再起動回数までそのまま維持されていました(実測値)。しかし、同じ検証で見落としがちな点も確認されました。 stable チャネルは当日(2026-09-15)すでに v1.36 を指しており、1.34 からチャネルに追従すると マイナーバージョンを2つ一度にスキップする ことになります。インストールスクリプトも Plan CRD もそれを防ぎませんでした(実測値)。自動アップグレードには、チャネルよりもバージョンの固定を推奨します。

k0s はバイナリを置き換えて再起動するのが基本であり、自動化は autopilot が担当します。必ず autopilot という名前の Plan 1つに、何を変更するか(k0supdate でバイナリ、 airgapupdate でエアギャップイメージバンドル)を記述します。autopilot はコントロールプレーンを1台ずつアップデートしながら毎回すべてのコントロールプレーンの準備ができたことを確認し、そのあとでワーカーを基本的に1台ずつアップデートします。バイナリの sha256 検証を設定することも可能です。外部から SSH でアップデートしたい場合は k0sctl を使用します。

7. エアギャップインストール

インターネット環境のない場所に構築する方法は、3つともほぼ同様です。バイナリと イメージバンドルを事前に転送し、指定されたフォルダに配置するか、プライベートレジストリを使用します。

イメージの配置先 その他の方法
k3s /var/lib/rancher/k3s/agent/images/ プライベートレジストリ + registries.yaml、内蔵分散ミラー(Spegel)
RKE2 /var/lib/rancher/rke2/agent/images/ プライベートレジストリ + registries.yaml、Hauler、内蔵ミラー
k0s ワーカーの /var/lib/k0s/images/ k0s airgap list-images でリストを取得して手動でバンドル

転送すべきデータ量は、第3回のリソース表における GitHub リリースファイルのサイズで比較できます。あらかじめお伝えすると、RKE2 が最も容量が大きくなります。バイナリだけでなく、kubelet や containerd を含むランタイムイメージと CNI イメージを一緒に転送する必要があるためです。

8. バックアップとリストア

k3s RKE2 k0s
デフォルトストレージのバックアップ SQLite: server/db/ フォルダのコピー etcd スナップショット自動 k0s backup(etcd または kine/SQLite)
自動スナップショット etcd の場合12時間ごとに5個保存 12時間ごとにサーバーあたり5個保存 ドキュメントで見つからず(未確認)
S3へ送信 --etcd-s3* --etcd-s3* - を標準出力に出力して直接
リストア --cluster-reset --cluster-reset-restore-path 同等の方式 k0s restore <파일>
一緒に保管すべきもの サーバートークン サーバー トークン バンドルに PKI を含む

k3s と RKE2 は トークンを必ず一緒に保管する必要があります。スナップショット内のブートストラップデータ(CA などの機密情報)をトークンで暗号化するため、別のホストに復元する際にトークンがないとスナップショットを使用できません。

k0s のバックアップバンドルには、PKI、etcd スナップショット(または kine/SQLite スナップショット)、 k0s.yaml、マニフェスト、イメージ、Helm 設定が含まれます。除外されるのは、PV データと、kine の背後に 外部 MySQL・PostgreSQL を配置した場合のデータです。その DB は DB 側で個別にバックアップします。

実測:復元コマンドが成功したのに何も戻らなかった

TT Lab の k0s 実習で最も危険だった場面です。 k0s stop の直後に k0s restore <파일> を実行して再起動すると、コマンドはエラーも警告もなく終了し、クラスターも立ち上がるものの、 バックアップ作成後に作成した ConfigMap がそのまま残っていました(実測)。etcd はデータディレクトリがすでに存在する場合はそれを使用し、展開したスナップショットを無視するためです。手順の順序は k0s stop → 既存の etcd データのクリア → k0s restore → k0s start であるべきでした。復元できたと錯覚してしまうことが最も危険です。バックアップは、復元をテストしてみて初めてバックアップと言えます。

k3s の復元は結果がより明確でした。 --cluster-reset で復元すると 6 秒でリセットされ、起動から 11 秒で API が復旧し、スナップショット以降の変更は消去され、以前の DB は etcd-old-<시각> フォルダに残りました(実測、v1.35.8+k3s1)。

ティティの一言。 セキュリティスイッチをオンにするのは 1 行ですが、その 1 行が立つ土台(ホストの準備)は人が作らなければなりません。そして、バックアップは必ず一度復元してみてください。「成功」と表示されたのに何も戻らなかったことが実際にありますから。

参考

すべてのドキュメントは 2026-10-13 に閲覧しました。

ログインするといいねできます

コメント

まだコメントはありません。

ログインするとコメントできます