Raspberry Pi 4 でおうちk8sクラスタを構築する
概要
だいたいこの手の構築手順はいろいろな方がまとめられてますが、自分がやった作業の備忘録も兼ねてまとめておきます
構成はmaster×1、worker×2として、raspberry piを3台使って作ります
物理構築
物理的な構築は以下の記事とほぼ同じ手順でやりました qiita.com
また、ルータの設定については以下記事と同じ手順で行っています qiita.com この記事自体がだいたい↑これと同じ手順となるのでコレだけ読めば良い説
完成した様子がこちら(良い良い)
「Raspberry Pi 4で」というタイトルになってますが、もともとRaspberry Pi 3(Model 3+)を持っていたのでMasterNodeには3を使おうと思います
(下から3番目のラズパイが3)
今回のクラスタ構成のために買ったものを以下にまとめておきます
もの | 製品 | 数 |
---|---|---|
ラズパイ | Raspberry Pi 4 Model B | 2 |
ケース | 積層式ケース for Raspberry Pi 4 / Pi 3 Model B+ | 1 |
SDカード | KEXIN MicroSDカード UHS-I Class10 SDHC 16GB(3個セット) | 3枚 |
USD充電器 | AUKEY USB充電器 50W/10A ACアダプター 5ポート | 1 |
LANケーブル(15cm) | エレコム LANケーブル 0.15m×2本 | 3本(1本は余ってる) |
LANケーブル(30cm) | TWS-63BK [スリムLANケーブル CAT.6 0.3m 黒] | 1 |
USBケーブル(type-c) | USB C ケーブル 30cm SUNGUY 【2本セット0.3m】 | 2本 |
スイッチングハブ | TP-Link 5ポート スイッチングハブ | 1 |
無線ルータ | BUFFALO 無線LAN親機 WMR-433W2-BK | 1 |
- スイッチングハブは他記事などではよくこちらの商品が使われていて、自分も最初使いましたが、ネットワークがよく途切れるので買い替えました
- TP-Linkだと電源が必要になりサイズも大きくなりましたが、サイズ的にはケース下のネジが挟まれるようになってちょうど良いサイズだった
- LANケーブルはすべて15cmでもつなげられるが、ケース最上段に置く無線ルータへはギリギリでケーブルに負荷がかかるため30cmのほうがおすすめ
論理構築
全台共通
https://www.raspberrypi.org/downloads/raspbian/ からOSイメージをダウンロード
今回はk8sクラスタ用でdesktopは不要なのでRaspbian Buster Liteを選びました
他の記事などではddコマンドなどを利用してSDへイメージを書き込んでいますが、自分は balenaEtcher というアプリケーションを利用して書き込みました(弱い)
Select imageに解凍したimgファイル、Select targetに対象のSDを選択して"Flash!"を実行します
書き込みには少し時間かかるのでお茶でも飲みながら待ちましょう
書き込みが完了したらsshdとcgroupsの設定のために以下を実行します(SDカードに対して)
$ cd /Volumes/boot $ touch ssh
cmdline.txtの末尾にcgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1
を追記
$ cd /Volumes/boot $ cat cmdline.txt console=serial0,115200 console=tty1 root=PARTUUID=6c586e13-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet init=/usr/lib/raspi-config/init_resize.sh cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1
SDをラズパイにセットして電源を入れます
arp -a
をラズパイと同じLANに繋がれたPC(自分はmac使ってる)から実行してラズパイのIPを調べます
$ arp -a ? (192.168.13.1) at 18:c2:bf:ea:d5:9a on en1 ifscope [ethernet] ? (192.168.13.2) at dc:a6:32:6e:d6:92 on en1 ifscope [ethernet] ...
192.168.13.1
はルータのIPなので、192.168.13.2
の方っぽいです
sshで入ってみます
$ ssh pi@192.168.13.2
piユーザの初期パスワードはraspberry
です
pi@raspberrypi:~ $
無事ログインできました
piユーザ/rootユーザのパスワードを変えておきましょう
$ passwd $ sudo passwd
作業用のユーザを作成します(パスワード設定も)
$ sudo useradd --groups adm,dialout,cdrom,sudo,audio,video,plugdev,games,users,input,netdev,spi,i2c,gpio -m sminamot $ sudo passwd sminamot
最後にpiユーザを無効化しておきます
$ sudo passwd --lock pi
コレ以降は作ったユーザで作業を進めます
$ ssh sminamot@192.168.13.2
初期設定
$ sudo raspi-config
4 Localisation Options
->I1 Change Locale
en_GB.UTF-8 UTF-8
のチェックを外すen_US.UTF-8 UTF-8
にチェックを入れる- OKを押したあとに聞かれるDefault localeを
en_US.UTF-8
にする
4 Localisation Options
->I2 Change Timezone
Asia
->Tokyo
8 Update
ラズパイ自体のアップデートも行います
$ sudo apt update $ sudo apt upgrade -y $ sudo apt dist-upgrade $ sudo rpi-update
設定書き換えなどのためにvimを入れておきます
$ sudo apt-get install vim -y
次にIPの固定化を行います
設定内容は以下のとおり(hostnameの設定は後ほど)
Node | IP | hostname |
---|---|---|
master | 192.168.13.101 | raspberrypi-master |
node1 | 192.168.13.102 | raspberrypi-node01 |
node2 | 192.168.13.103 | raspberrypi-node02 |
/etc/dhcpcd.conf
に以下を追記します(それぞれのNodeに合わせて設定値を変える)
interface eth0 static ip_address=192.168.13.101/24 static routers=192.168.13.1 static domain_name_servers=192.168.13.1 8.8.8.8
反映します
$ sudo service dhcpcd reload
固定したIPでログインができることを確認しておきましょう
$ ssh sminamot@192.168.13.101
SSHの設定をしてパスワードログインはできないようにしておきます
$ sudo vim /etc/ssh/sshd_config
- #PermitRootLogin prohibit-password + PermitRootLogin no
- #PubkeyAuthentication yes + PubkeyAuthentication yes
- #PasswordAuthentication yes - #PermitEmptyPasswords no + PasswordAuthentication no + PermitEmptyPasswords no
- UsePAM yes + UsePAM no
手元のmacから公開鍵を書き込んでおきます(ここでは公開鍵は事前に作成してあるものを利用する)
$ ssh-copy-id -i ~/.ssh/id_rsa_raspberrypi sminamot@192.168.13.101
公開鍵の登録が完了したらsshの再起動を行います
$ sudo systemctl restart ssh
※ 手元のmacから秘密鍵を利用したログインができることを確認しておきましょう
iptablesのバージョン更新
コレをやっておかないとk8s構築した際にPodから他Podや外部への通信がうまくできません
$ sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
swapの無効化もしておきます(しておかないとk8sインストール時に失敗します)
$ sudo dphys-swapfile swapoff $ sudo systemctl stop dphys-swapfile $ sudo systemctl disable dphys-swapfile
続いてhost名の設定
/etc/hostname
を更新します(それぞれのNodeに合わせて設定値を変える)
$ cat /etc/hostname raspberrypi-master
/etc/hosts
も修正します(それぞれのNodeに合わせて設定値を変える)
127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback ff02::1 ip6-allnodes ff02::2 ip6-allrouters -127.0.1.1 raspberrypi +127.0.1.1 raspberrypi-master
ここまでの作業ができたらラズパイを再起動しましょう
$ sudo reboot
パッケージインストール
ここからk8sクラスタ構築に必要なパッケージをインストールしていきます
まずはDocker
$ sudo apt-get install apt-transport-https ca-certificates curl software-properties-common -y $ curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg | sudo apt-key add - $ echo "deb [arch=armhf] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \ $(lsb_release -cs) stable" | \ sudo tee /etc/apt/sources.list.d/docker.list $ sudo apt-get update $ sudo apt-get install docker-ce -y
Errors were encountered while processing: aufs-dkms E: Sub-process /usr/bin/dpkg returned an error code (1)
インストール中に上記のエラーで失敗した場合、以下を実行してから再度インストールを行います
$ sudo rm /var/lib/dpkg/info/aufs-dkms.postinst $ sudo rm /var/lib/dpkg/info/aufs-dkms.prerm $ sudo dpkg --configure aufs-dkms # 再度インストール $ sudo apt-get install docker-ce -y
インストールされたことを確認します
$ sudo docker version Client: Docker Engine - Community Version: 19.03.5 API version: 1.40 Go version: go1.12.12 Git commit: 633a0ea Built: Wed Nov 13 07:37:22 2019 OS/Arch: linux/arm Experimental: false Server: Docker Engine - Community ...
続いてkubernetes
$ curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg|sudo apt-key add - $ echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kube.list $ sudo apt-get update $ sudo apt-get install kubelet kubeadm kubectl -y
インストールされたことを確認します
$ kubectl version Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.2", GitCommit:"59603c6e503c87169aea6106f57b9f242f64df89", GitTreeState:"clean", BuildDate:"2020-01-18T23:30:10Z", GoVersion:"go1.13.5", Compiler:"gc", Platform:"linux/arm"} The connection to the server localhost:8080 was refused - did you specify the right host or port?
ここまではラズパイ3台ともに共通(一部Nodeに合わせて設定を分ける部分もある)で行っておきます
ここからはMaster/Workerノードに分けた設定を行っていきます
Master
$ 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
また、同じくコンソールに出力されたkubeadm join 192.168.13.101:6443 --token XXX
はWorkerのセットアップ時に実行するためメモっておく
続いてネットワークプラグインをインストールします
Raspberry Piはarmプロセッサのため、armにも対応したFlannelを利用します
Creating a single control-plane cluster with kubeadm - Kubernetes
Flannelのタブに記載されているコマンドを実行します
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/2140ac876ef134e0ed5af15c65e414cf26827915/Documentation/kube-flannel.yml
Podのが正しく稼働していることを確認しておきましょう
$ kubectl get po -n kube-system -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES coredns-6955765f44-qrq2s 1/1 Running 0 13m 10.244.0.3 raspberrypi-master <none> <none> coredns-6955765f44-xhqzt 1/1 Running 0 13m 10.244.0.2 raspberrypi-master <none> <none> etcd-raspberrypi-master 1/1 Running 0 13m 192.168.13.101 raspberrypi-master <none> <none> kube-apiserver-raspberrypi-master 1/1 Running 0 13m 192.168.13.101 raspberrypi-master <none> <none> kube-controller-manager-raspberrypi-master 1/1 Running 1 13m 192.168.13.101 raspberrypi-master <none> <none> kube-flannel-ds-arm-gwcv9 1/1 Running 0 2m39s 192.168.13.101 raspberrypi-master <none> <none> kube-proxy-lg4qn 1/1 Running 0 13m 192.168.13.101 raspberrypi-master <none> <none> kube-scheduler-raspberrypi-master 1/1 Running 1 13m 192.168.13.101 raspberrypi-master <none> <none>
Worker
先ほどメモった、Masterのkubeadm init
実行の際に出力されたコマンドを実行します
$ sudo kubeadm join 192.168.13.101:6443 --token XXX \ > --discovery-token-ca-cert-hash sha256:XXX
確認
workerが追加されたことを確認します
$ kubectl get nodes NAME STATUS ROLES AGE VERSION raspberrypi-master Ready master 21m v1.17.2 raspberrypi-node01 Ready <none> 3m40s v1.17.2 raspberrypi-node02 Ready <none> 3m38s v1.17.2
worker nodeにラベルを付けておきます
$ kubectl label node raspberrypi-node01 node-role.kubernetes.io/worker=worker $ kubectl label node raspberrypi-node02 node-role.kubernetes.io/worker=worker # 確認 $ kubectl get nodes NAME STATUS ROLES AGE VERSION raspberrypi-master Ready master 25m v1.17.2 raspberrypi-node01 Ready worker 7m40s v1.17.2 raspberrypi-node02 Ready worker 7m38s v1.17.2
OK!!
Macのkubectlを利用する
k8sの操作をMac上から行うための設定もしておきます(事前にMac上でkubectlを利用できるようにしておく)
master node環境に入り、~/.kube/config
の設定から以下の項目をMac側の~/.kube/config
をコピペすればOK
- clusters
- contexts
- users
nameは必要に応じて変更しても問題ありません(自分はraspberrypi-k8s
に変更しました)
まとめ
これでおうちk8sライフが過ごせそうです
何やろうかな…