Kubernetesディストリビューション — 自分で立てる
traefik を削除したら再起動後に復活した
目標
k3sサーバーがmanifestsディレクトリのファイルをAddOnとして適用し、traefikをHelmChartとしてインストールする仕組みを、本物のk3sで確認します。 kubectlでの削除、再起動、.skip、--disable、HelmChartConfig、構成ファイルとCLIフラグの優先順位が、それぞれ何を変え、何を残すのかを記録に残します。
なぜ重要なのか
k3sは、インストール1行でIngress・DNS・メトリクスまで揃ったクラスターを提供します。その便利さは、「k3sが起動するたびにデフォルトのコンポーネントのマニフェストを書き直して適用する」という設計から生まれています。 そのため、マネージドクラスターでやっていたようにkubectlでコンポーネントを削除すると、次の再起動で静かに復活します。逆に、マニフェストファイルを削除しても、クラスターのオブジェクトは残ります。 無効にするのは--disable、ファイルだけを無視するのは.skip、値だけを変えるのはHelmChartConfigです。この3つの違いを知らないと、アップグレードやリブートの後に「誰がこれをまたインストールしたのか」を追いかけることになります。 構成ファイルも同じで、インストールスクリプトがサービスユニットに入れたフラグがconfig.yamlより優先されることを知らないと、直した値が反映されない理由を見つけられません。
ステップ
- 次のフィールドを書いてください(書き込み先:
/root/k3s-pkg/inventory.json)。version(ノードのkubeletVersion)、addons(kube-systemのAddOn名をソートした配列)、helmcharts(kube-systemのHelmChart名をソートした配列)、manifest_files(manifestsディレクトリの下にあるファイルの相対パスをソートした配列)です。 /var/lib/rancher/k3s/server/manifests/lab-banner.yamlにNamespacek3s-pkgとConfigMapbanner(ネームスペースはk3s-pkg、msg: v1)を書いて、AddOnとしてデプロイしてください。作成されたConfigMapをkubectlで削除し、20秒待って戻ってこないことを確認してから、ファイルの値をmsg: v2に変更して再び作成させてください。次のフィールドを書いてください(書き込み先:/root/k3s-pkg/banner.json)。deleted_uid(削除したもののUID)、restored_uid(再び作成されたもののUID)、returned_before_edit(ファイルを修正する前に戻ってきたかどうか、ブール値)です。- kube-systemのHelmChart
traefikをkubectlで削除し、traefik Deploymentが消えるまで待ってください(まだ再起動しません)。次のフィールドを書いてください(書き込み先:/root/k3s-pkg/gone.json)。deleted_at(削除した時刻、UTCのRFC3339形式。例: 2026-01-01T00:00:00Z)、manifest_still_there(traefik.yamlファイルがまだあるかどうか、ブール値)、release_left(残っているtraefikのリリースSecretの数、整数)です。 systemctl restart k3sでk3sを再起動し、traefik Deploymentが再びAvailableになるまで待ってください。次のフィールドを書いてください(書き込み先:/root/k3s-pkg/revive.json)。helmchart_uid(再び作成されたHelmChart traefikのUID)、helmchart_created(そのcreationTimestamp)、revived(Deploymentが戻ってきたかどうか、ブール値)です。/var/lib/rancher/k3s/server/manifests/lab-pinned.yamlでConfigMappinned(ネームスペースはk3s-pkg、v: "1")をデプロイしてください。作成されたことを確認してから、同じディレクトリにlab-pinned.yaml.skipを作成し、ファイルの値をv: "2"に変更して20秒待ってください。次のフィールドを書いてください(書き込み先:/root/k3s-pkg/skip.json)。file_value(ファイルに書かれた値)、live_value(クラスターのConfigMapの値)、addon_still_exists(AddOn lab-pinnedが残っているかどうか、ブール値)です。/etc/rancher/k3s/config.yamlはそのままにして、/etc/rancher/k3s/config.yaml.d/50-disable.yamlを作成し、metrics-serverを無効にしてください。local-storageは引き続き無効のままである必要があります。ファイルを書いた直後の20秒間、metrics-serverがそのままであることを確認してから、k3sを再起動してください。次のフィールドを書いてください(書き込み先:/root/k3s-pkg/disable.json)。changed_before_restart(再起動前に消えたかどうか、ブール値)、removed_addons(再起動で消えたAddOn名をソートした配列)、files_left(manifests/metrics-serverの下に残ったファイルの数、整数)です。/etc/rancher/k3s/config.yamlに、既存のdisableのリストを維持したままwrite-kubeconfig-mode: "0600"を追加して、k3sを再起動してください。/etc/rancher/k3s/k3s.yamlの権限がどうなったかを確認して、次のフィールドを書いてください(書き込み先:/root/k3s-pkg/precedence.json)。config_value(config.yamlに書いた値、文字列)、effective_mode(再起動後のk3s.yamlの8進数の権限、文字列。例: "640")、winner(cliまたはconfig)、flag_file(勝った値が書かれているファイルの絶対パス)です。- 再起動せずに、
/var/lib/rancher/k3s/server/manifests/traefik-config.yamlにHelmChartConfigtraefik(kube-system)を置いて、traefikのログレベルをDEBUG(logs.general.level)に変更してください。次のフィールドを書いてください(書き込み先:/root/k3s-pkg/hcc.json)。revision_before(適用前のtraefikリリースの最大のリビジョン、整数)、revision_after(適用後、整数)、log_arg(traefikコンテナの引数のうち、ログレベルの引数の全体)です。 - 次のフィールドを書いてください(書き込み先:
/root/k3s-pkg/report.json)。needs_restart(オブジェクト。manifest_file・skip_file・helmchartconfig・config_dropinのそれぞれについて、再起動が必要だったかどうかのブール値)、revived_by_restart(ステップ3・4で再起動により復活したHelmChartの名前)、disable_deletes_files(ブール値)、skip_removes_resources(ブール値)、current_addons(現在のkube-systemのAddOn名をソートした配列)、traefik_revision(現在のtraefikリリースの最大のリビジョン、整数)です。
参考
- VMの中にk3s v1.35.8+k3s1が1台あります。レシピはconfig.yamlでlocal-storageだけを無効にし、インストールスクリプトに
--write-kubeconfig-mode 644を渡しています。 - 再起動は
systemctl restart k3sです。APIは5秒前後、traefikは20秒ほどで戻ってきます(実測)。 - AddOnの確認:
kubectl -n kube-system get addon -o custom-columns=NAME:.metadata.name,SOURCE:.spec.source - よくあるミス: drop-inで
disable:を書くこと。最後の値が勝つため、config.yamlのlocal-storageが再びインストールされます。 - よくあるミス: デフォルトのコンポーネントのマニフェストファイル(traefik.yamlなど)を直接編集することです。起動時に書き直されて消えます。
- Managing Packaged Components・Helm・Configuration Options
何がAddOnとしてインストールされたかを確認する
次のフィールドを書いてください(書き込み先: /root/k3s-pkg/inventory.json)。version(ノードのkubeletVersion)、addons(kube-systemのAddOn名をソートした配列)、helmcharts(kube-systemのHelmChart名をソートした配列)、manifest_files(manifestsディレクトリの下にあるファイルの相対パスをソートした配列)です。
AddOnはk3s.cattle.ioグループのCRDで、ファイル1つがAddOn1つです。サブディレクトリのファイルもそれぞれAddOnになります。local-storageはレシピのconfig.yamlですでに無効にしてあるので、一覧にないのが正常です。
kubectlで削除したConfigMapはいつ戻るのか
/var/lib/rancher/k3s/server/manifests/lab-banner.yamlにNamespacek3s-pkgとConfigMapbanner(ネームスペースはk3s-pkg、msg: v1)を書いて、AddOnとしてデプロイしてください。作成されたConfigMapをkubectlで削除し、20秒待って戻ってこないことを確認してから、ファイルの値をmsg: v2に変更して再び作成させてください。次のフィールドを書いてください(書き込み先: /root/k3s-pkg/banner.json)。deleted_uid(削除したもののUID)、restored_uid(再び作成されたもののUID)、returned_before_edit(ファイルを修正する前に戻ってきたかどうか、ブール値)です。
デプロイコントローラーは、ファイルが変更されたときとk3sが起動したときに適用します。クラスターのオブジェクトが削除されたという事実は、適用のきっかけではありません。AddOnはファイルのチェックサムを覚えているので、touchのように内容が同じ変更もきっかけになりません。
traefikをkubectlで削除した
kube-systemのHelmCharttraefikをkubectlで削除し、traefik Deploymentが消えるまで待ってください(まだ再起動しません)。次のフィールドを書いてください(書き込み先: /root/k3s-pkg/gone.json)。deleted_at(削除した時刻、UTCのRFC3339形式。例: 2026-01-01T00:00:00Z)、manifest_still_there(traefik.yamlファイルがまだあるかどうか、ブール値)、release_left(残っているtraefikのリリースSecretの数、整数)です。
HelmChartにはhelm-controllerのfinalizerが付いていて、削除するとhelm-deleteジョブが先にリリースを削除します。Helmのリリースは、kube-systemでowner=helm,name=traefikラベルが付いたSecretとして残ります。manifestsディレクトリは、クラスターのオブジェクトを削除しても触られません。
再起動したらtraefikが復活した
systemctl restart k3sでk3sを再起動し、traefik Deploymentが再びAvailableになるまで待ってください。次のフィールドを書いてください(書き込み先: /root/k3s-pkg/revive.json)。helmchart_uid(再び作成されたHelmChart traefikのUID)、helmchart_created(そのcreationTimestamp)、revived(Deploymentが戻ってきたかどうか、ブール値)です。
k3sは起動のたびに、デフォルトのコンポーネントのマニフェストをディスクに書き直して適用します。ファイルが作ったHelmChartがなければ新しく作られ、するとhelm-installジョブが再び動きます。APIの準備ができてからtraefikが起動するまでに、20秒ほどの差があります。
.skipは削除せずに見なかったことにする
/var/lib/rancher/k3s/server/manifests/lab-pinned.yamlでConfigMappinned(ネームスペースはk3s-pkg、v: "1")をデプロイしてください。作成されたことを確認してから、同じディレクトリにlab-pinned.yaml.skipを作成し、ファイルの値をv: "2"に変更して20秒待ってください。次のフィールドを書いてください(書き込み先: /root/k3s-pkg/skip.json)。file_value(ファイルに書かれた値)、live_value(クラスターのConfigMapの値)、addon_still_exists(AddOn lab-pinnedが残っているかどうか、ブール値)です。
.skipファイルは、内容ではなく存在だけを見ます。すでに適用されたAddOnとそれが作ったオブジェクトはそのままにして、以降そのファイルの変更を無視します。
drop-in1つでmetrics-serverを無効にする
/etc/rancher/k3s/config.yamlはそのままにして、/etc/rancher/k3s/config.yaml.d/50-disable.yamlを作成し、metrics-serverを無効にしてください。local-storageは引き続き無効のままである必要があります。ファイルを書いた直後の20秒間、metrics-serverがそのままであることを確認してから、k3sを再起動してください。次のフィールドを書いてください(書き込み先: /root/k3s-pkg/disable.json)。changed_before_restart(再起動前に消えたかどうか、ブール値)、removed_addons(再起動で消えたAddOn名をソートした配列)、files_left(manifests/metrics-serverの下に残ったファイルの数、整数)です。
drop-inは名前順に読み込まれ、同じキーが複数のファイルにあると最後の値が勝ちます。リストに追加するには、キー名の末尾に+を付けます。--disableはAddOnを削除するだけでなく、元のファイルも削除します。構成ファイルは、k3sが起動するときに読み込まれます。
config.yamlを直したのに権限が変わらない
/etc/rancher/k3s/config.yamlに、既存のdisableのリストを維持したままwrite-kubeconfig-mode: "0600"を追加して、k3sを再起動してください。/etc/rancher/k3s/k3s.yamlの権限がどうなったかを確認して、次のフィールドを書いてください(書き込み先: /root/k3s-pkg/precedence.json)。config_value(config.yamlに書いた値、文字列)、effective_mode(再起動後のk3s.yamlの8進数の権限、文字列。例: "640")、winner(cliまたはconfig)、flag_file(勝った値が書かれているファイルの絶対パス)です。
構成ファイルとCLI引数が同じキーを持つ場合は、CLIが優先されます。インストールスクリプトに渡したINSTALL_K3S_EXECは、systemdユニットのExecStartに引数として保存されます。systemctl cat k3sで見てください。
再起動せずにtraefikの値だけを変える
再起動せずに、/var/lib/rancher/k3s/server/manifests/traefik-config.yamlにHelmChartConfigtraefik(kube-system)を置いて、traefikのログレベルをDEBUG(logs.general.level)に変更してください。次のフィールドを書いてください(書き込み先: /root/k3s-pkg/hcc.json)。revision_before(適用前のtraefikリリースの最大のリビジョン、整数)、revision_after(適用後、整数)、log_arg(traefikコンテナの引数のうち、ログレベルの引数の全体)です。
HelmChartConfigは、名前とネームスペースが対象のHelmChartと同じである必要があります。valuesContentはHelmChartのvaluesContentより優先され、spec.setよりは弱いです。helm-controllerがhelm upgradeを実行するので、リリースSecretが1つ増えます(sh.helm.release.v1.traefik.vN)。
削除・無視・オーバーライドを1つの表にまとめる
次のフィールドを書いてください(書き込み先: /root/k3s-pkg/report.json)。needs_restart(オブジェクト。manifest_file・skip_file・helmchartconfig・config_dropinのそれぞれについて、再起動が必要だったかどうかのブール値)、revived_by_restart(ステップ3・4で再起動により復活したHelmChartの名前)、disable_deletes_files(ブール値)、skip_removes_resources(ブール値)、current_addons(現在のkube-systemのAddOn名をソートした配列)、traefik_revision(現在のtraefikリリースの最大のリビジョン、整数)です。
前のステップで残したjsonと現在のクラスターを根拠にして書きます。採点ツールは、同じ値をクラスターと記録ファイルからもう一度計算します。