Skip to main content

K3sのHelmChart CRDで配ったアプリを直接helm upgradeしたら、次のreconcileで設定が消えた

1. 本番でHelmリリースを直接upgradeしたら、翌朝設定が消えていた

K3sクラスタ上でHelmChart CRDから配布していたアプリケーションに、緊急のパラメータ変更が必要になった。helm upgrade --set で直接値を書き換え、Podが正しい設定で立ち上がったことを確認して作業を終えた。

section01

ところが翌朝、ノードの定期メンテナンスでクラスタが再起動した後、設定は昨日のupgrade前の状態に戻っていた。helm history を見てもリビジョンは上がっているのに、実際に動いているPodの中身は古いままだった。K3sとKubernetesの違いを調べていくと、原因は自分のミスではなく、K3sだけに存在する「HelmChart CRD」という自動化レイヤーにあることが分かった。

こうした「クラスタが裏で何を自動化しているか分からない」という不安は、K3sベースのマネージドサービスを選ぶときにも見落とされがちな観点だ。Kuboのように運用の透明性を訴求するサービスもあるが、まずはK3s自体の仕組みを理解しておく必要がある。

2. K3sだけに存在する3層構造: HelmChart CRD → helm-controller → Kubernetes Job

vanilla Kubernetesで helm install を使う場合、Helmクライアントがチャートをレンダリングし、Kubernetes APIに直接リソースを作成する。そこには「宣言的な監視者」は存在せず、次に誰かが helm upgrade するまで状態は変わらない。

K3sはこれとは別に、独自のHelm Controllerを同梱している。K3sの公式ドキュメントによれば、K3sは HelmChart というCustom Resource Definition(CRD)を使って、Helmチャートのインストール・アップグレード・アンインストールを宣言的に管理する仕組みを持つ。組み込みのTraefikやServiceLBだけでなく、任意の自作Helmチャートをこの仕組みで自動デプロイすることもできる。

section02

つまりK3sでは「HelmChart CRD(宣言)→ helm-controller(監視)→ Kubernetes Job(実行)」という3層構造がバックグラウンドで常に動いている。k3s-io/helm-controllerのフィールドリファレンスには chartContent や valuesContent など多数の設定項目があるが、「CRDの外側で加えられた変更がどう扱われるか」については明記されていない。これがトラブルの温床になる。

3. 何が起きていたか: failurePolicyとJobの再実行トリガー

K3s公式ドキュメントには failurePolicy という設定があり、デフォルトは "reinstall" となっている。これはJobが失敗と判定された場合に、クリーンなアンインストール→再インストールを自動実行する挙動だ。"abort" に切り替えない限り、helm-controllerは「desired state(HelmChart CRDの内容)」と「actual state(クラスタの実際の状態)」の差分を検知するたびに、Helm操作を伴うJobを再実行する。

この挙動は実際に複数の障害報告として上がっている。k3s-io/helm-controllerのIssue #50では、チャートのバージョンが変わっていないにもかかわらず、helm-controllerが繰り返しinstall Jobを再トリガーし、新しいリビジョンを生成し続けるという事象が報告されている。ログには DesiredSet - Replace Wait batch/v1, Kind=Job という記録が残り、コントローラーがJobリソースの置き換えを継続的に検知していたことが分かる。

section03

さらにk3s-io/k3sのIssue #2893では、HelmChartConfig でTraefikのカスタム設定(ダッシュボード有効化やTLS設定)を加えていたユーザーが、「K3sやホストを再起動するたびに、このカスタマイズが読み込まれず、デフォルト設定が適用される」と報告している。この報告では、マニフェストファイルに空白や改行を加えて強制的に再読込させることで一時的に回避したとされている。手動での kubectl edit はこの3層構造から見れば「一時的にしか残らない差分」でしかない。

このJobの再実行トリガーを管理画面上で追えるかどうかは、運用のしやすさに直結する。KuboのCaptain UIは、こうしたバックグラウンドで動くJobやHelmリリースの状態を可視化する機能を持ち、「気づいたら設定が戻っていた」状態を減らす方向で設計されている。

