5年ほど前から自宅サーバーにKubernetesを導入し、Mastodon、Discord Bot、このブログ、自作Webサービスや各種アプリケーションをKubernetes上で動かしています。
1ヶ月ほど前に、マニフェストリポジトリをほぼ全て公開リポジトリに移行したため、内容を備忘録としてまとめました。
ハードウェアはVPS 1台と、自宅内の3台の物理マシンの計4ノードで構成されています。
学割が使えなくなる3月にMac Miniの最小構成を買ったので追加する予定なのですが、めんどくさくて放置しています。また、CPUが極端に弱いノードがあると他も不安定になる(特に後述するLonghorn)ので、ラズパイノードはそろそろ消したいですね。
自宅回線の契約プランがv4 over IPv6なため、固定のIPv4アドレスを使えません。このため、外部公開用としてVPSをノードに追加しています。
ただ、これのためだけにVPSを使うのはリソースがもったいないので、コントロールプレーンとしても働いてもらっています。一方で、VPSをコントロールプレーンにすると、値上げされた時の移行が面倒なので、そこはデメリットです。
ホストマシンのOS初期設定、ネットワーク(Netplan)、ファイアウォール(UFW)、WireGuard、およびK3sのインストールは、Ansibleで管理しています(まだ公開リポジトリにできていない)。
本当はNixOSでやりたいのですが、昔Longhorn周りでハマってAnsibleに移行してから戻れていません。
やっていることは以下あたりです。
open-iscsiといったホストにインストールが必要なパッケージの管理wg0.conf を構築inventory.yml にホスト名・WAN/LAN IP・Wireguard IP・設定したいNodeのlabelやtaintsなどを追加するだけでこれらの設定が自動的に行えるようになっています。
gitにpushしたら勝手に反映されるArgoCDより変更が面倒だし遅いので、ArgoCDで管理できない最小限のことだけ設定すると良いです。
クラスタ内のアプリケーション管理には、ArgoCDを使っています。
マニフェストリポジトリは kgtkr/public-cd で公開しています。
syncPolicy.automated.xxx の設定には気を付けましょう。
例えばargocdやlonghornを誤って削除してしまうと非常に面倒です。それらが入っている Namespace もです。消えると面倒な Application には finalizers: [] を設定したり、PVCには argocd.argoproj.io/sync-options: Prune=false を設定して何重にも保険をかけておいたほうがいいです。個人クラスタならkubectl使い放題なので、ミスってgitにpushしただけでデータ消えるみたいなのはなるべく事前に防ぎましょう。やらかして復元にN時間取られるみたいなことを過去に何度もやりました。
PVには、分散ブロックストレージであるLonghornを使っています。
Longhornではバックアップ先としてS3やNFSを設定できます。
ここでは、外部のパブリッククラウドストレージを直接指定するのではなく、同じ Kubernetes クラスタ内にデプロイした S3 互換ストレージであるMinIOをバックアップの宛先として指定しています。S3を指定するとAPIコール数が多すぎて破産します。
なお、MinIO本体のストレージには local-path を使用しています。
クラスタ内の MinIO にバックアップをとるだけでは、すべてのノードのディスクが同時に故障した際にデータが飛ぶので外部へのバックアップは必須です。
そのため、毎日rcloneを用いたバックアップ処理を CronJob で実行し、MinIO 上のバックアップデータを Google Driveに上げています。
この同期処理では以下のようなことを行っています。
volume.cfg)が一定数以上存在するかをチェックし、足りない場合は異常終了させています。これは local-path をボリュームとして使っているため、デプロイノードの変更時の事故防止です。kubectl で Kubernetes Secret に書き戻す処理を自動で行っています。かなりのCPUとネットワーク帯域を使うため、ラズパイは使わず、同じ物理LANで繋がっている2台のミニPCのみで運用しています。昔はラズパイでも有効化していたのですが、あまりに不安定だったのでやめました。
あとこれはLonghorn関係ないですが、デイリーバックアップを1ヶ月分残すみたいなのはやめましょう。夏休みにかなり時間をかけて遊んでいたマイクラサーバーを3ヶ月くらい放置していたらデータが消えて、消えたデータでバックアップも上書きされていて詰みました。こんな感じ で設定しておくと、例えば backup-daily を指定するだけで、yearly / monthly / weekly / dailyバックアップをそれぞれ適当な数保持してくれるので便利です。
これだけは Kubernetes ではなくAnsibleで管理していますが、全てのサーバーや、クライアントPC、スマホを同一のネットワークにするためにWireguardを使っています。
これにより、自宅のネットワークの固定IPや使えるポートについて気にしなくてよくなり、かなり管理が楽になります。
また、ArgoCDやLonghornの管理画面にパスワード設定ミスなどがあっても、VPN外からのアクセスを弾くことで保険にもなります。
MetalLBを用いて、アドレスプールを以下のように定義しています。
default: 自宅LANのIP(192.168.11.10 - 30)public-ips: VPSのパブリックIP(163.44.96.193/32)local-ips: VPNのIP(192.168.190.xxx/32)各 Ingress Nginx の定義で metallb.universe.tf/address-pool を使い分けることで、バインド先を動的に切り替えています。
ちなみにここらへんの設定はよくわかっていません。完全に雰囲気です。ネットワーク難しいよ~。
Ingress Nginx コントローラーは、意図しないアクセスを防ぐためにパブリック用とプライベート用で2つに分離して運用しています。
ingress-nginx (外部公開用):
nodeSelector によって VPSのノードに固定しています。163.44.96.193)を割り当ててバインドしています。これにより、インターネット経由のトラフィックを VPS 上で直接受け取ることができます。ingress-nginx-private:
https://argocd.k3s.kgtkr.net:8443/80 / 443 ポートを使うと動いたり動かなかったり、再起動すると壊れたり直ったりして不安定だったので(普通にネットワーク周りの知識不足)、 8080 / 8443 を使っています。SSL/TLS 証明書の自動発行には cert-manager を使用しています。
ingress-nginx-private には外部からアクセスできないのでチャレンジには HTTP-01 ではなく DNS-01を使用しています。
external-dnsによってIngressの変更時に自動でDNSレコードを修正しています。
cert-managerもだが、まあよくある設定です。Cloudflare DNSいつもありがとう。
自宅のグローバルIPはddclientを用いてDNSレコードを更新することでいつでも取れるようにしています。クラスタ管理に限らずRemote Desktopなどでも使えて便利です。
監視のためにdatadogや、argocd-notificationsを動かしていますが、あまり見ていない。まあ最悪落ちていてもあまり迷惑かからないものばかりなので…。datadogはかなりCPU食う(ラズパイみたいな雑魚CPUだと割合的にかなり)のでなんとかしたくはあります。
GitOpsしたいなら機密情報の管理が問題になりますが、これはSealed Secretsを使っています。
Sealed Secretsの注意点として、クラスタが飛ぶとデータの復元が不可能になる可能性があるため、各種tokenのように再発行できないもの(例: ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY)はパスワードマネージャなどにも保存しておきましょう。
コントロールプレーンのバックアップや冗長化まで考えるとやっていけないので「全てのノードのデータが飛んでもansibleのapplyとArgoCDのデプロイと少しの作業だけで復元可能か」を考えて運用するべきだと考えています。
HelmチャートやイメージのアップデートはRenovateに任せるとスマホからでもPRをマージするだけで更新できるので便利です。
バージョンタグを切るのが嫌いなので、自作のアプリケーションは masterにプッシュされると kgtkr/docker-tags-gen-action を使って 20260707061339182-24a45e3 のようなタイムスタンプ付きタグで ghcr.io にプッシュしています。renovateの設定で "versioning": "regex:^(?<minor>\\d{17})-[0-9a-f]{7}(-(?<compatibility>.*))?$" しておけば自動更新に対応できるので雑運用にはおすすめです。
ずっとやらなきゃと思っていたマニフェストリポジトリのpublic化、AIの助けもあり数年越しにできたので次はansibleリポジトリとdotfiles (nix home manager + nix darwin)の設定のpublic化目指します。