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を取り付けましたが、カメラやセンサーなどを取り付けてみるのも面白そうです。以下の続きの記事で実施してみました。