Raspberry Piを使ってKubernetesクラスタを構築した
Raspberry Piを使って自宅環境でKubernetesクラスタを構築しました。
いわゆる、おうちKubernetesをやってみたかったのでやりました。
その内容を紹介します。
物理構築
自宅で未使用だったRaspberry Pi 3と買い足したRaspberry Pi 4を使用しました。
物品一覧
- Raspberry Pi 3 Model B 1台
- Raspberry Pi 4 Model B/2GB 2台
- microSDカード 32GB 3枚
- Amazon.co.jp: ロジテック スイッチングハブ 5ポート 10/100Mbps AC電源 小型 LAN-SW05PSBE: パソコン・周辺機器
- Amazon | GeeekPi Raspberry Pi 4モデルB用Piラックケース、冷却ファンおよびヒートシンク付きRaspberry Pi 3 B +ケース、4層アクリルケーススタッキング可能ケースRaspberry Pi 3/2モデルB用クラスターケース (クリア) | GeeekPi | ベアボーンPC 通販
- LANケーブル 4本
- Amazon.co.jp: AUKEY USB充電器 50W/10A ACアダプター 5ポート スマホ充電器 携帯急速充電 AiPower搭載 Apple 新型 iPad Pro/iPhone X/iPhone 8 / iPhone 7 / 7 Plus/iPod/Xperia/Nexus/Galaxy等対応 (ブラック)PA-U33【PSE認証済み】: 家電・カメラ
- micro USB ケーブル 2.4A 2本(Raspberry Pi 3用)
- USB Type-C ケーブル 2本(Raspberry Pi 4用)
- Micro HDMI to HDMI変換ケーブル(Raspberry Pi 4用)
- Raspberry Pi 4をディスプレイにつなぐのに使いました
- 両面テープ
- スイッチングハブを固定するのに使いました
注意
Raspberry Piの電源にモバイルバッテリーを使用しています。
ただRaspberry Piで推奨されている電源のスペックはRaspberry Pi 3では2.5A、Raspberry Pi 4では3.0Aとなっています。
今回使用しているモバイルバッテリーはこのスペックを満たしていません。
今のところ、問題なく起動していますが、使用は自己責任でお願いします。
配置について
1段目から3段目までにRaspberry Piを配置し、4段目にスイッチングハブを配置しました。
バッテリーは横に置くようにしました。
Raspberry Piのセットアップ
OSのインストール
microSDカードにRaspbian OSをインストールします。
SDカードリーダーが必要になります。
公式で提供されているRaspberry Pi Imagerを利用してRaspbianをインストールします。
Setting up your Raspberry Pi - Set up your SD card | Raspberry Pi Projects
Raspberry Piの設定変更
それぞれのRaspberry Piに対して下記手順を行います。
Raspberry Piの起動
- Raspberry PiにmicroSDカードを挿入する
- Raspberry PiとディスプレイをHDMIでつなぐ
- Raspberry Piにキーボードをつなぐ
- Raspberry Piにマウスをつなぐ
- Raspberry Piの電源をいれる
OSの設定変更
- 初回起動時のセットアップ画面は適宜設定する
- WiFiのセットアップ、ソフトウェアのアップデートはスキップする
- SSHを有効にする
- 設定 -> Raspberry Piの設定 -> インターフェイス -> SSHを有効にする
- 有線LANのIPアドレスを固定にする
- こちらを参考にさせていただきました -> ラズベリーパイで固定IPアドレスを設定する - ムギークのブログ
- cgroupsを有効にする
/boot/cmdline.txt
にcgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1
を追記する
- Raspberry Piを再起動する
SSHの設定
これ以降はRaspberry Piをスイッチングハブ経由でルータに接続し、操作用PCからSSHで操作します。
- SSHの設定変更
- 操作用PCからSSHでRaspberry Piに接続する
- 初期設定時はuser = pi、password = raspberryになっています
- SSHの公開鍵認証を設定する
- 操作用PCのSSH公開鍵をRaspberry Piの
~/.ssh/authorized_keys
に追記する
- 操作用PCのSSH公開鍵をRaspberry Piの
- SSHのパスワード認証を無効化する
/etc/ssh/sshd_config
にPasswordAuthentication no
を記載する
- 操作用PCからSSHでRaspberry Piに接続する
Kubernetesクラスタのセットアップ
Ansibleでセットアップしました。
Ansibleのファイルは下記にあります。
Ansibleで使用するhostsファイルの対象IPアドレスなどを設定内容に合わせて適宜変更します。
その後、以下のコマンドを実行すればKubernetesクラスタを構築できます。
$ ansible-playbook -i hosts control-plane-playbook.yml $ ansible-playbook -i hosts node-playbook.yml
playbookの内容解説
Control Planeのセットアップ
Dockerをインストールします。
control-plane-playbook.yml
... // リポジトリの追加 - name: Add an apt signing key for Docker apt_key: url: https://download.docker.com/linux/raspbian/gpg state: present - name: Add apt repository for stable version apt_repository: repo: deb [arch=armhf] https://download.docker.com/linux/raspbian {{ ansible_distribution_release }} stable state: present // インストール - name: Install docker and its dependecies apt: name: "{{ packages }}" state: present update_cache: yes vars: packages: - docker-ce - docker-ce-cli - containerd.io notify: - docker status ...
リポジトリの追加では、raspbian用のURLの指定が必要です。
kubeletを起動可能にするため、スワップを無効にします。
control-plane-playbook.yml
... - name: Remove swapfile from /etc/fstab mount: name: "{{ item }}" fstype: swap state: absent with_items: - swap - none - name: Disable swap command: swapoff -a when: ansible_swaptotal_mb > 0 ...
Kubernetesをkubeadmでセットアップします。
control-plane-playbook.yml
... - name: Add an apt signing key for Kubernetes apt_key: url: https://packages.cloud.google.com/apt/doc/apt-key.gpg state: present - name: Adding apt repository for Kubernetes apt_repository: repo: deb https://apt.kubernetes.io/ kubernetes-xenial main state: present filename: kubernetes.list - name: Install Kubernetes binaries apt: name: "{{ packages }}" state: present vars: packages: - kubelet - kubeadm - kubectl - name: Configure node ip lineinfile: create: yes path: /etc/default/kubelet line: KUBELET_EXTRA_ARGS=--node-ip={{ ansible_host }} - name: Check if kubeadm has already run stat: path: "/etc/kubernetes/pki/ca.key" register: kubeadm_ca - name: Initialize the Kubernetes cluster using kubeadm command: kubeadm init --apiserver-advertise-address="{{ ansible_host }}" --apiserver-cert-extra-sans="{{ ansible_host }}" --node-name k8s-control-plane --pod-network-cidr=10.244.0.0/16 when: not kubeadm_ca.stat.exists - name: Restart kubelet service: name: kubelet daemon_reload: yes state: restarted ...
kubeadm init
は一度実行すると2回目以降はエラーになるので、2回目以降は実行されないように条件を付けてます。
Flannelをデプロイします。
control-plane-playbook.yml
... - name: Setup kubeconfig for user command: "{{ item }}" with_items: - mkdir -p /home/pi/.kube - cp /etc/kubernetes/admin.conf /home/pi/.kube/config - chown pi:pi /home/pi/.kube/config - name: Install flannel pod network become: false command: kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml ...
kubeadm join
の内容をローカルにコピーします。
後ほど、NodeをKubernetesクラスタに参加させるのに使用します。
control-plane-playbook.yml
- name: Generate join command command: kubeadm token create --print-join-command register: join_command - name: Copy join command to local file become: false local_action: copy content="{{ join_command.stdout_lines[0] }}" dest="./join-command"
Nodeのセットアップ
ほぼcontrol planeの時と内容は一緒です。
control planeが出力したkubeadm join
のコマンドを実行します。
node-playbook.yml
... - name: Copy the join command to server location copy: src=join-command dest=/tmp/join-command.sh mode=0777 - name: Reset Kubernetes component command: kubeadm reset --force register: reset_cluster - name: Join the node to cluster command: sh /tmp/join-command.sh when: reset_cluster is succeeded ...
kubeadm join
は一度実行すると2回目以降はエラーになるので、毎回kubeadm reset
をして実行できるようにしています。
結果
control-planeの.kube/configの内容を操作用PCの.kube/configに追記すれば、操作用PCからkubectl
を実行できます。
$ kubectl get node NAME STATUS ROLES AGE VERSION k8s-control-plane Ready master 16h v1.18.6 raspberrypi-2 Ready <none> 143m v1.18.6 raspberrypi-3 Ready <none> 143m v1.18.6
まとめ
Kubernetesクラスタを構築する中でkubeadmを試行錯誤したのでそのあたりが勉強になりました。
あとはAnsibleを普段使わないのでハマりながらクラスタ構築用のスクリプトを書きました。