Raspberry Pi を使って、 kubernetes クラスタを作成する話は多く見かけます。私も興味があったので今更ですが、これにチャレンジをしました。 kubernetes のバージョンが今は 1.25 系となり、 これまで非推奨とマークされていた docker が外れてしまったことで、古い情報をそのまま使うことができず、苦労しました。
物理的な完成図
今回は OS の設定や kubernetes の構築がメインの記事ですが、物理的に組み立てた時の写真が以下のものです。ごちゃごちゃとしていますが、下のほうに電源供給、有線ハブがあり、最上部にはトラベルルーターを置いて Wi-Fi 経由でこのクラスタにアクセスできるようにしています。環境構築時には、このトラベルルーターなしで、有線で接続して行いました。
トラベルルーターありにした時の話もどこかで記載するつもりです
OS の準備
使用する OS は Raspberry Pi OS Lite (2022/9月版) です。これを MicroSD に書き込み、ラズベリーパイで起動した後、各種パッケージを最新にしておきます。
$ sudo apt update
$ sudo apt dist-upgrade
ここまで処理できたら、一度 microSD カードを Windows PC に装着して、 cmdline.txt ファイルを編集します。このファイルにはすでに情報が書き込まれていますが、1行目の末尾に以下の文字列を追記します。
cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1
一度起動させた後で、このような書き換え処理を行う理由は、初回の起動でストレージ拡張が行われたタイミングで、コマンドオプションの設定も消えてしまうためです。
スワップの無効化
kubernetes がスワップ無効化を要求するのでその設定をします。以下のコマンドを実行してスワップを無効化します。
$ sudo dphys-swapfile swapoff
$ sudo systemctl stop dphys-swapfile
$ sudo systemctl disable dphys-swapfile
ホスト名の変更
ホスト名を適切なものに変更しておきます。3台のラズベリーパイで構成する都合、以下のホスト名をつけておこうと思います。
- k8s-master
- k8s-worker1
- k8s-worker2
$ sudo hostnamectl set-hostname k8s-master
IP の固定化
DHCP 側で固定 IP が振られるようにするというのも1つの手ですが、ここではクライアント側で固定化を行います。 dhcpcd.conf ファイルをエディタで開いて、下記に示すようにネットワークの設定を行います。私の場合、ラズベリーパイが動作しているネットワークは 192.168.21.0/24 となっているので、このような設定になっています。
$ sudo nano /etc/dhcpcd.conf
interface eth0
static ip_address=192.168.21.101/24
static routers=192.168.21.1
static domain_name_servers=192.168.21.1
今回は k8s-master ホストから順に 192.168.21.101 – 103 を設定しました。
また、 /etc/hosts ファイルに固定IP と新しくつけたホスト名の対応表を記載しておきます。以下にその例を示します。
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
127.0.1.1 k8s-master
192.168.21.101 k8s-master
192.168.21.102 k8s-worker1
192.168.21.103 k8s-worker2
再起動
ここまでの内容を反映するため、再起動します。
OS の準備 (2)
kubernetes をインストールする際に使用するツールのインストールを行います。
$ sudo apt install apt-transport-https curl ebtables arptables
iptables の設定を変更します。
$ sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
$ sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
$ sudo update-alternatives --set arptables /usr/sbin/arptables-legacy
$ sudo update-alternatives --set ebtables /usr/sbin/ebtables-legacy
$ sudo -i
# cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
# modprobe overlay
# modprobe br_netfilter
# cat > /etc/sysctl.d/99-kubernetes-cri.conf <<EOF
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# sysctl --system
CRI-O のインストール
kubernetes 1.24 から Docker のサポートが外れてしまったので、 CRI-O を使って構築します。他には containerd を使う方法もあるようです。
リポジトリの登録
インストールのためにリポジトリを追加します。
# echo "deb https://ftp.gwdg.de/pub/opensuse/repositories/devel:/kubic:/libcontainers:/stable/Debian_11/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
# echo "deb https://ftp.gwdg.de/pub/opensuse/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.25:/1.25.1/Debian_11/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:1.25.1.list
# curl -L https://ftp.gwdg.de/pub/opensuse/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/1.25:/1.25.1/Debian_11/Release.key | apt-key add -
# curl -L https://ftp.gwdg.de/pub/opensuse/repositories/devel:/kubic:/libcontainers:/stable/Debian_11/Release.key | apt-key add -
本来ならば、 https://download.opensuse.org/repositories を登録すべきなのですが、パッケージの取得でハッシュが合わないエラーが出てしまったため、ミラーサーバーのアドレスをここでは使用しています。
# apt update
CRI-O インストール
以下のコマンドを実行してインストールを行います。
# apt install cri-o cri-o-runc
# systemctl daemon-reload
# systemctl start crio
# systemctl enable crio
Kubernetes のインストール
Kubernetes (k8s) のインストールを行います。ここでは 1.25.1 を明示的に指定してインストールをしています。 k8s と CRI-O との組み合わせには注意する必要があります。
リポジトリ登録
# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
# cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
# apt update
インストール
# apt install kubelet=1.25.1-00 kubeadm=1.25.1-00 kubectl=1.25.1-00
最後に、バージョンが勝手に更新されないようホールドしておきます。
# apt-mark hold kubelet kubeadm kubectl cri-o cri-o-runc
ここまで完了したら、root のシェルを抜けておきます。
ここまでのインストール作業はクラスタに参加する全てのラズベリーパイで行っておく必要があります。
クラスタを作成
k8s-master にて、以下のコマンドを実行してクラスタを作成します。今回は flannel を使用することを想定しているので cidr に 10.244.0.0/16 を設定します。
$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16
このコマンドを実行した後に表示されるコマンド列を以下の通り実行します。またワーカーノード追加に必要なコマンドも一緒に出力されているので、そちらをメモしておきます。
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
flannel のインストール
以下のコマンドを実行して flannel をインストールします。
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
動作の確認
状態を確認するコマンドを実行してみて、 k8s が動作しているかを確認してみます。
$ kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane 9m47s v1.25.1
しばらく待ってみて、 STATUS の状態が Ready になるかを確認します。
続いて POD の状態を表示させてみます。
$ kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-flannel kube-flannel-ds-nn8q5 1/1 Running 0 2m29s
kube-system coredns-565d847f94-4nvm7 1/1 Running 0 10m
kube-system coredns-565d847f94-8sxd4 1/1 Running 0 10m
kube-system etcd-k8s-master 1/1 Running 0 10m
kube-system kube-apiserver-k8s-master 1/1 Running 0 10m
kube-system kube-controller-manager-k8s-master 1/1 Running 0 10m
kube-system kube-proxy-8xt9c 1/1 Running 0 10m
kube-system kube-scheduler-k8s-master 1/1 Running 0 10m
このようにすべてのものが Running となっているようであれば正常です。
kube-frannel-ds-*** のものが Running にならず、苦戦したことがあります。この時にはいくつか理由がありましたが、 そのうち1つの事例として cidr を 10.244.0.0/16 とするところをタイプミスで別アドレスになっていたことがありました。
クラスタを作成 – ワーカーノードを追加
先の kubeadm init 実行後に表示されたコマンドを、ワーカーノードで実行してノードを登録します。その時のコマンド例が以下の通りです。
kubeadm join 192.168.21.101:6443 --token ic598u.wus4wdkfbva2iimx \
--discovery-token-ca-cert-hash sha256:fcc5b939086d10a8ae4577965d1fe109b70de0250f9d8aa8fd033cd29aa3babcd
$ sudo kubeadm join 192.168.21.101:6443 --token ic598u.wus4wdkfbva2iimx \
--discovery-token-ca-cert-hash sha256:fcc5b939086d10a8ae4577965d1fe109b70de0250f9d8aa8fd033cd29aa3babcd
もし、このコマンド列をメモするのを忘れた場合には、以下のコマンドで再生成できるようです。
$ kubeadm token create --print-join-command
登録が完了すると、 master ノードで kubectl get node コマンドを実行したときに、追加したノードが表示されます。
$ kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane 41m v1.25.1
k8s-worker1 Ready <none> 37s v1.25.1
まとめ
kubernetes を初めて構築しましたが、とても手間取りました。やはり docker が非推奨・標準から外れた現時点の状態で、過去の情報が多く見つかりそちらを参照してしまったため、惑わされたというのが大きいと思いました。それでも、参考文献に挙げたサイトの情報で正常に起動できるようになり大変助けられました。
この k8s クラスタを用いて、いろいろな実験および学習を進めていきたいと思っています。
参考
- kubeadmでのkubernetes構築
- Raspberry Piをかき集めてKubernetesを体感する
- https://future-architect.github.io/articles/20220908a/
- LoadBalancer の設定をするときにはここを参照
コメント