Open4

地理的に分散した Kubernetes クラスターを Proxmox + LXC + Tailscale で構成する (High Availability)

yudeyude

構築

Proxmox ホスト単位

  • IPv4 パケットフォワーディングを有効にする。
    sysctl -w net.ipv4.ip_forward=1
    

control-plane, worker 単位

  • Web UI から LXC を作成する。
    • 非特権コンテナのチェックを外す。
    • スワップは使わないので 0 byte でよい。
    • DNS はとりあえず 1.1.1.1 にしておく。
      • ホスト側に Tailscale が導入されていると 100.100.100.100 に向くのでゲスト側 (LXC) に tailscaled をインストールし、Tailscale にログインするまで名前解決できなくなる。
  • 作成後、/etc/pve/lxc/<ID>.conf に以下を追記する。
    features: mount=fuse,nesting=1
    lxc.cgroup2.devices.allow: c 10:200 rwm
    lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
    lxc.apparmor.profile: unconfined
    lxc.cap.drop:
    lxc.cgroup.devices.allow: a
    lxc.mount.auto: proc:rw sys:rw
    lxc.mount.entry: /dev/fuse dev/fuse none bind,create=file 0 0
    
  • LXC を起動する。
  • LXC 内に Tailscale をインストール、ログインする。
    • tailscale up
  • エラー failed to start OOM watcher open /dev/kmsg: no such file or directory 対策のため、以下を LXC 内で実行する。
    ln -s /dev/console /dev/kmsg
    echo 'L /dev/kmsg - - - - /dev/console' > /etc/tmpfiles.d/kmsg.conf
    
  • スワップを完全に切る。
    swapoff -a
    
yudeyude

LXC 内に K3s をインストールする

  • Tailscale 内での IP アドレスは tailscale ip とかで確認する。

control-plane

1 台目

curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server \
    --cluster-init \
    --advertise-address <Tailscale の IP アドレス> \
    --node-ip <Tailscale の IP アドレス> \
    --node-external-ip <Tailscale の IP アドレス>" \
    sh -s

2 台目以降

  • トークンは 1 台目の control-plane 上の /var/lib/rancher/k3s/server/token にある。
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server \
    --server https://<1 台目のノードの Tailscale の IP アドレス> :6443 \
    --token \
    <トークン> \
    --advertise-address <Tailscale の IP アドレス> \
    --node-ip <Tailscale の IP アドレス> \
    --node-external-ip <Tailscale の IP アドレス>" \
    sh -s

この時点で k3s kubectl get node を実行すると目的のノードがすべて Ready になっているはず。

yude in 🌐 dev in ~ on ☁️  (auto)
❯ kubectl get node
NAME          STATUS   ROLES                       AGE    VERSION
k8s-hitachi   Ready    control-plane,etcd,master   94m    v1.30.4+k3s1
k8s-maple     Ready    control-plane,etcd,master   100m   v1.30.4+k3s1
k8s-sakyu     Ready    control-plane,etcd,master   97m    v1.30.4+k3s1

worker

1 台目以降

curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="agent \
    --server https://<コントロールプレーン (どれでもよい) の Tailscale の IP アドレス>:6443 \
    --token \
    <トークン> \
    --node-ip <Tailscale の IP アドレス> \
    --node-external-ip <Tailscale の IP アドレス>" \
    sh -s

K3s の systemd unit ファイルを編集する

  • 現状だと、サーバーを再起動した時に K3s が上がってこないことがある。
  • これは Tailscale よりも前に K3s が起動した時に発生する (と思われる)。
  • したがって、以下の unit ファイルの After= の項を編集する。
    • control-plane: /etc/systemd/system/k3s.service
    • worker: /etc/systemd/system/k3s-agent.service
  • 編集内容
    • After=network.targetAfter=tailscaled.service に書き換える。
  • 書き換え後は、念の為 systemctl daemon-reload を実行する。
yudeyude

kubectl get node を実行した際に、worker の role が <none> と表示されることがあるようです。

yude in 🌐 dev in ~ on ☁️  (auto)
❯ kubectl get node
NAME               STATUS   ROLES                       AGE    VERSION
k8s-hitachi        Ready    control-plane,etcd,master   111m   v1.30.4+k3s1
k8s-maple          Ready    control-plane,etcd,master   117m   v1.30.4+k3s1
k8s-sakyu          Ready    control-plane,etcd,master   113m   v1.30.4+k3s1
k8s-worker-maple   Ready    <none>                      13s    v1.30.4+k3s1

以下のようにして解決できます:

yude in 🌐 dev in ~ on ☁️  (auto)
❯ kubectl label node k8s-worker-maple node-role.kubernetes.io/worker=worker
node/k8s-worker-maple labeled

yude in 🌐 dev in ~ on ☁️  (auto)
❯ kubectl get node
NAME               STATUS   ROLES                       AGE    VERSION
k8s-hitachi        Ready    control-plane,etcd,master   112m   v1.30.4+k3s1
k8s-maple          Ready    control-plane,etcd,master   117m   v1.30.4+k3s1
k8s-sakyu          Ready    control-plane,etcd,master   114m   v1.30.4+k3s1
k8s-worker-maple   Ready    worker                      57s    v1.30.4+k3s1
yudeyude

Zenn が発狂して更新できないんですが control-plane, worker 起動時に --flannel-iface tailscale0 というのも追加してあげてください