SCSK 岩井です。
今回はRaspberry Piを2台使ってWebサーバの冗長化を行ってみたいと思います。
ただWebサーバを冗長化するだけではなく、WebサイトとLED点灯/消灯を連動させてみたいと思います。
ちょっとだけそれっぽくなる予定です。
下準備
使用するRaspberry Piは以下のものです。
【Raspberry Pi 5】
CPU: Broadcom BCM2712 quad-core Arm Cortex A76 processor @ 2.4GHz
Memory: 8GB
OS: Bookworm
【Raspberry Pi 3 Model B+】
CPU: Broadcom BCM2837B0, Cortex-A53 (ARMv8) 64-bit SoC @ 1.4GHz
Memory: 1GB
OS: Bookworm
この2台にflask(簡易的なWebアプリフレームワーク)をインストールしてWeb経由操作でLED点灯/消灯する構成を組んでみます。
【追加で用意するもの】
LED(赤)×1
LED(黄)×1
抵抗(330Ω)×2
ジャンパーケーブル×4
ブレッドボード×1
Webサーバアクセス用PC
ライブラリのインストール
ラズパイに必要なライブラリ(Flask、GPIO(Rasberry Pi 3)、gpiozero(Rasberry Pi 5))をインストールします。
Raspberry Pi 5はGPIOが使えなくなってしまったので代わりにgpiozeroをインストールします。
# Raspberry Pi 5の場合
sudo apt update
sudo apt install python3-flask
sudo apt install gpiozero
# Raspberry Pi 3の場合
sudo apt update
sudo apt install python3-flask
sudo apt install python3-rpi.gpio
Pythonスクリプトの作成
PythonでFlaskアプリケーションを作成します。
ファイル名はapp.pyにしてみました。
Web画面上にLED点灯用とLED消灯用のリンクを張って、LEDを着けたり消したりできるようにします。
まずはviを起動します。
# Raspberry Pi 3/Raspberry Pi 5共通
sudo vi app.py
以下のコードを記述してファイルを保存します。Raspberry Pi 5はgpiozeroライブラリ、Raspberry Pi 3は
GPIOライブラリなのでコードが異なります。同じ画面を作成していますが、Raspberry Pi 5はWebアクセスされると「Unit 1」、
Raspberry Pi 3はWebアクセスされると「Unit 2」と表示されるようにしています。
# Raspberry Pi 5の場合
from flask import Flask
from gpiozero import LED
app = Flask(__name__)
# GPIO 17を制御するLEDオブジェクトの作成
led = LED(17)
@app.route('/')
def index():
return '''
<h1>LED Control(Unit 1)</h1>
<p><a href="/led/on">Turn LED ON</a></p>
<p><a href="/led/off">Turn LED OFF</a></p>
'''
@app.route('/led/on')
def led_on():
led.on() # LEDを点灯
return '<h1>LED is ON</h1><p><a href="/">Back to home</a></p>'
@app.route('/led/off')
def led_off():
led.off() # LEDを消灯
return '<h1>LED is OFF</h1><p><a href="/">Back to home</a></p>'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
# Raspberry Pi 3の場合
from flask import Flask
import RPi.GPIO as GPIO
app = Flask(__name__)
# GPIOピンの設定
LED_PIN = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(LED_PIN, GPIO.OUT)
@app.route('/')
def index():
return '''
<h1>LED Control(Unit 2)</h1>
<p><a href="/led/on">Turn LED ON</a></p>
<p><a href="/led/off">Turn LED OFF</a></p>
'''
@app.route('/led/on')
def led_on():
GPIO.output(LED_PIN, GPIO.HIGH)
return '<h1>LED is ON</h1><p><a href="/">Back to Home</a></p>'
@app.route('/led/off')
def led_off():
GPIO.output(LED_PIN, GPIO.LOW)
return '<h1>LED is OFF</h1><p><a href="/">Back to Home</a></p>'
if __name__ == '__main__':
try:
app.run(host='0.0.0.0', port=5000)
finally:
GPIO.cleanup()
LEDとRaspberry Piを接続する
ブレッドボードにLEDと抵抗を接続します。
Raspberry Pi 5用とRaspberry Pi 3用に2セット回路を作ります。
イメージはこんなカンジで。(左側がRaspberry Pi 3用、右側がRaspberry Pi 5用)
次に回路とRaspberry Pi 5、Raspberry Pi 3を接続します。
なお、コードの中にあったGPIO 17は17ピンではなく、11ピンのGPIO17 です。
17ピンに刺すと3.3vの電圧がかかりっぱなしになるので、
ただLEDが光ってるだけの状態になります。(Webアプリと連動しません)
10分悩みました。
11ピンのGPIO17に+側(LED側のケーブル)、14ピンのGroundに-側(抵抗側のケーブル)を接続します。
【Raspberry Pi 5のピン配置】
Raspberry Pi 5 Pinouts including GPIO for the 40 Pin Header – element14 Community
【Raspberry Pi 3のピン配置】
Raspberry Pi 3 Model B GPIO 40 Pin Block Pinout – element14 Community
Webサーバの起動(Pythonスクリプトの実行)
各Raspberry Piのコンソールで、Webサーバを起動します。
まずはIPアドレス確認から。
# Raspberry Pi 5/Raspberry Pi 3共通
ip addr
次に各Raspberry PiでWebサーバを起動します。
# Raspberry Pi 5/Raspberry Pi 3共通
python3 app.py
WebブラウザからアクセスとLED操作
Webサイトアクセス用PCでブラウザを2つ起動し、それぞれ以下のURLにアクセスします。
http://Raspberry Pi 5のIPアドレス:5000 |
http://Raspberry Pi 3のIPアドレス:5000 |
次にブラウザ上の「Turn LED ON」のリンクをクリックします。
LED点灯。やりました。
「Back to Home」のリンクをクリックして前の画面に戻ります。
今度は「Turn LED OFF」のリンクをクリックします。
LED消灯。(写真撮り忘れました)
nginxのインストールとプロキシ設定
nginxを使用してFlaskアプリへのリクエストをプロキシできるようにするため、各Raspberry Piにnginxをインストールします。
# Raspberry Pi 5/Raspberry Pi 3共通
sudo apt install nginx
プロキシを有効化するため、nginxの設定を変更します。
# Raspberry Pi 5/Raspberry Pi 3共通
sudo vi /etc/nginx/sites-available/default
設定内容は以下のとおり。
# Raspberry Pi 5/Raspberry Pi 3共通
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Keepalivedのインストールと設定
keepalivedインストールしてWebサイト(Flaskアプリ)の冗長化構成を組んでみます。
各Raspberry Piにkeepalivedをインストールします。
# Raspberry Pi 5/Raspberry Pi 3共通
sudo apt update
sudo apt install keepalived
次に各Raspberry Piでkeepalivedの設定ファイルを編集します。
# Raspberry Pi 5/Raspberry Pi 3共通
sudo vi /etc/keepalived/keepalived.conf
Raspberry Pi 5をMaster、Raspberry Pi 3をBackupとします。
仮想IPアドレス(virtual_ipaddress)は192.168.11.110、Master側を優先させるため、priorityを100とします。
なお、interfaceは仮想IPアドレスを持たせるネットワークインターフェイスを指定します。
# Raspberry Pi 5(Master)
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass mypass
}
virtual_ipaddress {
192.168.11.110
}
}
Backup側の仮想IPアドレス(virtual_ipaddress)はMaster側と同様の192.168.11.110、priorityを90とします。
# Raspberry Pi 3(Backup)
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass mypass
}
virtual_ipaddress {
192.168.11.110
}
}
各Raspberry Piでkeepalivedを再起動します。
# Raspberry Pi 5/Raspberry Pi 3共通
sudo systemctl restart keepalived
動作確認
Webサイトアクセス用PC上のブラウザで仮想IPアドレスのURLにアクセスします。
http://192.168.11.110/ |
Unit 1の表記があり、Master側(Raspberry Pi 5)のWebサイトにアクセスしていることがわかります。
Raspberry Pi 5に接続したLEDの点灯/消灯も問題なくできます。
ここで、Raspberry Pi5をシャットダウンします。
その後上記URLにアクセスするとUnit 2の表記があり、Backup側(Rapberry Pi 3)のWebサイトにアクセスしています。
Raspberry Pi 3に接続したLEDの点灯/消灯も問題なくできます。
これでWebサイトを冗長化することができました。
GPIO側も冗長構成とする必要がありますが、片系に障害が発生してもサービスを継続させることができるようになります。
今回はLEDを取り付けましたが、カメラやセンサーなどを取り付けてみるのも面白そうです。以下の続きの記事で実施してみました。