もち256ログ
About Note Log
Log
published: 2022-02-27
RaspberryPiでk8sクラスタを構築する

お久しぶりです、もち256です。

昨今では半導体不足の影響もあり、Raspberry Pi(以後「ラズパイ」と呼称)が手に入らなくなっていますが、たまたま3台入手することができました。

なので、今回はラズパイ3台を使用した、k8sクラスタの構築方法を書いておこうと思います。


はじめに

Kubernetes(k8s)クラスタとは「複数のホストを使用して冗長化したクラスタを構築し、複数コンテナによって構成されたアプリを運用する」という仕組みです。

今回この仕組みを使って検証したいことがあったので、クラスタを構築することとしました。


用意したもの

今回k8sクラスタを構築するにあたり、下記のものを用意しました。

blog_image
機器名 商品名 単価 個数
ラズパイ Raspberry Pi 4 Model B 8GB 10,670 3
L2スイッチ GS305-300JPS 2,720 1
LANケーブル LD-C6YT/BK05 470 4
ラズパイ ケース RPI4-ACCASBK 1,650 3
SDカード SDSQUAR-032G-JN3MA 3,031 3
ラズパイ 電源 SSCI-056830 1,580 3
電源ケーブル AVT-K6A-2650BK 1,930 1
ラック HC-19MB2S-3937 2,728 1
技術評論社 たった1日で基本が身に付く! Docker/Kubernetes超入門 2,838 1

画像には含まれていませんが、ラックはイオンで販売されていた食器の水切りラックを購入しました。

他、RaspberryPiは共立エレショップ、その他周辺機器はヨドバシ.comで購入しました。

機器の総額は、63,000円程度でした。


機器の準備

用意した機器を組み合わせます。

今回、作りたいラズパイのネットワークは、下記になります。

マスターノードを「m256-main」とし(以後「mainノード」と呼称)、他のワーカーノード(以後「subノード」と呼称)を「m256-sub」としています。
また、mainノードはIPマスカレードの設定を行い、subノードはNATを使用してWANへ接続します。

blog_image

ラズパイにケースを装着すると、こんな感じになります(かっこいい)。

blog_image

最終的にラックを使用して、こんな感じで配置しています。
使用しない時は延長用電源ケーブルも収納できて便利です。

blog_image

Raspberry Pi OSのインストール

さて、ここからが各端末の設定になります。
まずは、ラズパイにOSをインストールします。

OSのインストールは、Raspberry Pi Imagerを使用して、SDカードに焼いていきます。

blog_image

今回はGUIを使用する予定がないため、OSは「Raspberry Pi OS Lite (64-bit)」を使用します。

blog_image

また、インストールを行う時点でsshやWi-Fiの設定を行います。
この作業によって、ディスプレイを使用せずにラズパイへ接続を行い、設定を完了することができるようになります。

「m256-main」など、ホスト名もこの設定画面で設定を行えます。

blog_image

この作業を完了後、ラズパイの電源を付けると、インストール時に登録したWi-Fiへ接続されます。
自分はこの時、ルーターの設定画面から各ラズパイのIPアドレスを特定し、sshを行いました。


各ノードの設定

ここからが各ラズパイの設定になります。
まずはapt updateを行います。

sudo apt -y update
sudo apt -y upgrade

次に、sudoを使用する際にパスワードを毎回入力するのも面倒なので、visudoの設定を行います。

sudo visudo
# 下記の行を追加する
# ------------------------------------
# pi      ALL=(ALL:ALL) NOPASSWD:ALL

また、任意で強固なパスワードに変更しておきます。

sudo passwd pi

そして、sshの認証方式をパスワード方式から、公開鍵認証方式に変更します。
下記のコマンドは、mainノードでのみ行いました。

cd ~/.ssh
# 公開鍵の生成
ssh-keygen -t rsa -b 4096 -C "" -f m256-sub.id_rsa
ssh-copy-id -i ~/.ssh/m256-sub.id_rsa.pub pi@m256-sub1
ssh-copy-id -i ~/.ssh/m256-sub.id_rsa.pub pi@m256-sub2

vim ~/.ssh/config
# 下記の行を追加する
# ----------------------------------
# Host m256-sub1
#    HostName m256-sub1
#    User pi
#    IdentityFile /home/pi/.ssh/m256-sub.id_rsa
# 
# Host m256-sub2
#    HostName m256-sub2
#    User pi
#    IdentityFile /home/pi/.ssh/m256-sub.id_rsa

最後に、subノードでパスワード認証方式を不許可に設定し、初期設定は終了です。
mainノードの公開鍵を生成した場合は、mainノードで下記の設定を行っても良いです。

sudo vi /etc/ssh/sshd_config
# 下記の行を追加する
# ----------------------------------
# PasswordAuthentication no

sudo systemctl restart sshd

IPアドレスの固定化

ラズパイ同士のネットワークを作るため、まずはスイッチに接続されているインターフェースのIPアドレスを静的に設定します。

設定を書き換えるため、適当にエディタをインストールします。

sudo apt -y install vim

IPアドレスは「dhcpcd.conf」に設定を行います。

sudo vim /etc/dhcpcd.conf

