VRRP(Virtual Router Redundancy Protocol)は、サーバやルータなどを冗長化するプロトコルで、複数台のサーバに同じIPアドレス(仮想IP:VIP)を割り当てて、一つのサーバとして扱うことができます。
KeeppalivedのVRRP機能を利用して、Webサーバがダウンしたときに、バックアップサーバに切り替えるテストをしてみました。
参考)
「Ubuntu 20.04 で Keepalived を同一筐体で用いて冗長構成/負荷分散する」
https://weseek.co.jp/tech/2989/
参考にさせていただいたサイトでは、マスターもバックアップも同じ設定ファイルで書かれており、状態によって切り替える工夫がされています。
環境) Ubuntu 22.04 x 2 / VirtualBox
インストール
sudo apt-get install keepalived
設定ファイル編集
sudo vi /etc/keepalived/keepalived.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
global_defs { enable_script_security } vrrp_instance LVS_SETTINGS { state BACKUP interface enp0s3 # ifconfigコマンドで確認 virtual_router_id 50 # VRRP Group ID priority 100 advert_int 1 # 生存確認パケットの間隔 notify_master "/etc/keepalived/notify_master.sh" notify_backup "/etc/keepalived/notify_backup.sh" virtual_ipaddress { 192.168.1.11 } } include virtualserver-backup.conf |
sudo vi /etc/keepalived/virtualserver-backup.conf
#
空ファイル
sudo vi /etc/keepalived/virtualserver-master.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
virtual_server 192.168.1.11 8000 { #VIP delay_loop 6 # アプリの生存確認間隔 lb_algo rr # 負荷分散手法 lb_kind DR # パケット転送方式 protocol TCP # 対象プロトコル real_server 192.168.1.124 8000 { weight 1 # 負荷分散で使う重み HTTP_GET { # 生存確認のプロトコル url { path /health } connect_timeout 10 } } real_server 192.168.1.168 8000 { weight 1 HTTP_GET { url { path /health } connect_timeout 10 } } } |
sudo vi /etc/keepalived/notify_master.sh
1 2 3 |
#!/bin/bash -u sudo sed -i -e "s/include virtualserver-backup.conf/include virtualserver-master.conf/g" /etc/keepalived/keepalived.conf sudo service keepalived reload |
sudo vi /etc/keepalived/notify_backup.sh
1 2 3 4 5 6 7 8 9 10 11 12 |
#!/bin/bash -u RELOAD_FLG=0 grep "include virtualserver-backup.conf" /etc/keepalived/keepalived.conf > /dev/null # Normally the exit status is 0 if a line is selected, 1 if no lines were selected, and 2 if an error occurred. see: man grep if [ $? -ne 0 ] ; then RELOAD_FLG=1 fi sudo sed -i -e "s/include virtualserver-master.conf/include virtualserver-backup.conf/g" /etc/keepalived/keepalived.conf # reload のタイミングで BACKUP state に移行して再度このスクリプトが実行されるため、無限実行を防ぐためにチェックを行う if [ ${RELOAD_FLG} -eq 1 ] ; then sudo service keepalived reload fi |
スクリプト実行ユーザ追加
sudo useradd keepalived_script
sudo visudo
….下記追記
keepalived_script ALL=(ALL:ALL) NOPASSWD: ALL
パーミッションの変更
cd /etc/keepalived
sudo chmod u+x notify_backup.sh notify_master.sh
sudo chown keepalived_script:keepalived_script notify_backup.sh notify_master.sh
IPフォワード設定
sudo vi /etc/sysctl.d/98-keepalived.conf
1 2 3 4 5 6 7 8 9 10 11 12 |
# パケットを転送するために IP フォーワードを許可 net.ipv4.ip_forward = 1 # ARP リクエストが eth0 に来たときに eth0 に vip が設定されていなかったとしても、 # lo に vip が設定されていると ARP レスポンスを返してしまうため、 # それを防ぐために eth0 に設定されていないアドレスに対する ARP リクエストには応答しないようにしている # see: https://www.valinux.co.jp/technologylibrary/document/linux/arp0001/ net.ipv4.conf.eth0.arp_ignore = 1 net.ipv4.conf.eth0.arp_announce = 2 # LVS 間での通信とクライアントとの通信で異なる NIC を使用する場合は rp_filter を無効化(0)に # net.ipv4.conf.eth0.rp_filter = 0 |
設定更新
sudo sysctl -p
loにvip割り当て
sudo vi /etc/netplan/99_lo_config.yaml
1 2 3 4 5 6 7 |
network: version: 2 renderer: networkd ethernets: lo: addresses: - 192.168.1.11/32 |
設定更新
sudo netplan apply
確認
ip a show lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet 192.168.1.11/32 scope global lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
再起動
sudo service keepalived status
sudo service keepalived restart
Webアプリ
index.htmlにサーバを識別できる名前を入れておく。(場所は任意。サーバ起動まで同じ場所)
生存確認用にファイル作成
touch health
サーバ起動
python3 -m http.server 8000
確認
sudo journalctl -u keepalived
設定うまくいっていれば、ログが表示されます。
WebClientは、WSLのコンソールからCurlコマンドで確認しました。
最初は、リアルサーバのIPにアクセス、次にバーチャルIPにアクセスし、ラウンドロビンでアクセスできるていることを確認後、n0cのサーバをダウンさせました。
一回は失敗しましたが、その後はn0dの方に切り替わっています。
実際に動かしてみると、理解が深まります。
まずは簡単なWebサーバでしたが、この環境を他のサーバでも使おうと思います。