LoginSignup
9
5

More than 3 years have passed since last update.

Raspberry PiでKubernetesクラスター用のNFSを作る

Posted at

概要

  • Raspberry Pi 4 Model B + M.2 SSDでNFSサーバーを構築
  • KubernetesのPersistent Volumeとして登録

背景

自宅内で複数端末から接続できる Jupyter 環境欲しいなあ。

→ 例によってラズパイk8sクラスター上に作ろう。

→ ラズパイk8sクラスターに永続ボリューム無いからデータ保存どうしよう...

→ NFS追加しよう!せっかくだから見栄え意識してこれもラズパイで構築しよう!

Before After

Before
P_20200210_085613.jpg

After
最下段のハブを上に移動し、空いたスペースにラズパイ + SSDを追加しました。
P_20210512_191122.jpg

※ ラズパイk8sクラスター作成に関してはこちらで記事にしています。

そもそも何故ラズパイk8sに別途永続ボリュームが必要なのか?

端的に言うと、k8sのPodは揮発性だから。
Pod中に保存してもデプロイ等でPodが再作成されると消えます。

なので、Persistent Volumeという概念がk8sにはあります。

図にするとこんな感じです。(実際にはPVCをつかってPVをPodに割り当てますが割愛します)

persistent_volume.png

Dockerと名前つきボリュームの関係をイメージするとわかりやすいかも。

ハードウェア

今回追加したハードウェアは以下になります。

  • Raspberry Pi 4 Model B 8GB
  • Geekworm X873
  • M.2 SSD (2280) 128GB NVMe

ラズパイのストレージにはmicroSDを使うのが一般的ですが、NFSとして永続ストレージに使用するには適していません。
そのため、SSDをストレージに採用します。
普通の2.5インチSSDでもいいのですが、クラスターの積層ケースに積むことを考慮してM.2 SSDを採用しました。

P_20210511_211740.jpg
上記は X873 に M.2 SSD を取り付けた状態です。
これをラズパイの下に固定します。

構築

ここからはOS、NFS、PersistentVolumeの構築を順に紹介していきます。

OSイメージの書き込み

まずは X873 をラズパイではなく、作業マシンにUSB接続します。
その状態でRaspberry Pi Imager を使用してSSDにOSイメージを書き込みます。

Raspberry Pi Imagerはシンプルなので公式ドキュメントを読めばわかります。
OSはせっかくメモリ8GBモデルにしているので、64bit版にします。
まあ、1プロセスで3GB以上メモリを使う予定はないのですが。
(32bitだと1プロセスのメモリが3GBに制限される)

64bit版は2021/05/23時点ではRaspberry Pi Imagerから選択できないため、以下の公式ダウンロードページから取得し、解凍し、 Use custom から指定して利用します。

スクリーンショット 2021-05-23 21-56-52.png

あとは WRITE ボタンを押せばOSイメージがSSDに書き込まれます。

OSイメージが書き込めたら、追加でファイルを設置してsshを起動する設定にします。
再度SSDをUSB接続しなおして、 boot/ssh ファイルを生成します。

# 起動時にsshを有効にする設定
# パスは私の環境の例
$ touch /media/reireias/boot/ssh

OS初期設定

ラズパイにSSDを接続し、電源を入れます。
ルーター等からIPさえ特定できれば、ラズパイにディスプレイもキーボードも接続せずに初期ユーザー + 初期パスワードでssh接続できるはずです。
(我が家にmicroHDMI端子が無くてつながるディスプレイはなかった...)

ssh鍵の設置、パスワード変更、swapの無効化、ホスト名の設定等を行っていきます。
最後にパッケージを更新して再起動をかけます。

# authorized_keysの設定
$ scp ~/.ssh/id_rsa.pub pi@ip:/tmp/authorized_keys
$ ssh pi@ip
$ mkdir ~/.ssh
$ cp /tmp/authorized_keys ~/.ssh/authorized_keys

# 初期パスワードを変更
$ sudo passwd pi

# swapを無効化
$ sudo systemctl disable dphys-swapfile.service

# ホスト名を設定
# 今回は pikube01 ~ pikube03 という名前にしました
$ sudo vi /etc/hosts
$ sudo vi /etc/hostname

# 何らかの手段でIPを固定化しておくと便利でしょう
# 私はルーターの機能で固定DHCPを設定しています

