ラズパイで k8s cluster を構築した

Posted on 2021-01-04 in zakki

経緯

お正月休みにラズパイを触りたいなーと思っていて意気揚々とこの製品キットをポチっていたんですけど、その後おうち k8s の記事が 2 つ 3 つ目に飛び込んできたためか自分も作りたくなってしまったので、ラズパイとその他必要なものを追加でポチるという非常に計画性皆無な姿を晒していたのがお正月休み直前の私の姿となります。

ちなみに私のラズパイ経験は昔なんとなく触った経験しかないゼロに等しいものです。

準備

というわけでポチったものです。一部自宅に転がっていたものがあります。

名称 製品 個数 備考
Raspberry Pi4 TRASKIT Raspberry Pi 4 Model B 1 製品キット、箱型ケースは未使用
Raspberry Pi4 Raspberry Pi4 ModelB 8GB 2 -
積層式ケース 積層式ケース for Raspberry Pi 4 / Pi 3 Model B+ 1 -
MicroSD カード KEXIN MicroSD カード 32GB(2 個セット) 1 計 2 個
ルーター BUFFALO 無線 LAN 親機 WMR-433W2-BK 1 -
USB 充電器 AUKEY USB 充電器 50W/10A AC アダプター 5 ポート 1 -
USB TypeC ケーブル SUNGUY USB C ケーブル【0.3m*2】 2 計 4 本、ラズパイその他給電用
LAN ケーブル エレコム LAN ケーブル 0.15m×2 本 2 計 4 本
スイッチングハブ BUFFALO スイッチングハブ LSW4-GT-5NS/BK 1 自宅に転がっていたもの、ホコリがすごかった

前述の通り、当初は製品キットのみ購入予定でしたが追加でラズパイ *2 を購入しました。本体を追加購入したのは良かったものの冷却関連の購入をすっかり忘れていて、追加購入分のヒートシンクが無いことに気づいたのは組み上げる途中でした。ああまた追加購入だよ年末に頼んでいつ来るのかな …、と憂いていたら積層式ケース一式の中に予備のヒートシンクがあってホッとしたという一幕がございました。よく知らないまま中身も確認しないとこうなります。

製品キットですが USB-C SD カードリーダーなども付属されていて意外に重宝しています。また日本語に訳された付属マニュアルの翻訳具合が中々いい味を出していて好きです。この辺は販売しているところなどでガラっと変わるのかな。( 今製品ページを改めて読んだら製品説明文からいい味出してた )

スイッチングハブは家に転がっていたものを再利用しました。購入する場合はスイッチングハブも USB 給電仕様のものにした方が楽になると思います。

組み立て

積層式ケースの説明書の言う通りに組み立てて行きます。組み立て自体はそこまで難しいものではありませんでした。各層にラズパイボードを固定して組み立てた後だとヒートシンクを貼りつけるのに難儀するので最初に貼り付けてしまった方がよいです。そういえば説明書のヒートシンクの場所が 3B+ ぽいものでした。4 だと場所が異なるので適当に Web を探しつつ貼り付けましょう。

組み終わると「ルータ +USB 充電器 + ラズパイ 3 段重ね + ハブ」みたいなミニタワーが完成します。この時点で結構な充実感があります。ただこれ、全体として一つに固定されていないのでケーブルの抜き差しをするときなどに予想外にモノも一緒に動くので「ああっ」とか言います。不器用さを全開に出しつつ言いました。結束バンドのようなもので固定すると中々よい塩梅になるかもしれません ( まだ試してない )。

起動

OS はこちらのRaspberry Pi OS Liteを使用しました。デスクトップ環境は要らないかなと思ったので入れていません。… とか言っていますが実態は少し違っており、正確には「デスクトップ環境で起動させたかったけど上手くいかなかったので Lite に切り替えた」となります。悲しい。

製品キットの SD カードにはNOOBSがプリインストールされていて、NOOBS 起動 ->RaspberryPi デスクトップ環境 Install-> 起動 という流れで進むはずなのですがインストール後どうもうまくデスクトップ環境が起動できない。解決を目指し色々策を弄したのですが結局ダメでまさに Noob。そのことに一人自嘲的に笑うも状況は全く改善されるはずもなく上記の方向に舵を取りました。

起動後に SSH を有効にするには、書き込んだイメージを一回マウントして「SSH という名のファイル」を作成することで解決します。Web 上にある Mac での操作例を見つつ、Windows ではどうやるんだろ … とか思っていたのですが、前述のカードリーダーで認識させたところ自動でマウントされまして、ファイル作成することで難なく解決しました。よかった。

ネットワーク

購入したルータ (WMR-433W2-BK) は他の方のおうち k8s 構築記事でもよく使用されているものです。こちらはワイヤレスワンモードというモードにして使用します。無線 LAN 環境から 1 つ IP アドレスをもらい、ローカル IP アドレスと NAT みたくして通信を確立している感じでした。ローカル IP アドレス帯は192.168.13.0/24がデフォルトで決まっており、特に設定変更はできないようです。

