はじめに
構築するシステムのサーバーでIPアドレスベースのフェールオーバー構成を組む場合、いずれかの方法を用いてサーバー間でIPアドレスを引き継がせる必要があります。よくある構成としては以下のようなパターンがあります。(IPアドレスはすべて例です)
- サーバーAにIP-A(192.168.0.1)、サーバーBにIP-B(192.168.0.2)、共有用としてIP-C(192.168.0.3)を割り当て、IP-Cを持っているサーバーが応答し、障害時はIP-Cを切り替えます。
- サーバーAにIP-A(192.168.0.1)、サーバーBにIP-B(192.168.0.2)を割り当て、障害時はIP-Aを引き継ぎます。あまり多くないパターンです。IP-Bは管理用として利用されています。
Linodeにおいても通常は1台のインスタンスにそれぞれIPアドレスが割り当てられますが、LinodeのIP Sharing機能を利用して複数のIPアドレスを割り当てて、そのIPを共有することで、フェールオーバー構成を組むことが可能です。
なお、冗長構成及び負荷分散を実現する方法として、LinodeのマネージドロードバランサーであるNodeBalancersを用いる方法もあります。本記事でのIPアドレス方式でのフェールオーバー構成は、Linodeインスタンスにてロードバランサーを構築する場合や、何らかの理由でクライアントと直接通信を行う必要があるときなどに用いられます。
フェールオーバーの方式
IP Sharingの概要についてはLinodeのドキュメントに記載されています。
注意点としては、フェールオーバーメソッドや利用するソフトウェアがデータセンターにより違いがあり、Linodeインスタンスが配置されるデータセンターに併せて構成する必要があります。寄稿時に東京リージョンでサポートしているフェールオーバーメソッドはARPベースでのKeepAlived方式です。(最新情報は以下URLにて確認してください)
主にインターネット用のルーティングプロトコルのBGPや、聞きなれないlelastic、FRRなどの文言が出てきましたが心配ありません。Linode環境にて手順化されているため、ドキュメントを見ながら設定を行うだけでフェールオーバー構成が実現できます。
グローバルIPアドレスであるPublic IPをフェールオーバー構成とする場合は、2つ目のIPアドレスを1台のインスタンスに追加する必要があります。グローバルIPアドレスの追加はIPv4アドレス枯渇の観点からLinodeカスタマーサポートへ申請が必要ですので、手順の理解についてはこの記事が役に立てば幸いです。
事前準備
同じリージョンにてLinodeインスタンスを2台作成します。今回は対応しているフェールオーバー方式に併せて作成しました
ディストリビューションは「Ubuntu 22.04 LTS」を選択していますので、その他のディストリビューションを用いる場合はLinodeドキュメントに記載のコマンドを置き換えてください。
まずはApacheをインストールします。sudo用のユーザーは任意のユーザー名で作成してください。
# adduser -a user01
# gpasswd -a user01 sudo
ユーザーにて再ログインし、以後はsudoで実行します。
$ sudo apt update
$ sudo apt install apache2 -y
$ sudo vi /var/www/html/server.html
サーバーAに接続されていることがわかるように、シンプルなHTMLファイルを作成します。
<html><head></head><body><h1>
Server-A
</h1></body></html>
サーバーBも同様に作成します。
<html><head></head><body><h1>
Server-B
</h1></body></html>
両方のサーバーでWebサーバーを起動します。
$ sudo systemctl start apache2
$ sudo systemctl enable apache2
サーバーAのグローバルIPにアクセスすると、「サーバーA」が表示されます。
http://[LinodeのグローバルIP]/server.html
ARPベースでのKeepAlived方式
東京リージョン等でサポートしている方式です。ここで紹介する手順は以下のURLをベースにしていますが、コンフィグファイルに多少の変更を加えています。
Public IPアドレスの追加
Linodeインスタンスのネットワーク設定より、サーバーAに対して、IPアドレスの追加を行います。なお追加の課金(2023/4現在、IP毎に月$2)が発生します。
PublicであるグローバルIPアドレスを追加する場合は、カスタマーサポートへ申請が必要です。申請をしていない場合は以下のメッセージが表示され追加できません。
今回はグローバルIPアドレスを冗長化するため、Publicを選択し「Allocate」をクリックします。
2つめの「IPv4 - Public」が割り当てられました。
IP Sharingの設定
先ほど割り当てたPublic IPに対して、IP Sharingの設定を行います。
サーバーBのネットワーク設定にて「IP Sharing」をクリックします。
先ほど割り当てたサーバーAの2つめのPublic IPを選択し、「Save」をクリックします。
サーバーAの共有IPが「IPv4 - Shared」として割り当てられました。
keepalivedのインストールと設定
両方のサーバーにkeepalivedをインストールします。
$ sudo apt update && sudo apt upgrade
$ sudo apt install keepalived
$ sudo vi /etc/keepalived/keepalived.conf
サーバーAにてkeepalived.confを以下のように作成します。
global_defs {
}
vrrp_script check_apache2 {
script "/etc/keepalived/apache2-check.sh"
interval 2
fall 2
rise 2
}
vrrp_instance Instance1 {
state MASTER
interface eth0
virtual_router_id 10
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass fowebpass #fowebpassは例。共通のパスワードを記載
}
unicast_src_ip 198.51.100.1 #左記は例。サーバーAの1つ目のPublic IPを記載
unicast_peer {
198.51.100.2 #左記は例。サーバーBのPublic IPを記載
}
virtual_ipaddress {
198.51.100.3 #左記は例。IP Sharingで割り当てたIPを記載
}
track_script {
check_apache2
}
}
サーバーBにも同じようにkeepalived.confを以下のように作成します。
global_defs {
}
vrrp_script check_apache2 {
script "/etc/keepalived/apache2-check.sh"
interval 2
fall 2
rise 2
}
vrrp_instance Instance1 {
state BACKUP # サーバーBはBACKUPに変更
interface eth0
virtual_router_id 10
priority 99 # サーバーBは99に変更
advert_int 1
authentication {
auth_type PASS
auth_pass fowebpass #fowebpassは例。共通のパスワードを記載
}
unicast_src_ip 198.51.100.2 #左記は例。サーバーBのPublic IPを記載
unicast_peer {
198.51.100.1 #左記は例。サーバーAの1つ目のPublic IPを記載
}
virtual_ipaddress {
198.51.100.3 #左記は例。IP Sharingで割り当てたIPを記載
}
track_script {
check_apache2
}
}
両方のサーバーにapache2のプロセス正常性を確認するための簡単なスクリプトを追加します。
$ sudo vi /etc/keepalived/apache2-check.sh
#!/bin/bash
systemctl is-active apache2
スクリプトの権限を変更し、keepalivedを起動します。
$ sudo chmod 744 /etc/keepalived/apache2-check.sh
$ sudo systemctl enable keepalived
$ sudo systemctl start keepalived
状態確認を行います。
サーバーAでのログは以下の通りです。マルチマスターにならないように一旦BACKUP STATEで起動し、すぐにMASTER STATEに選出されていることがわかります。
$ sudo tail -20 /var/log/syslog | grep Keepalive
Mar 27 01:26:09 localhost systemd[1]: Started Keepalive Daemon (LVS and VRRP).
Mar 27 01:26:09 localhost Keepalived_vrrp[10352]: VRRP_Script(check_apache2) succeeded
Mar 27 01:26:09 localhost Keepalived_vrrp[10352]: (Instance1) Entering BACKUP STATE
Mar 27 01:26:12 localhost Keepalived_vrrp[10352]: (Instance1) Entering MASTER STATE
eth0に共有IPが適用されています。
$ sudo ip addr
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
inet サーバーAのIP/24 brd BROADCAST scope global eth0
valid_lft forever preferred_lft forever
inet 共有IP/32 scope global eth0
valid_lft forever preferred_lft forever
サーバーBでのログは以下の通りです。BACKUP STATEになっていることがわかります。
$ sudo tail -20 /var/log/syslog | grep Keepalive
Mar 27 01:26:13 localhost systemd[1]: Started Keepalive Daemon (LVS and VRRP).
Mar 27 01:26:13 localhost Keepalived[48819]: Startup complete
Mar 27 01:26:13 localhost Keepalived_vrrp[48820]: VRRP_Script(check_apache2) succeeded
Mar 27 01:26:13 localhost Keepalived_vrrp[48820]: (Instance1) Entering BACKUP STATE
共有IPは適用されていません。
$ sudo ip addr
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
inet サーバーBのIP/24 brd BROADCAST scope global eth0
valid_lft forever preferred_lft forever
パソコンのブラウザから共有IPにアクセスすると、サーバーAが応答します。
サーバーの切り替え
切り替えを行います。ここではapacheを停止します。
$ sudo systemctl stop apache2
パソコンのブラウザから共有IPにアクセスすると、サーバーBが応答します。
同時にパソコンからpingにてサーバーの切り替えを確認した結果です。
> ping 共有IP -t
共有IP からの応答: バイト数 =32 時間 =30ms TTL=49
共有IP からの応答: バイト数 =32 時間 =31ms TTL=49
要求がタイムアウトしました。 # ここで切り替わっています。
共有IP からの応答: バイト数 =32 時間 =29ms TTL=49
共有IP からの応答: バイト数 =32 時間 =32ms TTL=49
状態確認を行います。
サーバーAでのログは以下の通りです。FAULT STATEになっていることがわかります。
$ sudo tail -20 /var/log/syslog | grep Keepalive
root@localhost:~# tail -50 /var/log/syslog | grep Keepalive
Mar 27 02:02:21 localhost Keepalived_vrrp[10352]: Script `check_apache2` now returning 3
Mar 27 02:02:23 localhost Keepalived_vrrp[10352]: VRRP_Script(check_apache2) failed (exited with status 3)
Mar 27 02:02:23 localhost Keepalived_vrrp[10352]: (Instance1) Entering FAULT STATE
共有IPは適用されていません。
$ sudo ip addr
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
inet サーバーAのIP/24 brd BROADCAST scope global eth0
valid_lft forever preferred_lft forever
サーバーBでのログは以下の通りです。MATER STATEに切り替わっていることがわかります。
$ sudo tail -20 /var/log/syslog | grep Keepalive
Mar 27 01:35:07 localhost Keepalived_vrrp[48820]: (Instance1) Entering BACKUP STATE
Mar 27 02:02:24 localhost Keepalived_vrrp[48820]: (Instance1) Entering MASTER STATE
サーバーBのeth0に対して共有IPが適用されています。
$ sudo ip addr
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
inet サーバーBのIP/24 brd BROADCAST scope global eth0
valid_lft forever preferred_lft forever
inet 共有IP/32 scope global eth0
valid_lft forever preferred_lft forever
サーバーAのapacheが再度立ち上がるとフェールバックされて、サーバーAが応答します。
BGPベースでのlelastic方式
シンガポールリージョンなどでサポートしているlelasticによる方式を記載します。
ドキュメントでは以下URLにて記載されています。
apacheのインストールなど基本的なサーバーの準備は「事前準備」と同じですが、リージョンはシンガポールを選択しています。
Public IPアドレスの追加及び、IP Sharingの設定
こちらもkeepalivedの場合と同様に、Public IPの追加及びIP Sharingの設定を行います。
共有IPをLinuxのネットワーク構成に追加
両方のサーバーのloインターフェースに共有IPを適用します。
$ sudo vi /etc/netplan/01-netcfg.yaml
network:
version: 2
renderer: networkd
ethernets:
eth0:
dhcp4: yes
lo: #ここから追加
match:
name: lo
addresses:
- 共有IP/32 #/32を指定してください。
設定を適用します。loインターフェースに共有IPが割り当たっていることが確認できます。
$ sudo netplan apply
$ ip addr
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 共有IP/32 scope global lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
inet 一つ目のPublic IP/24 brd BROADCAST scope global eth0
valid_lft forever preferred_lft forever
inet 共有IP/24 brd BROADCAST scope global eth0
lelasticのインストールと設定
両方のサーバーにlelasticをインストールします。以下のURLにてversionを確認し、次のコマンドの引数に適用してください。
https://github.com/linode/lelastic/releases
確認したversionに書き換えてインストールを行います。
version=v0.0.6
curl -LO https://github.com/linode/lelastic/releases/download/$version/lelastic.gz
gunzip lelastic.gz
chmod 755 lelastic
sudo mv lelastic /usr/local/bin/
起動スクリプトを作成します。
-
[id]はフェールオーバー方式一覧からリージョンのIDを取得して適用します。
https://www.linode.com/docs/products/compute/compute-instances/guides/failover/#ip-sharing-availability -
[role]は、サーバーAはprimary、サーバーBはsecondaryを選択します。
[id]、[role]を修正して作成します。
両方のサーバーで設定内容は同じです。
$ sudo vi /etc/systemd/system/lelastic.service
[Unit]
Description= Lelastic
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/bin/lelastic -dcid [id] -[role] &
ExecReload=/bin/kill -s HUP $MAINPID
[Install]
WantedBy=multi-user.target
lelasticを起動します。
$ sudo chmod 644 /etc/systemd/system/lelastic.service
$ sudo systemctl start lelastic
$ sudo systemctl enable lelastic
パソコンのブラウザから共有IPにアクセスすると、サーバーAが応答します。
サーバーの切り替え
切り替えを行います。ここではサーバーAを停止します。
$ sudo shutdown -h now
パソコンのブラウザから共有IPにアクセスすると、サーバーBが応答します。
同時にパソコンからpingにてサーバーの切り替えを確認した結果です。
> ping 共有IP -t
共有IP からの応答: バイト数 =32 時間 =210ms TTL=44
共有IP からの応答: バイト数 =32 時間 =203ms TTL=44
要求がタイムアウトしました。 # ここで切り替わっています。
共有IP からの応答: バイト数 =32 時間 =204ms TTL=44
共有IP からの応答: バイト数 =32 時間 =209ms TTL=44
サーバーAのOSが再度立ち上がるとフェールバックされて、サーバーAが応答します。
まとめ
LinodeでIPアドレスベースのフェールオーバー構成を実現する方法を紹介しました。NodeBalancersを用いないIPアドレスベースのサーバー冗長化を行う際に、公式のドキュメントと併せてぜひ参考にしてください。