# packageの更新
$ sudo apt update
$ sudo apt upgrade

# もろもろを反映させるために再起動
$ sudo reboot

あとはお好みでrsyslogやnode_exporter等設定していくのもいいでしょう。
私は新しいラズパイに毎回設定するのが面倒なのでAnsibleのスクリプトを用意して流しています。

NFSの設定

「ラズパイ NFS」等でググると山ほど記事がでてきます。
通常の説明はそちらに譲るとして、本記事ではせっかくなので私が使ったAnsibleでのスクリプトを紹介します。
これさえ用意しておけば、何度故障したって新規構築は楽ですね。

ホスト名を pikube04 にしているので、一部ファイル名もホスト名に合わせています。

$ tree
.
├── inventories
│   └── pikube04.yml
├── pikube04.yml
└── roles
    └── nfs
        ├── files
        │   └── exports
        └── tasks
            └── main.yml
inventories/pikube04.yml
---
raspberrypi:
  hosts:
    pikube04:
  vars:
    ansible_user: pi
    ansible_ssh_private_key_file: ~/.ssh/id_rsa
    ansible_become: yes
pikube04.yml
---
- hosts: raspberrypi
  roles:
    - nfs
roles/nfs/files/exports
# /etc/exports: the access control list for filesystems which may be exported
#               to NFS clients.  See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes       hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4        gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes  gss/krb5i(rw,sync,no_subtree_check)
#
/opt 192.168.0.0/255.255.255.0(rw,sync,no_subtree_check,all_squash)

※利用する場合はLANのCIDRに応じて 192.168.0.0/255.255.255.0 を修正してください。

roles/nfs/tasks/main.yml
---
- name: install nfs-server
  apt:
    name: nfs-kernel-server
    update_cache: yes

- name: create nfs directory
  file:
    path: /opt/nfs
    owner: nobody
    group: nogroup
    mode: 0755
    state: directory

- name: create nfs sub directory
  file:
    path: "/opt/nfs/{{ item }}"
    owner: nobody
    group: nogroup
    mode: 0755
    state: directory
  with_sequence: start=1 end=10 format=pv%02d

- name: copy exports
  copy:
    src: exports
    dest: /etc/exports
    owner: root
    group: root
    mode: 0644

- name: enable nfs-server
  systemd:
    name: nfs-server
    enabled: yes
    state: started
    daemon_reload: yes

NFS用のディレクトリ配下にPersistentVolume用のディレクトリを /opt/nfs/pv01/opt/nfs/pv10 まで作成しています。

以上でNFSの設定ができたはずなので、試しに作業マシンからマウントして確認してみます。

$ sudo mount 192.168.xx.xx:/opt/nfs/pv001 /mnt/nfs

# マウントできたら読み書きできるか適当に試す

Persistent Volumeの登録

マニュフェストを書いてk8sにPVを登録します。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv01
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  nfs:
    server: 192.168.xx.xx
    path: /opt/nfs/pv01

Persistent Volumeの利用

最終的にはJupyterのストレージとして以下のようにPodを構成しています。
Persistent Volume ClaimでPVを払い出してもらう形になります。

以下では自作のJupyterイメージ中でWORKDIRを /opt に指定しているため、Podの /opt にPVをマウントしています。
これでJupyter上で保存したファイルがNFSに保存されます。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: jupyter-deployment
spec:
  selector:
    matchLabels:
      app: jupyter
  replicas: 1
  template:
    metadata:
      labels:
        app: jupyter
    spec:
      containers:
        - name: jupyter
          image: reireias/jupyterlab:0.0.3
          ports:
            - containerPort: 8080
          volumeMounts:
            - name: opt
              mountPath: /opt
      volumes:
        - name: opt
          persistentVolumeClaim:
            claimName: jupyter-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jupyter-pvc
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 5Gi
  storageClassName: slow
---
apiVersion: v1
kind: Service
metadata:
  name: jupyter-service
spec:
  selector:
    app: jupyter
  ports:
    - port: 80
      targetPort: 8080
  type: LoadBalancer

まとめ

お家k8sクラスターに永続ストレージが増えた!
今までmicroSDの耐久性を気にして保存できなかったデータも保存できるようになった!

参考

9
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
5