自宅KubernetesをTalos Linux + Cloudflareベースに刷新した
こんにちは、whywrite.it 自宅サーバ班のwhywaita です。
自宅の Kubernetes クラスタを作り直しました。このブログ(blog.whywrite.it)もいまは新しいクラスタの上で動いています。
これで数年ぐらいは戦えるかなという気持ちになったので、記事に起こしておきます。
自宅に Kubernetes があると便利
自宅 Kubernetes 自体は以前から持っていて、kubeadm で立てたクラスタもかれこれ6年目ぐらいに突入しました。
自宅に Kubernetes があって何が便利かというと、「ちょっと作ったものを置く場所」に困らないことに尽きます。
- 趣味で作った Web アプリや bot をとりあえず動かしておける
- CronJob で定期実行したいバッチを気軽に増やせる
- PostgreSQL や MySQL が欲しくなったら operator に頼めば生えてくる
- 置き方がどれも同じ(Deployment、Service、HTTPRoute)なので、何を置いても管理の手間があまり変わらない
最近は AI のおかげで個人のソフトウェアを作るコストが下がり、作ったものの置き場所の方がボトルネックになりがち。(2026年6月のwhywaitaのAI現在地 でも少し書きました)作るたびに PaaS を選んで契約して……とやるより、「とりあえず自宅のクラスタに置く」で済むのは自宅のリソースも有効活用できるし便利。
最近はPCパーツ価格もだいぶ値上がっているのでこの辺はちょっとネックかな……安いときに買ってあったIntel NUCやThink Centreあたりでもう少し戦えそうなのでこのあたりで回す予定です。
いま載っているのは、このブログ(WordPress)、mstdn.uec.tokyo(Mastodon)、whywaita.com、細かい Web アプリがいくつかと CronJob 。
このタイミングでMastodonのバージョンアップを久しぶりに実施しました。
ミニPC 1台で動かしている
ハードウェアは ミニ1 台。control plane と worker を兼ねた 1 ノード構成で、etcd も 1 メンバのみ。
1 台構成なので、当然ノードが落ちればクラスタごと止まる。OS の upgrade でも全部止まる。自宅のサービスなのでそこは割り切っていて、その代わりに復旧の手段をちゃんと持つことでどうにかしました。
- etcd の snapshot を 6 時間ごとに Cloudflare R2 へ置く
- PostgreSQL(CloudNativePG)と MySQL(MOCO)のバックアップも R2 へ置く
- Secret の正本は Google Cloud Secret Manager に置き、External Secrets Operator で同期する
- クラスタの構成は全部 Git にあり、Argo CD が同期する
最悪ミニPCが壊れても、新しいマシンに OS を入れて Argo CD を入れれば、あとは Git から全部生えてくる……はず。
実際、構築途中でハードウェアを載せ替えた(ラズパイベース→ミニPC)ときは etcd の restore ではなく新規に bootstrap させたものの、Argo CD が 14 個の Application を同期して 10 分くらいで全部 Healthy になることを確認出来ました。
構成要素をざっと挙げるとこんな感じ。
- OS: Talos Linux
- SSH の無い Kubernetes 専用 OS。全部
talosctlの API で操作する
- SSH の無い Kubernetes 専用 OS。全部
- CNI: Cilium
- kube-proxy replacement、Gateway API、Hubble
- GitOps: Argo CD + Kustomize
- Storage: QNAP の NAS を iSCSI で
Ingress は使わず Gateway API に寄せていて、アプリを公開するときは HTTPRoute を書くだけで良いようにしておきました。
インターネット公開は Cloudflare
外部公開の経路は全部 Cloudflare に寄せることにしました。ここが今回こだわったポイント。
旧クラスタは DNS → VPS(Caddy)→ VPN → 自宅の ingress-nginx という経路を自作で作っていましたが、新しいクラスタでは VPS もポート開放も不要、1台で全てを完結することができました。
どこからでもインターネット経由で Cloudflare に来てもらい、そこから自宅に入ってきます。