mainノードには下記の設定をしました。

interface eth0
static ip_address=10.4.28.1/24

subノードには下記ような設定を行います。

「ip_address」は適宜変更を行い、「routers」はmainノードを設定します。

interface eth0
static ip_address=10.4.28.11/24
static routers=10.4.28.1
static domain_name_servers=8.8.8.8

また、全てのホストの「/etc/hosts」に下記の内容を記載し、ドメインを解決できるようにします。

10.4.28.1       m256-main
10.4.28.11      m256-sub1
10.4.28.12      m256-sub2

ここまでで、各ノードのIPアドレスが固定化できました。


IPマスカレードの設定

ここからは、mainノードにIPマスカレードの設定を行い、subノードの通信をmainノードを経由して行うようにします。

下記のコマンドをmainノードで実行します。

sudo vim /etc/sysctl.conf
# "net.ipv4.ip_forward=1"のコメントを外す

また、/proc配下の「ip_forward」にも設定を行います。

sudo su -
echo -n 1 > /proc/sys/net/ipv4/ip_forward
reboot

そして、iptablesの設定を行い、iptables-persistentを使用して設定を永続化します。

sudo apt -y install iptables
sudo iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
sudo iptables -A FORWARD -i wlan0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o wlan0 -j ACCEPT

sudo apt -y install iptables-persistent
# インストール時、現在のネットワーク設定を保存するか聞かれるので"YES"を選択する
# または、インストール後に"netfilter-persistant save"のコマンドを実行する
sudo systemctl enable netfilter-persistent

最後に、subノードからNATの機能が有効になっているか確認します。

# Wi-Fiの切断
sudo ifconfig wlan0 down

# 下記2つのコマンドが実行できればmainノードのIPマスカレード設定が完了している
ping 8.8.8.8
host mochi256.com

# subノードでWi-Fi設定を読み込まないようにする
sudo mv /etc/wpa_supplicant/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant.conf.bak

ここまでで、IPマスカレードの設定は完了です。


k8sクラスタの設定

ここからが本題のk8sクラスタの設定になります。

まず、これから使用する「kubeadm」コマンドで、swapが有効だとエラーが発生するため、swapの無効化を全てのノードで行います。

sudo dphys-swapfile swapoff
sudo systemctl stop dphys-swapfile
sudo systemctl disable dphys-swapfile

次に、全てのノードでdockerをインストールします。

dockerのバージョンは固定化しておき、piユーザーにdockerの実行権限を与えます。

sudo apt -y install docker docker-compose
sudo apt-mark hold docker docker-compose
sudo usermod -aG docker pi

そして、全てのノードに「kubelet, kubeadm, kubectl」のコマンドをインストールします。

sudo bash -c "curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -"
sudo bash -c "echo 'deb https://apt.kubernetes.io/ kubernetes-xenial main' > /etc/apt/sources.list.d/kubernetes.list"
sudo apt -y update
sudo apt -y install kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

# ラズパイ起動時の設定を行う
sudo vim /boot/cmdline.txt
# "cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory"を追記する
sudo reboot

mainノードの設定

下記のコマンドで、mainノードの設定を行います。

sudo kubeadm init --pod-network-cidr=10.244.0.0/16

このコマンド終了後「You can now join any number of machines by running the following on each node as root:」という、他のノードが参加するためのコマンドが出力されるので、内容をメモしておきます。

また、他にも設定を行うための指示が出力されるので、コマンドを実行します。

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

ここまで実行すると、下記のコマンドでノードの状態を確認できるようになります。

ただし、今の状態だとSTATUSが「NotReady」となります。

kubectl get node
# ------------------------------------------------
# NAME         STATUS     ROLES                  AGE     VERSION
# m256-main    NotReady   control-plane,master   3m57s   v1.23.4

状態を有効にするため、CNIプラグインのFlannelをインストールします。

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

インストールに成功すると、STATUSが「Ready」になります。


subノードの追加

最後に、mainノードに他ノードの追加を行います。

mainノードの設定時、他のノードが参加するためのコマンドが表示されているので、それを実行するのみです。

下記のコマンドは、subノードで実行します。

kubeadm join <Kubernetes APIのアドレス>:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>
# もしコマンドをメモし忘れている場合は、mainノードで下記のコマンドを実行すると、tokenとhashの値を取得できる
# ---------------------------------------------------------------
# token ⇒ $ kubeadm token list
# hash ⇒  $ openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'

k8sクラスタの状態確認

最後に、mainノードで下記のコマンドを実行し、クラスタが作成されていれば完了です。

kubectl get node
# ------------------------------------------------
# NAME         STATUS    OLES                  AGE     VERSION
# m256-main    Ready     control-plane,master  30m     v1.23.4
# m256-sub1    Ready     <none>                92s     v1.23.4
# m256-sub2    Ready     <none>                100s    v1.23.4

おわりに

今回は、k8sクラスタの作成方法のみを記事にしました。

せっかく作ったので、今後何か良さそうな運用方法があれば、ブログに書いてみようと思います。

今回は以上になります。
ここまで読んでいただき、ありがとうございました!


参考文献


ログ一覧へ戻る