ここ数年、複数台のRaspberry Pi 3/4を使って、Kubernetesクラスターを構築している記事をよく見かけます。Raspberry Piは安価なため、3台構成のクラスターを3万円弱で作成できます。私も構築してみました。
今回、3台のRaspberry Pi 4(4GB)に、Ubuntu Server 20.04 LTS(64bit)をインストールして構築しました(OSは32bit版より、64bit版にした方が、対応するバイナリ/dockerイメージが、若干多いようです)。
Raspberry Piの積層ケースについては、色々ある中、中国のAliExpress(52Pi Official Store)から、前面に12cmファンを備えた「Tower 4 Layer Acrylic Cluster Case」(送料込29.99USドル)を購入しました(コロナ禍による航空郵便の遅延により、届くまで1か月以上かかりました‥)。ファンが光るなど、派手な外観が特徴です。
Raspberry Pi 4は発熱が大きいため、安定運用のために、12cmファンで冷却しようと考えました。ファンは口径が大きい方が、同じ風量(=冷却性能)で、低回転(=低騒音)になります。ただ、このケース自体は、アクリル板の精度が悪くて組み立てしづらく、ツメが折れてしまったなど、使いづらいところがあります。また、写真にはファンガードがありますが、付属品ではなく、別途購入する必要がありました。
初期設定
最低限必要な初期設定として、ホスト名とタイムゾーンを設定しました。
1 | $ sudo hostnamectl set-hostname raspi001 |
※今回は、raspi001、raspi002、raspi003と設定しました。
OSを最新の状態に更新しておきます。
1 | $ sudo apt update |
ネットワークの設定
IPアドレスを固定するのに、ルーター側でMACアドレスと紐づけて設定しようとしましたが、Ubuntu 20.04の初期設定では正しく動作しませんでした。次のような設定ファイルで、DHCPの設定を修正する必要がありました。
1 | $ sudo vi /etc/netplan/99_config.yaml |
1 | network: |
設定ファイルを追加後、反映します(反映後、IPアドレスが変わる場合は、SSHの再接続が必要です)。
1 | $ sudo netplan apply |
※なお、直接、固定IPを設定する場合は次のようになります。
1 | network: |
Raspberry Pi OSとは異なり、mDNSが無効だったため、有効にしました(有効化すると、Windows 10 PCやMacから、raspi001.localでアクセスできるようになります)。
1 | $ sudo apt -y install avahi-daemon |
Kubernetesの動作に必要な設定
まず、スワップが無効である必要があります。free
コマンドで確認したところ、Ubuntu Server 20.04の場合、初期設定でスワップは0でした。
1 | $ free -h |
次に、cpusetとmemoryのcgroupが有効である必要があります。 /proc/cgroups
を確認したところ、memoryのcgroupが無効でした。
1 | $ cat /proc/cgroups |
そこで /boot/firmware/cmdline.txt
の最後に下記を追加し、再起動しました。 /proc/cgroups
でも有効になったことを確認しました。
1 | cgroup_enable=memory cgroup_memory=1 |
最後に、Kubernetesと互換性があるiptableに入れ替えます。
1 | $ sudo update-alternatives --set iptables /usr/sbin/iptables-legacy |
Dockerのインストール
Dockerをインストールします。
1 | $ sudo apt -y install apt-transport-https ca-certificates curl gnupg-agent software-properties-common |
※Kubernetesの動作確認済バージョンを指定してインストールする場合は次の通りです。
1 | $ sudo apt install containerd.io=1.2.13-2 docker-ce=5:19.03.11~3-0~ubuntu-focal docker-ce-cli=5:19.03.11~3-0~ubuntu-focal |
OS更新の際に、dockerのバージョンが上がって、Kubernetesとの互換性がなくなったりしないよう、dockerのバージョンを固定します。
1 | $ sudo apt-mark hold docker-ce docker-ce-cli |
kubernetesのドキュメントにあるように、cgroupの管理をcgroupfsではなく、systemdで行うように設定を追加します(動作が安定化するため)。
1 | $ sudo vi /etc/docker/daemon.json |
1 | { |
1 | $ sudo mkdir -p /etc/systemd/system/docker.service.d |
ユーザーにdockerの操作権限を与えるには、ユーザーを docker
グループに追加します(再ログインが必要です)。
※ユーザー ubuntu
に権限を与える場合
1 | $ sudo usermod -aG docker ubuntu |
バージョンを確認してみて、クライアント側・サーバー側双方のバージョンが表示されれば問題ありません。
1 | $ docker version |
kubernetesのインストール
Kubernetesをインストールします。
1 | $ curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - |
OS更新の際に、Kubernetesのバージョンが上がらないように、固定します。
1 | $ sudo apt-mark hold kubelet kubeadm kubectl |
マスターのセットアップ
マスター(1台目)、ワーカー(2台目、3台目)それぞれを設定していきます。
まずは、マスターを設定します。
1 | $ sudo kubeadm init |
ワーカー追加時に必要なため、表示内容の最後の部分をコピペしておきます。
1 | Then you can join any number of worker nodes by running the following on each as root: |
kubectlコマンドを利用できるよう、権限情報をコピーします。
1 | $ mkdir -p $HOME/.kube |
バージョンを確認します。
1 | $ kubectl version -o yaml |
仮想ネットワークのインストール
コンテナ間の仮想ネットワークをインストールします。
ここでは、Calicoをインストールします(OSが32bit版の場合は、Calicoは対応していないため、Flannelなどをインストールします)。
マスター上で、以下のコマンドを実行します。
1 | $ kubectl apply -f https://docs.projectcalico.org/v3.14/manifests/calico.yaml |
ワーカーのセットアップ
つぎに、ワーカーの2台をセットアップします。
マスターのセットアップ時に控えた内容を、2台のワーカーそれぞれで実行します。
1 | $ sudo kubeadm join 192.168.1.201:6443 --token r1j7o7.x7orcw1234567890 --discovery-token-ca-cert-hash sha256:f94e44006c8b45500328a11e2d5b4375b71467fcff8812345678901234567890 |
ワーカーでの作業は、以上で完了です。
ワーカーが追加されたか、マスター上で確認します。
1 | $ kubectl get nodes -o wide |
ワーカーのラベルが none
なので worker
というラベルをつけます。
1 | $ kubectl label node raspi002 node-role.kubernetes.io/worker=worker |
MetalLBのインストール
Kubernetes上のアプリに、外部からアクセスする際に便利なため、MetalLBをインストールします。マスター上で実行します。
1 | $ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/namespace.yaml |
MetalLBが使用するIPアドレスを設定します。ここでは、未使用の192.168.1.250~192.168.1.254を割り当てます。
下記の内容でファイルを作成し、適用します。
1 | $ vi metallb.config.yaml |
1 | apiVersion: v1 |
1 | $ kubectl apply -f metallb.config.yaml |
以上です。