Linuxサーバ上でのKeepalivedを活用した高可用性サービスの展開
こんにちは。技術部のPです。
高可用性(High Availability, HA)とは、サービスやシステムが常に稼働し、ユーザに対して中断なくサービスを提供できることを指します。今日のIT業界では、複数のプロバイダが同様のサービスを提供しているため、競争力を維持するためには、サービスの質だけでなく、ダウンタイムを最小限に抑え、常に利用可能な状態を保つことが重要です。
本記事では、Linuxサーバ上での高可用性を実現するための「Keepalived」の導入と設定について紹介します。
概要
- Keepalivedとは
- Keepalivedの導入と設定
- 動作確認
Keepalivedとは?
Keepalivedは、Linuxシステム向けに開発されたソフトウェアで、ロードバランシング(Load Balancing)と高可用性(High Availability)を提供するために使用されます。初版は2000年12月にリリースされ、現在も進化を続けています。
Keepalivedは、複数のサーバに対して仮想IPアドレス(VIP)を提供し、主サーバがダウンした場合に自動でバックアップサーバに切り替えることができます。
公式サイト:Keepalived
下記のシステム構成をご参考ください。
本構成では、db01 と db02 の2つのDBサーバが構成されています。初期設定では db01 がマスターとしてVirtual IP (VIP)を保持し、必要に応じてバックアップサーバ db02 にフェイルオーバーします。
- db01 (MASTER)
- Host name: db01
- Private IP: 192.168.0.31
- Virtual IP: 192.168.0.40
- OS: AlmaLinux
- Keepalived: 使用
- db02 (BACKUP)
- Host name: db02
- Private IP: 192.168.0.32
- OS: AlmaLinux
- Keepalived: 使用
- web01 (Web server)
- Host name: web01
- Private IP: 192.168.0.1
- OS: AlmaLinux
- Apache: 使用
Keepalivedの機能や動作を理解しやすくするために、次は導入と設定の部分を進めていきます。
Keepalivedの導入と設定
インストール手順
以下のコマンドでKeepalivedをインストールします。
# dnf install keepalived
# rpm -qa | grep keepalived
設定ファイルの編集
バックアップ用に元の設定ファイルをコピーし、必要な設定を行います。
■db01
# cp -p /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.org
# vi /etc/keepalived/keepalived.conf# cat /etc/keepalived/keepalived.conf
—————————————————————————————–
! Configuration File for keepalived
global_defs {
enable_script_security
}
vrrp_script mysqlchk {
script “/etc/keepalived/mysqlchk.sh”
interval 5
weight 2
fall 4
rise 2
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 100
advert_int 1
virtual_ipaddress {
192.168.0.40 dev eth0 label eth0:0 #VIP
}
unicast_src_ip 192.168.0.31
unicast_peer {
192.168.0.32
}
track_script {
mysqlchk
}
}
■db02
#cat /etc/keepalived/keepalived.conf
—————————————————————————————–
! Configuration File for keepalived
global_defs {
enable_script_security
}
vrrp_script mysqlchk {
script “/etc/keepalived/mysqlchk.sh”
interval 5
weight 2
fall 4
rise 2
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 100
advert_int 1
virtual_ipaddress {
192.168.0.40 dev eth0 label eth0:0 #VIP
}
unicast_src_ip 192.168.0.32
unicast_peer {
192.168.0.31
}
track_script {
mysqlchk
}
}
解説:
上記の設定では、最初にDBサーバ db01 が MASTER として起動され、インターフェース eth0 に割り当てられた Virtual IP (VIP) である 192.168.0.40 を保持します。また、db01 上の優先度(priority)が102になります。DBサーバ db02 が後で起動されるので、BACKUPとなり、優先度も102になります。
track_script を使用して、MySQLサービスの状態を監視するヘルスチェックスクリプトを実行します。
何らかの理由でMySQLが動作しなくなった場合、Keepalived は db01 上の優先度を 102-2=100 に減算します。この時点で、db01の優先度は100となり、最初にdb02 の優先度 102 より低くなるため、Keepalivedは db02 の状態を BACKUP から MASTER に切り替え、db02 がVirtual IPを保持するようになります。
■MySQLのヘルスチェックスクリプト
MySQLの状態を監視するためのスクリプトを作成します。
#vi /etc/keepalived/mysqlchk.sh
# cat /etc/keepalived/mysqlchk.sh
—————————————————————————————–
#!/bin/bash
TIMEOUT=60
SOCK=/var/lib/mysql/mysql.sock
sudo mysql -S $SOCK –connect-timeout=$TIMEOUT -e “show variables like ‘server_id’;”
—————————————————————————————–
■ログ設定とKeepalivedの起動
- ログの設定:
keepalivedログを出力するために、/etc/rsyslog.d/keepalived.conf ファイルに以下を追加します。
local7.* /var/log/keepalived/keepalived.log
- システムログの再起動:
# systemctl restart rsyslog.service
- Keepalivedの設定反映:
# systemctl start keepalived.service
動作確認
VIPの確認
■db01
ip a コマンドで仮想IPアドレスが正しく割り当てられているか確認します。
# ip a
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
–省略–
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
–省略–
inet 192.168.0.31/24 brd 192.168.0.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet 192.168.0.40/32 scope global eth0
–省略–
■db02
# ip a
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
–省略–
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
–省略–
inet 192.168.0.32/24 brd 192.168.0.255 scope global noprefixroute eth0
–省略–
VIPでウェブサーバから接続する確認
# mysql -h 192.168.0.40 -u root -p
Enter password:
MariaDB [(none)]> select @@hostname;
+————–+
| @@hostname |
+————–+
| db01 |
+————–+
1 row in set (0.001 sec)
「web01」ウエブサーバから VIP:192.168.0.40 経由で マスター:「db01」 に接続できることを確認できました。
IPが切り替わる動作の確認
・db01停止
# systemctl status mysql
● mariadb.service - MariaDB 10.3 database server
Loaded: loaded (/usr/lib/systemd/system/mariadb.service; enabled; vendor preset: disabled)
Active: active (running) since Fri 2023-12-22 12:16:21 JST; 4h 41min ago
Docs: man:mysqld(8)
https://mariadb.com/kb/en/library/systemd/
Process: 1089 ExecStartPost=/usr/libexec/mysql-check-upgrade (code=exited, status=0/SUCCESS)
Process: 760 ExecStartPre=/usr/libexec/mysql-prepare-db-dir mariadb.service (code=exited, status=0/SUCCESS)
Process: 710 ExecStartPre=/usr/libexec/mysql-check-socket (code=exited, status=0/SUCCESS)
Main PID: 800 (mysqld)
Status: "Taking your SQL requests now..."
Tasks: 39 (limit: 205422)
Memory: 1.3G
CGroup: /system.slice/mariadb.service
mq800 /usr/libexec/mysqld --basedir=/usr
12月 22 12:16:20 db01 systemd[1]: Starting MariaDB 10.3 database server...
12月 22 12:16:20 db01 mysql-prepare-db-dir[760]: Database MariaDB is probably initialized in /var/lib/mysql already, nothing is done.
12月 22 12:16:20 db01 mysql-prepare-db-dir[760]: If this is not the case, make sure the /var/lib/mysql is empty before running mysql-prepare-db-dir.
12月 22 12:16:21 db01 systemd[1]: Started MariaDB 10.3 database server.
# systemctl stop mysql
#
・ログを確認
# tail -f /var/log/keepalived/keepalived.log
Dec 22 12:21:53 db01 Keepalived_vrrp[903]: Sending gratuitous ARP on eth0 for 192.168.0.40
Dec 22 12:21:53 db01 Keepalived_vrrp[903]: Sending gratuitous ARP on eth0 for 192.168.0.40
Dec 22 12:21:53 db01 Keepalived_vrrp[903]: Sending gratuitous ARP on eth0 for 192.168.0.40
Dec 22 12:21:53 db01 Keepalived_vrrp[903]: Sending gratuitous ARP on eth0 for 192.168.0.40
Dec 22 16:58:16 db01 Keepalived_vrrp[903]: Script `mysqlchk` now returning 1
Dec 22 16:58:31 db01 Keepalived_vrrp[903]: VRRP_Script(mysqlchk) failed (exited with status 1)
Dec 22 16:58:31 db01 Keepalived_vrrp[903]: (VI_1) Changing effective priority from 102 to 100
Dec 22 16:58:34 db01 Keepalived_vrrp[903]: (VI_1) Master received advert from 192.168.0.32 with higher priority 102, ours 100
Dec 22 16:58:34 db01 Keepalived_vrrp[903]: (VI_1) Entering BACKUP STATE
Dec 22 16:58:34 db01 Keepalived_vrrp[903]: (VI_1) removing VIPs.
ログを見ると、先ずはdb01の優先度が102から100となり、最初にdb02(192.168.0.32)の優先度が102なので、MASTERになります。その後、db01がBACKUPになってVIPもdb01から削除され、db02に切り替わっています。
・db02での確認
#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
--省略--
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
--省略--
inet 192.168.0.32/24 brd 192.168.0.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet 192.168.0.40/32 scope global eth0:0
--省略--
今、MASTERとしてdb02がVIP(192.168.0.40)持っています。
・db01が復旧の場合
# systemctl start mysql
# tail -f /var/log/keepalived/keepalived.log
Dec 22 12:21:53 db01 Keepalived_vrrp[903]: Sending gratuitous ARP on eth0 for 192.168.0.40
Dec 22 16:58:16 db01 Keepalived_vrrp[903]: Script `mysqlchk` now returning 1
Dec 22 16:58:31 db01 Keepalived_vrrp[903]: VRRP_Script(mysqlchk) failed (exited with status 1)
Dec 22 16:58:31 db01 Keepalived_vrrp[903]: (VI_1) Changing effective priority from 102 to 100
Dec 22 16:58:34 db01 Keepalived_vrrp[903]: (VI_1) Master received advert from 192.168.0.32 with higher priority 102, ours 100
Dec 22 16:58:34 db01 Keepalived_vrrp[903]: (VI_1) Entering BACKUP STATE
Dec 22 16:58:34 db01 Keepalived_vrrp[903]: (VI_1) removing VIPs.
Dec 22 17:00:31 db01 Keepalived_vrrp[903]: Script `mysqlchk` now returning 0
Dec 22 17:00:36 db01 Keepalived_vrrp[903]: VRRP_Script(mysqlchk) succeeded
Dec 22 17:00:36 db01 Keepalived_vrrp[903]: (VI_1) Changing effective priority from 100 to 102
db01が復旧の場合、優先度が100から102になります。
まとめ
Keepalived を使用することで、Linux環境において高可用性とフェイルオーバーの仕組みを簡単に構築できます。これにより、サービスの中断を最小限に抑え、ユーザ体験を向上させることができます。