cloudflared が自宅から Cloudflare へ outbound で接続するので、自宅側でポートを開けるなどの作業は不要です。
Tunnel の手前には Cloudflare Worker を挟んでいます。Worker からは Workers VPC の binding で、Tunnel の先にある Cilium Gateway に直接 fetch() させています。いまの Worker はほぼ素通しで、Host ヘッダをそのまま Gateway に渡すだけ。どのアプリにルーティングするかは Kubernetes 側の HTTPRoute で決めているので、ロジックはほぼ自宅にあります。
DNS レコードと edge 証明書は Worker の Custom Domain に任せていて、HTTPRoute に書いた hostname を Custom Domain として登録する controller を自作しました。
なので新しいアプリを公開するときは HTTPRoute を 1 枚マージすれば、DNS も証明書も勝手にできあがるようになっているので、全自動で動いてくれます。
public と admin で入口を分けている
自宅クラスタには、誰に見られてもいいもの(ブログや Mastodon)と、自分しか触ってはいけないもの(Argo CD や Grafana、Hubble UI)が同居しているので、ここは入口ごと分けました。
- public: public Worker → public-gateway。
exposure=publicの label を付けた namespace の HTTPRoute だけを受け付ける - admin: Cloudflare Access → admin Worker → admin-gateway。
exposure=adminの namespace の HTTPRoute だけを受け付ける
Cilium の Gateway を 2 つ立て、それぞれの Listener の allowedRoutes で受け付ける namespace を絞っています。管理系の namespace には exposure=public を付けないので、うっかり HTTPRoute の向き先を間違えても管理画面が public 側に出ることはないようにしています。
admin 側は手前に Cloudflare Access がいて、許可したメールアドレスで認証しないと Worker にすら到達しません。VPN をつながなくても外から Argo CD を開けるのはかなり便利で、出先でスマホから管理用のUIを開くことができます。
どちらも HTTPRoute を書けば展開できる、というのは同じ。public か admin かは、HTTPRoute をどちらの Gateway にぶら下げるかと、namespace の label だけで決まります。
Worker は同じコードを binding(向き先の VPC Service)だけ変えて 2 つ deploy していて、Tunnel と cloudflared は共通化されています。
Cloudflare のマネージドサービスも使える
リクエストが必ず Worker を通るので、必要になったら Cloudflare のマネージドサービスをすぐ使えるようになっています。たとえば、
- 静的なファイルは R2 から返して、動的な部分だけ自宅に流す
- KV や D1 を使った処理を Worker 側に置く
- Queues や Cron Triggers で非同期処理を Cloudflare 側に寄せる
といったことを、アプリ単位で「ここは Cloudflare、ここは自宅」と選択可能。
自宅の NUC 1 台で持てないもの(グローバルな配信や、ノードが落ちても動いていてほしいもの)は Cloudflare に任せて、状態を持つものやリソースを食うものは自宅に置く、という使い分けができるようになっています。
いまのところ Worker に書いた例外は、他人の zone にある hostname(Cloudflare for SaaS の custom hostname)を自分の hostname に読み替える処理くらいで、アプリ固有のロジックはまだ何もないものの、入口が Worker になっていることで選択肢を後から足せるのは良い落とし所になったかなと。
所感
- 自宅 Kubernetes は、作ったものの置き場所として相変わらず便利。AI でものを作るコストが下がったぶん、むしろ価値が上がっている気がする
- 1 台構成は割り切ればかなり快適。冗長化するより、Git とバックアップから作り直せる状態を保つ方が自宅には合っていた
- スペックが足りなくなれば足せばええんや
- Cloudflare の前段に Worker を置き、public と admin で入口を分ける構成は、公開の手軽さと安全さのバランスが良い。Worker は今は素通しでも後から効いてきそう
ちなみに、今回の設計・実装・運用はほとんど AI Agent(hermes-agent / Claude Code / Codex / OpenCode)にやってもらっています。自分は方針を決めて PR をレビュー・マージし、物理作業と破壊的な操作(ディスクの wipe やクレデンシャルの発行など)だけやりました。
Git が正本で Argo CD が同期する構成は、AI Agent が間違えても PR で止められてすぐ戻せるので、任せる相手としても相性が良かったですね。設計ドキュメントを書き始めてから旧クラスタを止めるまで 実働だと余暇があった1週間くらいで、自分の手だけでやっていたらたぶんまだ終わってないでしょう。
冗長化するというよりはシンプルにKubernetesを使ってハードウェアを仮想化しつつアプリケーションを動かせて、もしハードウェア故障があってもAI Agentがあれば復旧できそうな感じがします。これがすごく便利。
AI Agentが発展してきて自宅サーバの面倒なところを全部やってくれるようになったので、また新しいおもちゃなどが完成したら記事にしたいと思います。