ClusterHATを使って世界最小Kubernetesクラスタを構築する - サーバー構築編

#はじめに
今やはすっかりKubernetesの時代である。
私も『世の中猫も杓子もKubernetesなので自分も乗っかって色々試してみたい。』と思ってはいたんだが、技術自体が潤沢な大規模クラスタ環境を有効活用する為のものなので、ちょっと試してみるにもなかなか難しい。GCPやAWSといったIaaSに一時的にVMを作って動かすというのが入門の主流なようだが、如何せん動かすとお金がかかるので、一度作って一通り触った後はイメージだけ残して二度と触らないというケースが多いんじゃないだろうか。「この話題の機能、うちのKubernetesクラスタでも試してみた」みたいな人ってほんと限られると思う。でも羨ましい。

そんな中、ちょっと前に[Raspberry Pi3 Model Bを複数台使って作るおうちKubernetesクラスタ](https://developers.cyberagent.co.jp/blog/archives/14721/)なるものも登場して「いいなぁ」と思っていた。別に何か運用したい訳では無く、ちゃんとクラスタという環境でKubernetes使ってみたいだけなんだからこれで充分。またさらにRaspberry Pi HATを使ってPi3 B一台でクラスタ構築出来る[ClusterHAT](https://clusterhat.com/)というHATキットの存在を知り、さらに手軽にかつ安価にクラスタ環境を構築出来るかもしれない。

という事で今回実際に試してみる。
![IMG_20180428_130743.jpg](https://qiita-image-store.s3.amazonaws.com/0/213933/4fefa3b8-b507-6d81-8975-9c3f78866b33.jpeg)
そうそう、なんかこういう感じの「豆腐一丁」くらいの大きさのもので、クラスタならではのKubernetesの機能なんかをクラウドVMの課金意識せず手軽に扱えるようになりたい。そう思われた方の参考になれば幸いである。

私はインフラやネットワーク、シス管周りはむしろ疎い方なので、出来ても「Kubernetesクラスタ出来てちょっといじれました」くらいが出来ることの限界だろうと思う。とりあえず当面の目標はそこに置く。
#参考
ClusterHATの本家サイトは[こちら](https://clusterhat].com/)。

以下の先人2サイトがとても参考になったので紹介しておく：
[Raspberry Pi + Cluster Hat でクラスタリングしてみた【ヘッドレスインストール】](http://www.mana-cat.com/entry/2018/02/08/120000)
[Cluster HATの購入から導入まで](http://hoteruaucra.blog.fc2.com/blog-entry-24.html)

またKubernetesをシングルノードで動かす[minikube](https://github.com/kubernetes/minikube)という素晴らしいツールも存在するので、『まずKuberenetesとは何かに興味がある』方はこちらから試してみることをお勧めしたい。
#ClusterHATとは
ClusterHATはRaspberry Pi A+/B+/2/3互換の小規模クラスタ構築用Raspberry Pi HATのキットで、その基盤に最大4つのPi Zero（もしくはZero W）を搭載する事が出来る。ということで母艦（コントローラー）のPi3 B等を合わせて5台クラスタを構築する事が出来る。HATはGPIOにがっつり突き刺す仕様なので母艦のGPIOは埋まってしまうが、他ノードの電源はここから供給されるので電力的な配線は不要。母艦とはUSBと繋がっており、ノードのネットワークはこのUSBを介してUSB Gadget Modeでネットワークをコントローラーから提供できる。Zero Wを使う場合には当然ネットワークは直接ノード自身から参加する事も可能。
![IMG_20180425_181547.jpg](https://qiita-image-store.s3.amazonaws.com/0/213933/fe97aedc-3e95-9035-a463-06e587bd7ae9.jpeg)
こんな感じでむき出しになったUSB-Bのオス端子にPi Zeroを突き刺す事で固定される。母艦とノードの固定はこれだけなのだが、そもそもPi Zeroが小さいので安定はしている。ちなみにPi Zeroの方にはUSB-Bのメス端子が2つ並んでいるが、PWR INではなくUSBの方に刺さないといけない。

ClusterHATの価格は日本円で3,500円くらい。既にコントローラーとなるPi3 Bがある場合にはCluster HATと必要なノード分のPi Zeroが必要となるが、母艦とClusterHATを繋ぐちょうどよい長さのUSBケーブルも同梱されており他には必要ない。今回は2号のマイクラ用Pi3 Bが貰えたのでCluster HATとPi Zero3枚を購入。送料も合わせるとトータル7,000円くらいで揃った。

Pi Zeroは製品パーツとして大量購入される事を避ける為に各パートナーから1台ずつしか購入できない。私は日本、香港、そしてCluster HATを購入したイギリスの[PIMORONIさん](https://shop.pimoroni.com/products/cluster-hat)からそれぞれ購入した。ちなみに、GPIOヘッダをはんだ付けしたZero Wには購入数制限が無かったはずなので、[スイッチサイエンスさんの該当ページ](https://www.switch-science.com/catalog/3646/)から纏めて購入する事が可能、なはず。
#ClusterHAT用ケース?
ちゃんとしたケースがあるかどうかって案外気になっていて、こういうややレアパーツを使う場合にはケースなんかが無かったりするが、[ClusterHAT用ケース](https://www.modmypi.com/raspberry-pi/cases-183/raspberry-pi-b-plus2-and-3-cases-1122/cases-for-hats-and-boards-1133/cluster-hat-case)も存在する。見た目シンプルながらClusterHATのLEDを小さな専用アクリルバーを使ってケース上面に表示させるという素敵な仕様になっている。ただファンを取り付ける仕組みは無い。

ただ今回はまずClusterHATを試してみる事が目的なので、既存のアクリルスタック型のPi3 Bケースの使える下段だけ使うことにする。フルケースではないので当然保護性等はほぼ無いんだが、それでもPiクラスタが固定出来る点、そして裏面に付いているメモリのヒートシンク用の穴が開いているという点を考えると悪くない。ソープディッシュのようなものだが、あると無いのとではだいぶ違う。
![IMG_20180425_181527.jpg](https://qiita-image-store.s3.amazonaws.com/0/213933/bcca4fd6-727e-cc5a-a1a0-e12bdb658241.jpeg)
ファンが付かないのでちょっと熱は気になる。コントローラーのGPIOが完全に埋まっているのでファンの電源はどこからか取ってこないといけないんだが、ノードのPi Zeroのうち1つにGPIOヘッダー付けたものにすれば取れるか、とは思う。ここは後々もうちょっと考える。
#サーバー構築
さて、ようやく本題のサーバー構築に移っていくが、ClusterHATの専用イメージが提供されている事、ClusterHAT用の専用コマンドが用意されている事以外は普通のRaspberry Piのサーバー構築とあまり変わりないと思う。USB Gadgetモードを使ってネットワーク接続をブリッジするところは特殊（であり個人的に一番勉強になったところ）だが、これもClusterHAT独自の技術という訳では無いのでUSB Gadget Modeを使ったことがある方であれば特段新しいものは無いと思う。
###ClusterHAT用イメージ
イメージは[Cluster HAT本家](https://clusterhat.com/setup-software)で提供されている。

イメージはマスタと各ノード毎個別に用意されていおり、それぞれをSDカードに書き込んでいけば良い。ただ提供イメージはマスタも各ノードもほとんど同じなので、1つだけダウンロードしてきてcmdline.txtをそれぞれ変更する事も可能。（具体的な変更方法は本家の中級向け(Intermediate)説明を参照。）

イメージはGUIありとGUI無し（Stretch Lite）版があり、またネットワーク接続方法としてUSB Gadget Modeを使うものとNATを使ったものがある。今回は一番スタンダードなGUI無しUSB Gadget Mode版を使用する。ここで一つ注意点があって、最近出たPi 3 B+だとUSB Gadget Modeで繋げる事が出来ないようなので、NAT版を使う必要がある。NAT版の詳細は[該当Googleグループのポスト](https://groups.google.com/forum/#!topic/clusterhat/vwiVEcjz3L0)を参照のこと。

もう一つ、原則これらノードはヘッドレスで構築するのでsshで接続できる必要があるが、最近のRaspbianではデフォルトでsshがoffになっている点。これはイメージを焼いた後のSDに自分で対応する必要がある。幸いSDのルート直下にsshという名前のファイルを作れば対応できる：

```bash:GitBash
cd d
touch ssh
```

とコマンド打ってからSDを取り出す。これで初回起動時にSSHがONになる。
###コントローラーから各ノードの電源を管理
ここは通常のRaspberry Piと同じで、SDを刺して電源を入れれば良。通常通りraspi-configでパスワード変更やSDの使用容量拡張等をやった後にapt-get update/upgradeを実施。

Pi Zeroの方はClusterHATに刺しただけでは電源供給を受けない。ClusterHATでは各ノード管理用のコマンドが用意されているので、刺した後にこれらコマンドを実行する必要がある。

```bash:controller
#ノードの電源をON
$ clusterhat on P1 P2
#ノードの電源をOFF
$ clusterhat off P1 P2
```

引数に操作対象となるノード（P1からP4）をリスト指定する事が出来るが、省略すると全ノードが対象となる。ほかにもノードのアラートLEDを操作するclusterhat alert on/offというコマンドも用意されている。

電源が入ると、今度は各ノードに入り込んで同様の初期設定を行う。
###ノードにsshで繋げる
clusterhat onにした後、私の場合はコントローラーの再起動が必要だったが、再起動後ブリッジの接続状況を確認すると以下のようにブリッジが認識されていた。

```bash:Controller
#ノードの電源をON
$ brctl show br0
bridge name     bridge id               STP enabled     interfaces
br0             8000.b827eb1aff31       no              eth0
                                                        ethpi1
                                                        ethpi2
                                                        ethpi3
```

また、コントローラーから各ノードへsshする場合、avahiのデーモンが既に走っているのでそれぞれをp1.local、p2.localという名前でアクセスできる。（コントローラー自身はcontroller.local）ユーザーIDはpiなので以下でsshに繋がる：

```bash:Controller
#ノードの電源をON
$ ssh pi@p1.local
$ ssh pi@p2.local
$ ssh pi@p3.local
```

###コントローラーがWi-Fi接続の場合
今回初期設定時にコントローラーはWi-Fi接続してあり、ClusterHATの初期設定ではブリッジが上手く設定できていなかった。上記brctl showではノードがマッピングされておらず、またssh接続しようとしてもいないと怒られた。調べてみたところデフォルトのイメージではコントローラーのeth0に対してマッピングされていた事が原因で、そもそもケーブルを接続してもいなかったので見つからないということだった。

まずはWi-Fiを使えるようにした上でマッピングを変更しないといけない。Wi-Fiを使う場合は：

```bash:Controller
#Wi-Fiを使用可能にする
$ wpa_passphrase "YOU_SSID" "KEY" | sudo tee -a /etc/wpa_supplicant/wpa_supplicant.conf > /dev/null
```

Wi-Fi設定後、/etc/wpa_supplicant/wpa_supplicant.confに既に設定されているbr0の設定情報を更新する。（eth0のマッピングをwlan0に変更。）変更後再起動すると繋がった。

結局この後各ノードのapt-get upgrade中に中断が発生したりネットワーク状態が不安定だったので、今回は元のイーサネット経由の設定に戻したが、Wi-Fiでも繋がる事の確認は取れた。
###困った時にはminicom
上記のWi-Fi事例のように、ヘッドレスの構成なのでこの手のエラーが出ると原因究明が難しい。そもそもノードに繋ぐことさえ出来ないのでノード側を調べようがない。これはノードを取り外して個別にモニタやキーボードに繋げないといけないかと困った（ちっちゃないHDMIのコネクタもbluetooth以外のキーボードも無いので）が、ターミナルエミュレーターを使ってシリアル接続して解決している人がいた。sshが使えなくてもエミュレーター経由で一旦繋げて各種対応を行うことが出来る。

```bash:Controller
#ノードにエミュレーター経由で接続
$ minicom p1.local
```

usbの接続は出来ているしavahiのデーモンは動いているので名前解決は出来るので、シリアル接続は可能だった。考えてみると、Pi Zeroを使ってUSB Gadget経由で接続せずにPi Zero Wで個別にネットワークに参加させる場合にもこの方法は有効だと思う。

###コントローラー&各ノードに固定IPを割り振る
各サーバーのIPが動的に変わるのはおそらく好ましくないだろうとのことで固定IPを割り振っていく。それぞれの/etc/dhcpcd.confに固定IP設定を記載していく。

```bash:Controller
interface br0
static ip_address=192.168.1.100/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.1
#fallback clusterhat_fallback_br0
```

```bash:Node
interface usb0
static ip_address=192.168.1.102/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.1
#fallback clusterhat_fallback_usb0
```

コントローラーとノードでは定義が異なる。コントローラーはeth0はブリッジの接続エンドポイントとして使用しブリッジbr0をネットワークに繋げているのでbr0に。ノードの場合はUSB Gadget ModeでUSB経由で繋げているのでusb0に。いずれもip address等でどのデバイスにIPが割り振られているかを確認の上そのデバイスに対して定義を行う。再起動すると：
![IMG_20180428_235635.jpg](https://qiita-image-store.s3.amazonaws.com/0/213933/d9bcc9ed-d858-392c-9cbe-892ebee53d81.jpeg)
こんな風になると成功。Horay!
#おわりに
ClusterHATを使ってKubernetesクラスタを構築するというゴールに向けて、今回はまずサーバー設定回りまでを行った。当然上記のようにスムーズに全てが進んだ訳では無く何度か『詰んだ』と思う事もあったが、その過程で得た情報を合わせて記載出来たので結果良かったと思っている。

次回からは今回準備した環境に、kubeadmを使わず素手でkubernetesを構築する。素手と言っても有名なKelsey Hightowerさんの[Kubernetes The Hard Way](https://github.com/kelseyhightower/kubernetes-the-hard-way)をなぞるつもりである。この豆腐クラスタではチュートリアル通りにいかないところ等、何かしら詰まるところがあったら特にそのあたりを具体的に記述したいと思う。まずは[インストール前にTLS証明書関連を準備する](https://qiita.com/ShinHashitani/items/d91599399422b7b03cb2)手順について纏める。

私と同様にKubernetesを色々触って理解したいとお考えの方にとって少しでも参考になれば幸いである。