一家に一台Kubernetesクラスタの時代が到来したとちらほらと聞こえ始めてきたので、いまさらながらRaspberry PIでKubernetesクラスタを作ってみました。
Raspberry PIのKubernetesクラスタであれば、EKSのようなクラウドベンダーが提供しているサービスではないので
- マスターノードに制約がなく自由に設定ができる
- サーバ費用をかけずに、複数ノード環境でaddonの検証ができる
というのが良いところか思います。
用意したもの
ラズパイとmicroSDカード、microUSBは千石電商、LANケーブルとケースはAmazon、その他はヨドバシAkibaで入手しました
- Raspberry PI 3 model B+ × 3
- 2.4A microUSB ケーブル 20cm × 5
- 6ポート 50W USB 充電機 (Elecom MPA-ACD03BK) × 1
- 50cm LANケーブル × 4
- コンパクト無線親機 (BUFFALO WMR-433W2-BK) × 1
- microUSB 給電 スイッチングハブ (LAN-SW05PSBE) × 3
- 積層式ケース × 1
- 六角スペーサー予備(M3×5mm) × 1
揃えた中でちょっと微妙だったかもと思ったは以下の2つです。
- LANケーブルは見た目にこだわった結果、長いものしかなく上記のものを選択しましたが短い方が配線は綺麗になるかと思います。
- 充電機に使ったElecom MPA-ACD03BKは思ったより大きく、横にすると入らなくなったので、もう少し小さいものを購入した方が良さそうです。
環境の構成
SSHで接続するPC環境はSSHを使える環境、Raspbianイメージを作成するPC環境はイメージをSDカードにwriteできる環境であればどんな環境でも大丈夫です。
- Raspberry PI k8s環境 (マスター, ワーカノード共通)
- Raspbian Buster Lite (Version:July 2019, Release date:2019-07-10, Kernel version:4.19)
ラズパイクラスタをRaspbian stretch lite
で作ったという記事を良くみかけますが、Raspbian Buster Lite
に関してもそれらの記事の設定方法とまったく同じで手順で大丈夫でした。
完成したところ
ケーブルはよく見かける感じのものだと味気ないので、白黒のケーブルにしてみました。ケースもグレーにして大人っぽい上品な感じに仕上げてみました。
ビールかなんかと一緒に置くとより一層大人っぽい雰囲気を楽しめるかもしれません。
作り方
組み立て
組み立て方はつまるところがないと思うので省略します。
イメージの準備
以下のSDカードの準備イメージ内のファイル編集は、ラズパイ3台分 (SDカード3枚)行います。
SDカードの準備
Raspbianイメージを作成するPC環境(Windows 10環境を使いました)で、Raspbian Buster Lite (旧raspbian stretch lite)の最新版のイメージをダウンロードします。
イメージのSDカードへの書き込みは、Win32 Disk Imagerというツールを使いました。
イメージ内のファイルを編集
SDカード作成後、Windows OS上で以下のファイルを変更しました。
/boot
ディレクトリ直下にあるcmdline.txt
を編集し、cgroup_enable=cpuset cgroup_enable=memory
を追加- cgroupsのcpusetとmemoryを有効化
- cgroupsのcpusetとmemoryを有効化
Raspbian起動後の下準備
microSDカードをラズパイに挿入、充電器からmicroUSBケーブルを指して給電してラズパイを起動します。ラズパイ各環境でIPアドレス、ホスト名設定するまではHDMIケーブルで外部モニタ、USBキーボードを接続して操作しました。
下準備の設定内容は、マスターノード、ワーカーノードで共通です。
パッケージ更新、スワップオフ
デフォルトの
- ユーザ: pi
- パスワード: raspberry
でログイン。
aptパッケージを最新化します。
$ sudo apt-get -y update $ sudo apt-get -y upgrade
Kubernetes 1.8以降スワップが有効のままだとkubeletが起動しなくなったので、スワップをオフにします。
$ sudo dphys-swapfile swapoff $ sudo dphys-swapfile uninstall $ sudo update-rc.d dphys-swapfile remove
ホスト名・Pアドレスを固定
次に /etc/hostname
, /etc/hosts
を編集しホスト名を変更、/etc/dhcpcd.conf
を編集しIPアドレスを固定します。
ホスト名、IPアドレスは3台それぞれ
をホスト名 (IPアドレス)にしてみました。
以下のようにマスターノードのホスト名の設定しました。
$ sudo vi /etc/hostname - raspberrypi + k8s-master-01
$ sudo vi /etc/hosts - 127.0.1.1 raspberrypi + 127.0.1.1 k8s-master-01
同様にマスターノードのIPアドレス設定を設定しました
$ sudo vi /etc/dhcpcd.conf 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
PC環境からSSH接続できるように
SSHの秘密鍵と公開鍵を作っておきます。鍵は同じものを使うようにしたため、実行は1回のみです。
$ ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/home/username/.ssh/id_rsa): Enter passphrase (empty for no passphrase): <パスフレーズ> Enter same passphrase again: <パスフレーズ> Your identification has been saved in 【秘密鍵のファイル名】 Your public key has been saved in 【秘密鍵のファイル名】.pub.
作った公開鍵をラズパイ側の~/.ssh/authorized_keys
にコピーします。以下はマスターノードの設定で実行したコマンドです。
$ ssh-copy-id -i 【秘密鍵のパス】 pi@192.168.13.101 /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "秘密鍵のファイル名.pub" The authenticity of host '192.168.13.101 (192.168.13.101)' can't be established. ECDSA key fingerprint is SHA256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. Are you sure you want to continue connecting (yes/no)? yes /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys pi@192.168.13.101's password: Number of key(s) added: 1 Now try logging into the machine, with: "ssh 'pi@192.168.13.1021" and check to make sure that only the key(s) you wanted were added.
SSH接続しやすいようにPC設定
.ssh/configに以下のように追加します。
Host k8s-master-01 HostName 192.168.13.101 User pi Port 22 IdentityFile 【秘密鍵のパス】
ここまででSSH接続の設定は終わりです。以後の作業は、PC環境からSSHで各ラズパイ環境接続して作業を行っていきます。
Dockerをインストール
各ラズパイ環境にDockerをインストールしていきます。
$ curl -sSL https://get.docker.com/ | sh
kubelet kubeadm kubectl kubernetes-cni のインストール
https経由でaptを実行するために必要なパッケージをインストールします。
$ sudo apt-get install -y apt-transport-https
Google cloudの公式キー登録します。
$ curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
ソースリストにkubernetesを追加します。
$ echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
apt更新
$ sudo apt-get update
kubelet kubeadm kubectl kubernetes-cniをインストールします。
$ sudo apt-get install kubelet kubeadm kubectl kubernetes-cni
各ノード間でバージョンが異なると予期せぬ動きに繋がるので、バージョンが変わらないようにしておきます。
$ sudo apt-mark hold kubelet kubeadm kubectl kubernetes-cni
マスターノードのセットアップ
以下のコマンドを実行し、kubernetesクラスタのコントロールプレーンを初期化します。
$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16
後にネットワークaddonとしてインストールするflannelのドキュメントを読むとkubeadmの場合、pod-network-cidrに制約があるようなのでドキュメント通りにしています。
他の有名どころのネットワークaddonとして
- Calicoは、AMD64プロセッサが動作要件にある。Raspbianは32bitなので候補から除外
- Weaveに関しては、ARMをサポートしているが32bitに対応しているか明示されていないので候補から除外
消去法で残ったflannelを使うことにしています。
kubeadm init
すると実行結果の一番最後の他のワーカーノードがジョインするためのコマンドが表示されるので控えておきます。
Your Kubernetes control-plane 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 You should now deploy a pod network to the cluster. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/ Then you can join any number of worker nodes by running the following on each as root: kubeadm join 192.168.13.101:6443 --token XXXXXXXXXXXXXXXXX \ --discovery-token-ca-cert-hash sha256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
続いて、kubeadm initの実行結果に記載されているコマンドを実行します。
$ mkdir -p $HOME/.kube $ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config $ sudo chown $(id -u):$(id -g) $HOME/.kube/config
現時点でどのPodが動いているか確認してみます。
$ kubectl get pods --all-namespaces NAMESPACE NAME READY STATUS RESTARTS AGE kube-system coredns-5c98db65d4-4bhgq 0/1 Pending 0 14m kube-system coredns-5c98db65d4-p5s4t 0/1 Pending 0 14m kube-system etcd-k8s-master-01 1/1 Running 0 14m kube-system kube-apiserver-k8s-master-01 1/1 Running 0 13m kube-system kube-controller-manager-k8s-master-01 1/1 Running 0 14m kube-system kube-proxy-dz99s 1/1 Running 0 14m kube-system kube-scheduler-k8s-master-01 1/1 Running 0
Pod network addonがなく、corednsのpodがREADYの状態になっています。 Network addonとしてflannelを入れてみます。
# コマンドは https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#pod-network から取得 $ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/62e44c867a2846fefb68bd5f178daf4da3095ccb/Documentation/kube-flannel.yml
数分待ってから再度Podの状態を確認してみると
$ kubectl get pods --all-namespaces NAMESPACE NAME READY STATUS RESTARTS AGE kube-system coredns-5c98db65d4-4bhgq 1/1 Running 0 37m kube-system coredns-5c98db65d4-p5s4t 1/1 Running 0 37m kube-system etcd-k8s-master-01 1/1 Running 0 37m kube-system kube-apiserver-k8s-master-01 1/1 Running 0 36m kube-system kube-controller-manager-k8s-master-01 1/1 Running 1 37m kube-system kube-flannel-ds-arm-szj4t 1/1 Running 0 4m50s kube-system kube-proxy-dz99s 1/1 Running 0 37m kube-system kube-scheduler-k8s-master-01 1/1 Running 1
全Pod Runningになっていることを確認できました。
ワーカーノードをKubernetesクラスに追加
残りのワーカーノードにSSHログインして、先程控えておいたクラスタ参加のためのコマンド実行するだけです。
$ sudo kubeadm join 192.168.13.101:6443 --token XXXXXXXXXXXXXXXXX \ --discovery-token-ca-cert-hash sha256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
再度マスターノードにSSHログインして、以下のコマンドを実行すると
$ kubectl get nodes NAME STATUS ROLES AGE VERSION k8s-master-01 Ready master 58m v1.15.3 k8s-worker-01 Ready <none> 17m v1.15.3 k8s-worker-02 Ready <none> 19s v1.15.3
無事3台のノードでkubernetesクラスタができていることが確認できました。