はじめに
このエントリでは、Raspberry Pi 5を使ってk3sクラスターを構築し、永続ストレージを設定する方法を紹介します。外付けSSDを活用し、Kubernetesの永続ボリューム(PV)と永続ボリュームクレーム(PVC)を使ってデータを安全に保存する環境を構築していきます。さらに、その環境上でFlaskアプリケーションをデプロイする手順も詳しく解説します。Raspberry Piを活用したホームサーバーや学習用プロジェクトに興味がある方に、ぜひ試していただきたい内容です。
前提条件
- 2台のRaspberry Pi 5(Rpi1とRpi2)
- 両方にUbuntu 24.04がインストール済み
- Rpi1をマスターノード、Rpi2をワーカーノードとしてk3sでクラスタを構築済み
- Rpi1の/mnt/my_ssd/に外付けSSDをマウント済み
- k3sの永続化領域として/mnt/my_ssd/k3s_storageを作成済み
1. 永続ボリューム(PV)と永続ボリュームクレーム(PVC)の作成
aspberry Pi 5でk3sクラスターを構築し、ファイルの永続化領域を作成するには、Kubernetesの永続ボリューム(PV)と永続ボリュームクレーム(PVC)を使用します。
1-1. 永続ボリューム(PV)の定義ファイルの作成(例:pv.yaml)
```yml
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /mnt/my_ssd/k3s_storage
storageClassName: manual
```
1-2. 永続ボリュームクレーム(PVC)の定義ファイルの作成(例:pvc.yaml)
```yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
storageClassName: manual
```
1-3. リソースの適用
```sh
kubectl apply -f pv.yaml
kubectl apply -f pvc.yaml
```
1-4. Podでの使用
永続ボリュームクレームを使用するPodの定義ファイルを作成します。以下は、PVCをマウントしてファイルを保存するPodの例です。
```yml
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: my-storage
volumes:
- name: my-storage
persistentVolumeClaim:
claimName: my-pvc
```
1-5. Podの適用
```sh
kubectl apply -f pod.yaml
```
これで、Podが/mnt/my_ssd/k3s_storageに保存されたファイルにアクセスできるようになります。データは永続ボリュームに保存され、Podが削除されても保持されます。
2. 永続ボリュームにファイルを作成する
2-1. Flask アプリケーションのセットアップ
以下のPythonコードをapp.pyという名前で保存します。
from flask import Flask, request, redirect, url_for, send_from_directory
import os
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = '/usr/share/nginx/html/uploads'
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 最大アップロードサイズ16MB
# アップロードフォルダが存在しない場合は作成
if not os.path.exists(app.config['UPLOAD_FOLDER']):
os.makedirs(app.config['UPLOAD_FOLDER'])
@app.route('/')
def index():
return '''
<!doctype html>
<title>File Upload</title>
<h1>Upload a File</h1>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="Upload">
</form>
'''
@app.route('/upload', methods=['POST'])
def upload_file():
if 'file' not in request.files:
return redirect(request.url)
file = request.files['file']
if file.filename == '':
return redirect(request.url)
if file:
filename = file.filename
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return redirect(url_for('uploaded_file',
filename=filename))
@app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'],
filename)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
2-1. Dockerfileの作成
Flaskアプリケーションをコンテナで動かすためのDockerfileを作成します。
# Python 3.11をベースにする
FROM python:3.11-slim
# 必要なパッケージをインストール
RUN pip install flask
# アプリケーションコードをコンテナにコピー
COPY app.py /app/app.py
# 作業ディレクトリを設定
WORKDIR /app
# Flaskアプリケーションを実行
CMD ["python", "app.py"]
2-3. Kubernetes Deploymentの設定
FlaskアプリケーションをデプロイするためのKubernetes Deploymentの設定ファイル (flask-deployment.yaml) を作成します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: flask-deployment
spec:
replicas: 1
selector:
matchLabels:
app: flask
template:
metadata:
labels:
app: flask
spec:
containers:
- name: flask-container
image: <your_docker_image> # デプロイするDockerイメージを指定
ports:
- containerPort: 5000
volumeMounts:
- name: flask-storage
mountPath: /usr/share/nginx/html/uploads
volumes:
- name: flask-storage
persistentVolumeClaim:
claimName: my-pvc
2-4. Serviceの設定
FlaskアプリケーションにアクセスするためのServiceの設定ファイル (flask-service.yaml) を作成します。
apiVersion: v1
kind: Service
metadata:
name: flask-service
spec:
selector:
app: flask
ports:
- protocol: TCP
port: 80
targetPort: 5000
type: LoadBalancer
2-5. Kubernetesリソースの適用
以下のコマンドで、DeploymentとServiceをKubernetesに適用します。
kubectl apply -f flask-deployment.yaml
kubectl apply -f flask-service.yaml
2-6. 動作確認
ブラウザでサービスのIPアドレスにアクセスし、ファイルをアップロードして保存されることを確認します。ファイルは永続ボリュームに保存され、Podの再起動や再作成後も保持されます。
おわりに
Raspberry Pi 5とk3sを組み合わせることで、低コストながらも強力なクラウドネイティブ環境を構築できることを実感していただけたと思います。今回の手順を応用すれば、さらに多くのアプリケーションをデプロイしたり、クラスタリングを活用したスケーラビリティの向上も可能です。