Internet ------- Router ---- 無線 LAN(AP) ---- WMR-433W2-BK ---- ハブ ----- ラズパイ *3
 -- パブリック IP --> | <------ 無線 LAN 環境 IP ----> | <--- ローカル IP -----> |
 -- パブリック IP --> | <------- 192.168.1.XX ------> | <--- 192.168.13.YY ---> |

上の図となっている場合、WMR-433W2-BK の IP アドレスはそれぞれ、

  • 無線 LAN 環境 IP: 192.168.1.4
  • ローカル IP: 192.168.13.1

となります。 まとめるとこのような感じとなりました。

ホストネーム 役割 IP アドレス 備考
- k8s 用無線ルータ 192.168.13.1 無線 LAN 環境側 IP アドレスは192.168.1.4
k8s-master Controll-node 192.168.13.2 -
k8s-node-1 Worker-node 192.168.13.5 -
k8s-node-2 Worker-node 192.168.13.6 -

なお、ラズパイ自身も無線 LAN を使用できる ( と思う ) のでそのような方針で構成もできるのかと思いますが特に試していません。

構築

ラズパイ 3 台について SSH でログインして各種設定を行います。詳細は Web にもあるので参照されたい方はそちらを。

  • 作業用ユーザの作成
  • SSH パスワード認証から公開鍵認証へ
    • 初期ユーザ / パスワードは pi/raspberry。ログインするとパスワード変更しろとお達しが表示される。
  • ホストネーム設定
  • タイムゾーン設定
  • ロケール設定
  • /etc/hosts 設定
    • controller-node*1, worker-node*2
  • iptables はiptables-legacyを使用するようにする
    • sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
  • swapoff
    • swapoff -a
  • パッケージ更新
    • sudo apt update
    • sudo apt upgrade

Docker インストール

$ 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 update
$ sudo apt install docker-ce

Kubernetes インストール

$ curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg|sudo pt-key add -
$ echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee etc/apt/sources.list.d/kube.list
$ sudo apt update
$ sudo apt install kubelet kubeadm kubectl

Kubernetes クラスタ作成

Kubernetes init

ラズパイ 3 台について設定完了後、Controller-node でコマンドからクラスタを作成します。コマンドが成功すると出力される kubeadm join XXX.XXX.XXX.XXX:6443 --token=XXXX --discovery-token-ca-cert-hash sha256:XXXは Worker ノードを追加するときに必要となるのでメモしておきます。

$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --ignore-preflight-errors=all

(中略)

Your Kubernetes master 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

(中略)

最初、sudo kubeadm init --pod-network-cidr=10.244.0.0/16で実行したところ、以下応答が返却されました。

[ERROR Mem]: the system RAM (1 MB) is less than the minimum 1700 MB

こちらはこの issueにて報告されている問題で、v1.21 で改善される予定だそう。今回は issue 内にもコメントあるように--ignore-preflight-errorsを付与して回避しています。出力された以下も併せて実行します。

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

ネットワークプラグイン

ネットワークプラグインの flannel を適用します。

$ kubectl apply -f  https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
podsecuritypolicy.policy/psp.flannel.unprivileged created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds create

-fの引数が与えている yaml はドキュメントで指定されている通りのものを使用しています。

Worker 追加

先ほどメモしたkubeadm joinコマンドを Worker-node で実行します。

$ kubeadm join XXX.XXX.XXX.XXX:6443 --token=XXXX --discovery-token-ca-cert-hash sha256:XXX

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 master to see this node join the cluster.

なお、--token=XXXは 24h 経過すると無効になります。そのような場合は Controller-node で再払い出しをしましょう。

$ sudo kubeadm token create
34osle.1we29eimvlo3ieu
$ sudo kubeadm token list
TOKEN                     TTL         EXPIRES                     USAGES                   DESCRIPTION                                                EXTRA GROUPS
34osle.1we29eimvlo3ieu    23h         2021-01-04T22:30:43+09:00   authentication,signing   <none> 

--discovery-token-ca-cert-hash の値は以下コマンドで分かります。

$ openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'

Worker が追加されると、kubectl get nodesに表示されます。

$ kubectl get nodes
NAME         STATUS   ROLES                  AGE     VERSION
k8s-master   Ready    control-plane,master   4d19h   v1.20.1
k8s-node-1   Ready    <none>                 4d19h   v1.20.1
k8s-node-2   Ready    <none>                 4d18h   v1.20.1

気になるところ

ということで無事 k8s cluster を構築できた。色々触ってみて理解を深めていきたい。現段階で少し気になったところ。

  • 時々コマンドが蹴られる

偶にこうなる。

$ kubectl get nodes
The connection to the server 192.168.13.2:6443 was refused - did you specify the right host or port?

Controll-node の CPU 使用率が比較的高いときに蹴られているように見えるのだけど、明確には何が原因か分かっていない。

参考

参考にさせていただいた記事です。ありがとうございました。

Kubernetes 感想