Raspberry Pi 4を使ってKubernetesクラスターを構築します。2023年版ということでDebianのバージョンは12 (bookworm)、コンテナランタイムはcontainerd、CLIはnerdctl、Kubernetesのバージョンはv1.28を使用します。まずは1台目のRaspberry Pi OSとnerdctlのセットアップまで行います。
ハードウェア環境
品物 | 詳細 | 個数 |
ラズパイ本体 | Raspberry Pi 4 Model B 4GB | 4 |
PoE HAT | Raspberry Pi PoE board (UD-RPPOE) | 4 |
micro SDカード | Transcend micro SDHC 32GB/64GB | 4 |
スイッチングハブ | TP-Link スイッチングハブ ギガ 5ポート PoEハブ (TL-SG1005P) | 1 |
その他 | 積層式ケース、LANケーブル、電源ケーブルなど 最初のセットアップ時にはキーボードやHDMI接続ディスプレイも必要 |
この中で調達が一番困難だったのはPoE HATでした。2021年頃に購入しましたが、コロナ禍の影響で在庫が無く、いろんな通販サイトを利用してどうにか4台調達しました。UD-RPPOEを調べると、2023年12月時点ではすでに生産終了(IODATA)になっているようですね。
4台のRaspberry Piは1台目をKubernetesのコントロールプレーンにして、2〜4台目をKubernetesのノードにします。公式によれば、かつてマスターノードと呼んでいたものは今はコントロールプレーンと呼ばれているようです。GitHubのmasterブランチがmainブランチに変名されたことと同じ理由でしょうか。ホスト名をコントロールプレーンにするのは長いので、GitHubに習ってmainを使うことにします。無線LAN側のIPアドレスはWi-Fiのアクセスポイントへ接続し、有線LAN側のIPアドレスはスイッチングハブ経由での通信に用います。
ホスト名 | 無線LANのIPアドレス | 有線LANのIPアドレス |
pi4main | 192.168.x.90/24 | 10.0.0.1/22 |
pi4node1 | 192.168.x.91/24 | 10.0.1.1/22 |
pi4node2 | 192.168.x.92/24 | 10.0.1.2/22 |
pi4node3 | 192.168.x.93/24 | 10.0.1.3/22 |
Raspberry Pi OSのインストール(1台目)
まずはmicro SDカードにRaspberry Pi OSを書き込みますが、最初の1台目のmicro SDカードをある程度までセットアップしてから2〜4台目のmicro SDカードにコピーしていくことにします。Kubernetes用ですので、Lite版のイメージを使います。
公式のページからWindowsやUbuntu、macOS用のツール(Raspberry Pi Imager)を使えば簡単にできますが、初代Raspberry Piの頃は以下のようにddコマンドでmicro SDカードにイメージを書き込んでいました。以下はmacOSでのコマンドです。
diskutil list # micro SDカードの/dev/disk[番号]をチェックする
diskutil eraseDisk FAT32 ボリューム名 MBR /dev/disk[番号]
diskutil unmountDisk /dev/disk[番号]
xz -d 2023-10-10-raspios-bookworm-arm64-lite.img.xz
sudo dd if=2022-01-28-raspios-bullseye-arm64-lite.img of=/dev/rdisk[番号] bs=16m
最初の1台目はHDMI接続ディスプレイとキーボードをつないでセットアップを行っていきます。最初に表示される画面で、キーボード配列を選択し、その後ユーザー名とパスワードを入力します。その後、Raspberry Pi OS Lite版ではコンソールの画面で「raspberrypi login:」が表示されるので、先ほど入力したユーザー名とパスワードでログインします。
Raspberry Pi OSにログインしたら、raspi-configコマンドでセットアップしていきます。
sudo raspi-config
第1階層 | 第2階層 | 説明 |
Update | raspi-configを最新版にバージョンアップします。 | |
System Options | Wireless LAN | 無線LANの設定を行います。国はJP(日本)を選択して、SSIDとパスワードを入力します。 |
System Options | Hostname | 1台目のホスト名「pi4main」を入力します。 |
Interface Options | SSH | SSHを有効にします。 |
Localisation Options | Locale | IPアドレスの設定が終わったら(nmtui)、ja_JP.UTF-8 UTF-8を選択します。 |
Localisation Options | Timezone | Asiaを選択して、Tokyoを選択します。 |
Advanced Options | Bootloader Version | Latestを選択します。 再起動後、「sudo vcgencmd bootloader_version」コマンドでブートローダのバージョンを確認できます。 |
Advanced Options | Boot Order | もしUSB接続したHDD/SSDから起動できるようにするのであれば、USB Bootを選択します。 |
最終的には4台分のSDカードを作成するので、今のうちにOSのアップグレードを行っておきます。
sudo apt update
sudo apt full-upgrade
1台目のIPアドレスを設定します。Debian 12 bookworm版のRaspberry PiではNetworkManagerを使っていますので、コンソール用の設定画面であるnmtuiコマンドでIPアドレスを設定します。
sudo nmtui
「Edit a connection」を選択してEnterキーを押すと「Ethernet」と「Wi-Fi」のリストが表示され、「Ethernet」の下には「Wired Connection 1」が表示されるので、これを選択したままEnterキーを押すとIPアドレスの入力画面になります。
同様の手順でWi-FiのIPアドレスも固定IPアドレスに変更します。
IPv6は不要なのでDisabledにしますが、NetworkManagerの設定だけでは完全にIPv6を無効化できない(localhostに::1が残る)ので、/boot/cmdline.txtにIPv6無効化の設定を追加します。
sudo nano /boot/cmdline.txt
ipv6.disable=1 console=serial0,115200 console=tty1 root=・・・
Debian 11 bullseyeまでは/etc/sysctl.confにIPv6無効化の設定を追加していましたが、Debian 12 bookwormでは無効にできなくなったので要注意です。
# Disable IPv6
net.ipv6.conf.all.disable_ipv6=1
再起動後、SSHで接続できるようになるので、SSH公開鍵認証でログインできるようにします。
# macOSからid_rsa.pubをコピーする
ssh-copy-id -i ~/.ssh/id_rsa.pub pi@192.168.x.90
PoE HATのファンが回りっぱなしになるため、ファンの回転温度を変更します。ついでに使用しないBluetoothも無効にしておきます。
sudo nano /boot/firmware/config.txt
ファイルの末尾に以下の設定を追加して再起動します。
dtoverlay=rpi-poe
dtparam=poe_fan_temp0=70000,poe_fan_temp0_hyst=1000
dtparam=poe_fan_temp1=75000,poe_fan_temp1_hyst=5000
dtparam=poe_fan_temp2=80000,poe_fan_temp2_hyst=5000
dtparam=poe_fan_temp3=82000,poe_fan_temp3_hyst=2000
dtoverlay=disable-bt
もし、無線LANの接続が不安定になるようでしたら、無線LANの電源管理を無効化するとよいかもしれません。
sudo apt install wireless-tools
sudo nano /etc/rc.local
# exit 0の前に挿入する
/usr/sbin/iwconfig wlan0 power off
sudo systemctl restart rc-local
iwconfig wlan0 # Power Management:off を確認する
gitやtmuxなどのツールをインストールしておきます。通信の確認用にiperfも入れています。NFSクライアントやSMBクライアントはKubernetesクラスターのノードからNFSサーバやSMBサーバに接続できるようにあらかじめインストールしておきます。
sudo apt install tmux iperf
sudo apt install nfs-common # NFSクライアント
sudo apt install cifs-utils smbclient # SMBクライアント
sudo apt install build-essential libbz2-dev libdb-dev \
libreadline-dev libffi-dev libgdbm-dev liblzma-dev \
libncursesw5-dev libsqlite3-dev libssl-dev \
zlib1g-dev uuid-dev tk-dev automake asciidoc git
containerdとnerdctlのセットアップ
コンテナランタイムをセットアップするため、containerdやrunc, CNIなどが同梱されているnerdctlのFull版をインストールします。2023年12月現在、最新版はv1.7.1です。
sudo apt install iptables arptables ebtables
sudo nano /boot/cmdline.txt
cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1 ・・・
再起動後、nerdctlのリリース一覧を見てARM64のFull版をダウンロードし、/usr/local配下に展開します。
mkdir ~/temp
cd ~/temp
wget https://github.com/containerd/nerdctl/releases/download/v1.7.1/nerdctl-full-1.7.1-linux-arm64.tar.gz
sudo tar Czxvf /usr/local nerdctl-full-0.20.0-linux-arm64.tar.gz
Kubernetesのコンテナランタイムとして使うための設定を行います。
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml > /dev/null
sudo nano /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
...
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
この後1台目にはプライベートレジストリを立ち上げるので、/etc/containerd/config.tomlにプライベートレジストリを追加するための設定も行います。
[plugins."io.containerd.grpc.v1.cri".registry]
config_path = "/etc/containerd/certs.d"
/etc/containerd/certs.dディレクトリにDocker Hubのレジストリとプライベートレジストリの設定を追加します。
sudo mkdir -p /etc/containerd/certs.d/docker.io
sudo nano /etc/containerd/certs.d/docker.io/hosts.toml
server = "https://registry-1.docker.io"
[host."https://registry-1.docker.io"]
sudo mkdir -p /etc/containerd/certs.d/10.0.0.1:5000
sudo nano /etc/containerd/certs.d/10.0.0.1:5000/hosts.toml
server = "http://10.0.0.1:5000"
[host."http://10.0.0.1:5000"]
capabilities = ["pull", "resolve", "push"]
skip_verify = true
containerdをRootfulモードで起動し、hello-worldで動作確認します。「Hello from Docker! (以下略)」と表示されれば成功です。
sudo systemctl enable --now containerd
sudo nerdctl run hello-world # テスト実行
nerdctl buildが使えるようにBuildkitを動かします。
sudo mkdir -p /etc/buildkit
sudo nano /etc/buildkit/buildkitd.toml
[worker.oci]
enabled = false
[worker.containerd]
enabled = true
# namespace should be "k8s.io" for Kubernetes (including Rancher Desktop)
namespace = "default"
sudo systemctl enable --now buildkit
kubeadm、kubelet、kubectlのインストールは次回やります。