はじめに
エンジニアならきっと誰しもやりたくなる(?)ラズパイを使ったKubernetesクラスタ構築に手を出してみたので、その際のメモとなります。
ハードウェア準備
必要機材
機材 | 数量 | 備考 |
---|---|---|
Raspberry Pi 4 Model B / 4GB | 3台 | |
microSDカード 32GB | 3枚 | |
Raspberry Pi クラスタケース | 1個 | |
スイッチングハブ (LSW6-GT-5ESL) | 1台 | コンパクトにしたい場合はUSB給電できる機種を選択した方が良いかもしれません。 |
USB充電器 (4ポート 100W) | 1台 | 3ポート以上かつ5V/3Aで出力できそうなものを選定 |
USB Type-Cケーブル | 3本 | |
0.5m LANケーブル | 3本 | ラズパイとスイッチングハブの接続用 |
5m LANケーブル | 1本 | ルータとスイッチングハブの接続用 |
ネットワーク構成
Raspberry Piはスイッチングハブを介して自宅のルータに接続しました。
OSセットアップ
今回はRaspberry Pi OSを使用します。
ラズパイ3台全てに対して、セットアップを実施していきます。
microSDカードへのOS書き込み手順は色々あるので省略しますが、Raspberry Pi Imagerを使用して書き込むのが楽なのでおすすめです。
パッケージ更新やツールインストール
とりあえずaptの更新とエディタをインストールしておきます。
sudo apt update && sudo apt upgrade
sudo apt install -y vim
IPアドレス固定
/etc/dhcpcd.conf
を開いて設定を追記します。
sudo vim /etc/dhcpcd.conf
ip_address
の値は各ラズパイ毎に変更する必要があります。
- master ... 192.168.1.111
- worker1 ... 192.168.1.112
- worker2 ... 192.168.1.113
以下はmasterの場合の例です。
interface eth0
static ip_address=192.168.1.111/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.1
設定したらラズパイを再起動し、ip addr
コマンド等でIPアドレスが設定した値に変わっていることを確認します。
ホスト名変更
初期設定ではホスト名がraspberrypiとなっているので変更していきます。
こちらも色々方法はありますが、raspi-config
を使用した方法でやってみます。
sudo raspi-config
「1 System Options」→「S4 Hostname」を選択
変更するホスト名を入力します。
今回はそれぞれ、master、worker1、worker2とします。
hosts編集
/etc/hosts
を編集して設定を追記します。
sudo vim /etc/hosts
192.168.1.111 master
192.168.1.112 worker1
192.168.1.113 worker2
スワップの無効化
スワップが有効化されているとKubernetesを起動できないため、スワップを無効化します。
sudo swapoff -a
sudo systemctl stop dphys-swapfile
sudo systemctl disable dphys-swapfile
systemctl status dphys-swapfile
ラズパイを再起動した後free -h
コマンドを実行し、swapの値が0となっていれば大丈夫です。
pi@master:~ $ free -h
total used free shared buff/cache available
Mem: 3.7Gi 498Mi 1.4Gi 201Mi 1.8Gi 2.9Gi
Swap: 0B 0B 0B
cgroupのメモリを有効化
こちらも設定しないと、Kubernetes起動時にエラーが発生する原因となります。
/boot/cmdline.txt
を編集して設定を追記します。
sudo vim /boot/cmdline.txt
元々の記載の末尾に、下記設定を追記します。
cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1
Dockerインストール
以下のコマンドを実行することでdockerをインストールできます。
curl -fsSL https://get.docker.com/ | sh
インストールが完了したら現在のユーザをdockerグループに追加しておきます。
この作業を実施することで、root権限無しでdockerコマンドを実行できるようになります。
sudo gpasswd -a $(whoami) docker
exit
Kubernetesインストール
apt-transport-https
とcurl
が入っていない場合はインストールしておきます。
(Raspberry Pi OSには初めから入っているはずなので、恐らくこの作業は必要無いです。)
sudo apt update && sudo apt install -y apt-transport-https curl
GPGキーを追加します。
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
リポジトリ定義をsources.list.d配下に追加します。
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
kubelet
, kubeadm
, kubectl
のインストールとバージョン固定を実施します。
sudo apt update
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
クラスタ構築の事前準備
この後のmasterノード設定やworkerノード追加の作業を実施前に、以下のコマンドでcontainerdを再起動しておきます。
(筆者の環境では、この作業を実施しておかないと後の作業でエラーが発生しました。)
sudo rm /etc/containerd/config.toml
sudo systemctl restart containerd
masterノード設定
masterノードの初期化を実施していきます。
この作業はmasterノード用のラズパイ(master)のみ実施します。
初期化処理
kubeadm init
コマンドを実行することでクラスタの初期化ができますが、まずは--dry-run
オプションを付与して、動作確認をします。
sudo kubeadm init \
--apiserver-advertise-address=192.168.1.111 \
--pod-network-cidr=10.244.0.0/16 \
--token-ttl 0 \
--dry-run
ドライランの実行でエラーが出た場合は、設定を見直す必要があります。公式の手順にもいくつか前提条件が記載されているので参考にしてみてください。
ドライランが問題無く実行できた場合は、--dry-run
オプションを外して実際にクラスタの初期化を実施します。
sudo kubeadm init \
--apiserver-advertise-address=192.168.1.111 \
--pod-network-cidr=10.244.0.0/16 \
--token-ttl 0
以下のようなメッセージが出力されていれば初期化処理は完了です。
...(省略)
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.1.111:6443 --token <認証トークン> \
--discovery-token-ca-cert-hash <ハッシュ値>
ここで表示されたkubeadm join
コマンドは、workerノード追加の際に必要なため、メモしておきます。
認証トークンの有効期限はデフォルトで24時間となっていますが、今回は--token-ttl 0
のオプションを付与することで、無期限にしています。
kubectlの設定
kubeadm init
実行時の出力メッセージにもある通り、以下のコマンドを実行してkubectl
を一般ユーザで実行できるように設定します。
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
ついでにkubectl
の補完機能も有効化しておきます。
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc
以下のように一般ユーザ権限でkubectl
が実行できていればOKです。
pi@master:~ $ kubectl get node
NAME STATUS ROLES AGE VERSION
master NotReady control-plane 83s v1.24.3
flannelインストール
CNIプラグインとして広く利用されているflannelをインストールします。
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
workerノードの追加
作成したクラスタにworkerノードを追加していきます。
この作業はworkerノード用のラズパイ(worker1, worker2)のみ実施します。
先ほどメモしておいたkubeadm join
コマンドをworkerノードで実行します。
sudo kubeadm join 192.168.1.111:6443 --token <認証トークン> --discovery-token-ca-cert-hash <ハッシュ値>
以下のようなメッセージが出力されていればOKです。
...(省略)
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
最後にmasterノードでworkerノードが正常に参加できていることを確認します。
STATUSがReadyになっていればOKです。
※ノード追加実施直後はSTATUSがNot Readyになっている可能性があります。その際は数分待ってから再度確認してみてください。
pi@master:~ $ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready control-plane 15m v1.24.3
worker1 Ready <none> 113s v1.24.3
worker2 Ready <none> 24s v1.24.3
これでKubernetesクラスタ構築は完了です。お疲れ様でした!