4. 落とし穴その2: HelmChartConfigを消してもロールバックされないリソースがある

さらに厄介なのは、reconcileの挙動が全てのリソース種別で一貫していない点だ。k3s-io/k3sのIssue #5534では、TraefikのポートをHelmChartConfigでカスタムポート(1234/5555)に変更した後、そのHelmChartConfigを削除しても、LoadBalancerタイプのServiceとklipper-lb Podはカスタム値のまま元に戻らなかったと報告されている。

つまり「HelmChartConfigを外せば必ず元通りになる」という前提も安全ではない。SUSEコミュニティフォーラムやk3s-io/k3sのDiscussion #11176にも「HelmChartConfigを当てたのに反映されない、あるいは想定通りに戻らない」という相談が繰り返し寄せられている。K3sのHelm Controllerは起動時に /var/lib/rancher/k3s/server/manifests/ を監視してJobを生成する仕組みであり、姉妹プロジェクトであるRKE2の公式ドキュメントでも「manifestsディレクトリ配下のマニフェストはAddOnカスタムリソースとして自動デプロイされる」と同様の仕組みが説明されている。それでもなお、リソース種別ごとの差分検知ロジックが必ずしも直感的ではない。

5. 正しい直し方: HelmChartConfig経由の変更とfailurePolicy: abort

この構造を踏まえると、K3s上でHelmChart CRD管理下のアプリやアドオンを変更する際のルールは明確になる。

  • kubectl edit や helm upgrade --set で直接変更しない。次のreconcileで消える前提で考える
  • 変更は必ず HelmChartConfig の valuesContent 経由で行う。これは helm-controller が正式な入力として認識するため、reconcileされても消えない
  • 意図しない自動再インストールを避けたい場合は failurePolicy: abort を設定する。失敗時にクリーン再インストールせず、失敗状態のまま止めて手動介入を待つようになる
  • HelmChartConfigを削除するときは、対象リソースが実際に既定値へ戻るか個別に確認する(Issue #5534のように戻らないリソース種別があるため)

section04

これはK3sを「軽量なKubernetes」としてだけ理解していると見落としがちな挙動だ。k3s-io/helm-controllerのIssue #351でも、reconcileロジック自体の改善要望が継続的に議論されており、この構造は今後も注意深く付き合っていく必要がある領域だと分かる。

6. Kuboならどうなるか

K3sベースのKuboを使っていても、このHelmChart CRDの仕組み自体は同じK3sの標準機能として存在する。違いは、この「見えない自動化レイヤー」がブラックボックスのまま放置されるか、可視化された状態で運用できるかだ。

Kubo Captain UIは、クラスタ内で自動的に走っているHelm ChartやJobの状態を管理画面上で確認できるように設計されており、「知らないうちにreconcileが走って設定が戻っていた」という事態に気づきやすくする。EKSやAKSでは触れないK3s内部の自動化を、Kuboならブラックボックスにせず運用できる。

また、Air-Gapped環境で /var/lib/rancher/k3s/server/manifests/ の手動編集すら難しい金融・医療・製造業向けには、Kubo On-Premiseが「Your Infrastructure. Your Rules.」の思想でこの運用課題に向き合う選択肢になる。

7. まとめ

K3sとKubernetesの違いは、レプリカセットやネットワーキングの実装だけではない。K3sが同梱するHelmChart CRD + helm-controller + Kubernetes Jobという3層の自動化構造は、vanilla Kubernetesには存在しない独自レイヤーであり、これを知らずに kubectl edit や helm upgrade で直接変更すると、次のreconcileで静かに元へ戻される。

変更は必ず HelmChartConfig 経由で行い、failurePolicy の挙動を理解した上で運用する。それがK3sクラスタを安定して本番運用するための最初の一歩だ。この自動化レイヤーを可視化しながら運用したいなら、KuboのCaptain UIも選択肢に入れてみてほしい。

Related articles

← Back to all posts