K3s でサーバーと Raspberry PI からなるクラスターを構築する

お久しぶりです。 @km_conner です。

この記事では軽量な Kubernetes ディストリビューションである K3s 1 を使用して通常の Linux サーバーと Raspberry Pi から成る Kubernetes クラスターの構築方法を紹介します。 この記事を読んでいる人の多くは家にサーバーラックがあるか、サーバーラックはないものの、古い PC 等を使って自宅サーバーのようなことをしていることと思います。(強い偏見) そのような方は是非 Kubernetes を導入することにより管理の自動化に挑戦してみてはいかがでしょうか?

ちなみに、滅多に更新されないことで有名なこのブログですがおそらく Kubernetes 関連の記事がこの後に続いて書く予定です。

K3s とは?

K3s とは軽量な Kubernetes ディストリビューションです。

k3s 以外にも microk8s や OpenShift など様々な Kubernetes ディストリビューションが存在しますが、これらに比べて圧倒的にメモリなどのリソース消費量が少ないという特徴があります。

例えば microk8s は各ノードにおいて4GB以上のメモリが搭載されていることが推奨されています。2 それに対して k3s はなんと推奨スペックがメモリ1GB以上となっています!3

このように、リソース使用量が少ないため Raspberry PI においても十分動作すると考えられます。

ちなみに、 microk8s を手元にある Raspberry PI (3 model B+) 上で動かすとメモリを全て消費し、SSH越しに操作していても明らかに動きが重くなるため実際に使うにはかなり難しいでしょう。

使用した環境・構成

使用した機材は以下の通りです。

これらのノードは予め固定 IP アドレスが割り振られており、それらの IP を使って互いに通信できる状態とします。

Linux Server を master ノードとします。通常であれば master ノードは Pod のスケジューリングが無効になっている場合が多いですが、今回は master ノードにおいても Pod の実行が可能となるように設定しています。 (これは、 Raspberry PI だけでは全ての Pod を動かすにはスペックが足りない場合があるためです。)

インストール手順

ここからの手順は概ね QUick Start4 に記載の手順に沿っています。 (多少オプションを追加しています。)

Linux Server 上での作業

まず初めに、 swap はオフにしておきましょう。 Swap が有効になった状態で Kubernetes を使用することは推奨されていません。 /etc/fstab にある Swap に関する行をコメントアウトして再起動することで Swap を恒久的に無効化することができます。

次に、 k3s をインストールするために以下のコマンドを実行します。

curl -sfL https://get.k3s.io | sh -s - \
  --write-kubeconfig-mode 644 \
  --bind-address aaa.bbb.ccc.ddd \
  --node-ip aaa.bbb.ccc.ddd

このコマンドにあるように、 k3s はインストールスクリプトを使って簡単にインストールすることができます。 指定したオプションは https://rancher.com/docs/k3s/latest/en/installation/install-options/server-config/ に記載のあるものです。

特に、 --write-kubeconfig-mode のオプションに関しては忘れずに指定しておくことを推奨します。 デフォルトでは k3s クラスタにアクセスするための設定ファイルは /etc/rancher/k3s/k3s.yaml 以下に保存されますがこのファイルのパーミッションはデフォルトで root 以外のアクセスを許可しません。 そのため kubectl を使う際に問題が発生する場合があります。

その他のオプションはネットワークに関するオプションですが、ノードに複数の IP アドレスが割り当てられている場合には指定しておく必要がありますが、それ以外の場合には指定しなくても動きます。

上記のコマンド自体は早ければ1分もかからないうちに実行され、サーバーへの k3s のインストールが完了します。

Raspberry Pi 上でのインストール

Raspberry Pi の場合も先程と同様の方法で Swap を無効にします。

次に、 https://rancher.com/docs/k3s/latest/en/advanced/#enabling-legacy-iptables-on-raspbian-buster の手順に従って、 環境構築をします。 (この部分に関しては書いている本人もあまりちゃんとは理解していないため詳細な説明は省きます)

その次は、Raspberry Pi がクラスターに参加するためのトークンを取得します。 トークンは master ノードの /var/lib/rancher/k3s/server/node-token にテキストファイルとして保存されています。

Raspberry Pi 上で以下のコマンドを実行して、 Kubernetes 関係のバイナリをインストールして、クラスターに参加します。 (K3s 的には worker node のことを K3s Agent と呼ぶようです。)

curl -sfL https://get.k3s.io | K3S_URL=https://192.168.1.100:6443 K3S_TOKEN=<Token> sh -

コマンドの実行自体はすぐに終わるので、その後正常にクラスターに参加できているかを確認します。

インストールできたことの確認

master ノード上で kubectl get nodes のコマンドを実行すると master と RPi のノードが両方出現するはずです。

NAME          STATUS   ROLES                  AGE   VERSION
ubuntu        Ready    control-plane,master   36d   v1.20.6+k3s1
raspberrypi   Ready    <none>                 36d   v1.20.6+k3s1

上記のような感じで両方のノードが Ready になっていれば正常です。

異なる種類のノードが共存している際の注意点

今回使用したノード群には x86-64 (以下 x64) と arm が含まれています。 そのため、マニフェストを書く際にはどちらの種類のノードで実行するかを予め設定する必要があります。 (例えば、x64 向けにビルドされたコンテナは基本的に Raspberry Pi 上では動作しないと考えてください。)

例えば Deployment を作成する際には以下のようにアーキテクチャーを明示的に指定しておく必要があります。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: service-name
spec:
  template:
    spec:
      nodeSelector:
        kubernetes.io/arch: amd64

おわりに

この記事では k3s のインストール方法を簡単に紹介しました。 もちろんこの状態ではまだまだ Kubernetes のメリットを活かせていないため、今後の記事で寄り便利に使えるような Tips を紹介していきたいと思います。