Redis Server をクラスタ化しないマスター/レプリカ構成の場合、クライアントが常にマスターサーバーに接続できるように HAProxy を手前に配置するパターンがあります。HAProxy が SPOF (Single Point of Failure) になるので、本記事では HAProxy を冗長化するパターンを説明します。
本記事では Private IP を使う例を説明します。VLAN を使うケースは別の記事で説明予定です。
HAProxy の IP Sharing 化については下記の資料を参照します。
Redis Sentinel の準備
以下の記事を参考にして、Redis Sentinel を使った 3 ノード構成と HAProxy と Redis Client の環境を用意します。
追加の HAProxy の準備
先に用意した HAProxy の構成を追加で一台作成します。それぞれ 2.4.22 で動作しています。
ord-haproxy1:~# haproxy -v
HAProxy version 2.4.22-0ubuntu0.22.04.1 2023/03/22 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2026.
Known bugs: http://www.haproxy.org/bugs/bugs-2.4.22.html
Running on: Linux 6.2.9-x86_64-linode160 #1 SMP PREEMPT_DYNAMIC Wed Apr 5 15:30:32 EDT 2023 x86_64
ord-haproxy2:~# haproxy -v
HAProxy version 2.4.22-0ubuntu0.22.04.1 2023/03/22 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2026.
Known bugs: http://www.haproxy.org/bugs/bugs-2.4.22.html
Running on: Linux 6.2.9-x86_64-linode160 #1 SMP PREEMPT_DYNAMIC Wed Apr 5 15:30:32 EDT 2023 x86_64
ord-redisclient:~# redis-cli -v
redis-cli 6.0.16
Redis Client からの動作確認
2つの HAProxy を配置し、それぞれ、Redis Sentinel を構成したノードに接続しています。
ord-redisclient:~# redis-cli -h ord-haproxy1 --tls --cacert redissentinel-ord_ca.crt info replication | egrep role
role:master
ord-redisclient:~# redis-cli -h ord-haproxy2 --tls --cacert redissentinel-ord_ca.crt info replication | egrep role
role:master
このときの /etc/hosts
の情報です。
# Redis
192.168.XXX.1 ord-redissentinel1 redis-1
192.168.XXX.2 ord-redissentinel2 redis-2
192.168.XXX.3 ord-redissentinel3 redis-3
192.168.0.1 ord-haproxy1
192.168.0.2 ord-haproxy2
192.168.XXX.11 ord-redisclient
この状態では 各 Redis Server の Firewalld では Redis Client からのアクセスも許可しているので、それぞれにアクセスすると redis-2
と redis-3
がレプリカであることが分かります。
ord-redisclient:~# redis-cli -h redis-1 --tls --cacert redissentinel-ord_ca.crt info replication | egrep role
role:master
ord-redisclient:~# redis-cli -h redis-2 --tls --cacert redissentinel-ord_ca.crt info replication | egrep role
role:slave
ord-redisclient:~# redis-cli -h redis-3 --tls --cacert redissentinel-ord_ca.crt info replication | egrep role
role:slave
IP Sharing の導入
IP Sharing は一つの IP を複数のノードで共有することができる技術です。一つのノードだけがその IP を使うことができ、内部的な障害検知によってIPを保持しているノードがダウンしたときに別のノードがそのIPを引き取ることができます。
下図のように2つの HAProxy があり、それぞれ 192.168.0.1
と 192.168.0.2
を持っています。haproxy1 はさらに別の 192.168.0.3
を持っている状態です。
haproxy2 のネットワーク設定で 192.168.0.3
を IP Sharing として登録し、適切な設定をすると、haproxy1 の障害時に haproxy2 が 192.168.0.3
を使うことができます。
haproxy1 に Private IP を追加
追加するには Cloud Manager からサポートサービスに連絡する必要があります。
haproxy2 に Shared IP として追加
haproxy2 のネットワーク設定から IP Sharing を選択します。
IP Sharing の画面から、 haproxy1 に追加した 192.168.0.3
を選択します。
追加されれば、''IP Sharing uploaded successfully`` のようなメッセージが表示されるので、ポップアップ画面を閉じます。
haproxy2 のネットワーク設定で追加した IP が Shared
として登録されています。
ネットワークに Shared IP を加える (haproxy1 と haproxy2 の共通設定)
先程の作業はプラットフォーム上の設定です。次に Linux 上の設定を行います。
/etc/netplan/01-netcfg.yaml
# This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
version: 2
renderer: networkd
ethernets:
eth0:
dhcp4: yes
lo: # ここから追加
match:
name: lo
addresses:
- 192.168.0.3/32 # /17 ではなく #32 ですので注意
設定を反映させます。
netplan apply
設定後、双方のサーバーの lo
デバイスに 登録した Private IP アドレスが表示されます。
ord-haproxy1:/etc/netplan# ip -4 a show dev lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet 192.168.0.3/32 scope global lo
valid_lft forever preferred_lft forever
ord-haproxy2:/etc/netplan# ip -4 a show dev lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet 192.168.0.3/32 scope global lo
valid_lft forever preferred_lft forever
lelastic のインストールと設定
lelastic
は Linode の独自ツールです。エラスティックな IP をできるだけ簡単に使用できるように設計されたクライアントです。
以下のコマンドを実行します。
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/
lelastic.service のファイルを作成する
ord-haproxy2:~# vi /etc/systemd/system/lelastic.service
ファイルは以下のようにします。[ID]
と [role]
は後で編集します。
[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
[ID]
はデータセンターの番号を入れます。下記のページの表に記載があります。
[role]
には Shared IP をプライマリで動かすホスト側(haproxy1) では primary
を、共有されるホスト側(haproxy2) では secondary
と書き換えます。
HAproxy 1 の設定
ExecStart=/usr/local/bin/lelastic -dcid 18 -primary &
-loglevel debug
などを追記すると、/var/log/syslog
により詳細なログが記録されます。
HAproxy 2 の設定
ExecStart=/usr/local/bin/lelastic -dcid 18 -secondary &
lelastic の起動 (haproxy1 と haproxy2 の共通作業)
chmod 644 /etc/systemd/system/lelastic.service
systemctl start lelastic
systemctl enable lelastic
HAProxy の Bind 設定の変更
haproxy1
frontend ft_redis
# HAProxy Private IP address
# bind 191.168.0.1:6379 name redis
# shared IP address
bind 192.168.0.3:6379 name redis
default_backend bk_redis
次のような設定にすることもできます。
bind *:6379 name redis
haproxy2
frontend ft_redis
# HAProxy Private IP address
# bind 191.168.0.2:6379 name redis
# shared IP address
bind 192.168.0.3:6379 name redis
default_backend bk_redis
Redis Client から IP Sharing が動作するかを確認
現在の状態です。
Redis クライアントに IP Sharing のアドレスを登録
IP Sharing のアドレスを /etc/hosts
に登録します。
192.168.XXX.1 ord-redissentinel1 redis-1
192.168.XXX.2 ord-redissentinel2 redis-2
192.168.XXX.3 ord-redissentinel3 redis-3
# END redis servers
192.168.0.1 ord-haproxy1
192.168.0.2 ord-haproxy2
192.168.0.3 ord-haproxy # 追加した行です
192.168.XXX.11 ord-redisclient
Redis-cli からの接続確認 (その 1)
ord-redisclient:~# redis-cli -h ord-haproxy --tls --cacert redissentinel-ord_ca.crt ping
PONG
ord-redisclient:~# redis-cli -h ord-haproxy --tls --cacert redissentinel-ord_ca.crt info replication | grep role
role: master
Read/Write もできる状態です。
ord-redisclient:~# redis-cli -h ord-haproxy --tls --cacert redissentinel-ord_ca.crt
ord-haproxy:6379> set scott tiger
OK
ord-haproxy:6379> get scott
"tiger"
ord-haproxy:6379> get scott
"tiger"
ord-haproxy:6379> set scott lion
OK
ord-haproxy:6379> get scott
"lion"
ord-haproxy:6379>
Primary と動作しているホストで lelastic を停止
マスターサーバーのプロセスを停止します。
ord-haproxy1:/etc/haproxy# systemctl stop lelastic
サーバー停止中でも同様に動作します。
この仕組みでは systemctl stop haproxy
は検知できません。
Redis-cli からの接続確認 (その 2)
一瞬接続エラーが出ますが、すぐに新しいコマンドに対して応答が返ってきます。
ord-haproxy:6379> get scott
Could not connect to Redis at ord-haproxy:6379: SSL_connect failed: unexpected eof while reading
not connected> get scott
"lion"
redis-2
がマスターに昇格していますが、その状況をクライアント側は気にすることなく接続できています。
ord-haproxy1:/etc/haproxy# redis-cli -h redis-2 --tls --cacert /etc/haproxy/tls/redissentinel-ord_ca.crt info replication | grep role
role:master
Secondary と動作しているホストで lelastic を停止
ord-haproxy2:/etc/systemd/system# systemctl stop lelastic
Redis-cli からの接続確認 (その 3)
応答はなくなります。
ord-haproxy:6379> get scott
Primary と動作しているホストで lelastic を再開
ord-haproxy1:/etc/haproxy# systemctl start lelastic
Redis-cli からの接続確認 (その 4)
すぐに接続されます。
ord-haproxy:6379> get scott
"lion"
(65.31s)
ord-haproxy:6379> get scott
"lion"
ord-haproxy:6379> set scott tiger
OK
ord-haproxy:6379> get scott
"tiger"
Redis マスターサーバーの停止
redis-1:~# systemctl stop redis-server
redis-2
がマスターに昇格しています。
ord-haproxy1:/etc/haproxy# redis-cli -h redis-2 --tls --cacert /etc/haproxy/tls/redissentinel-ord_ca.crt info replication | grep role
role:master
Redis-cli からの接続確認 (その 5)
redis-2
がマスターに昇格していますが、その状況をクライアント側は気にすることなく接続できています。
ord-haproxy:6379> get scott
Could not connect to Redis at ord-haproxy:6379: SSL_connect failed: unexpected eof while reading
not connected> get scott
"lion"
ord-haproxy:6379> get scott
"lion"
(65.31s)
ord-haproxy:6379> get scott
"lion"
止めたプロセスを再開します。
redis-1:~# systemctl start redis-server
ord-haproxy2:/etc/systemd/system# systemctl start lelastic
まとめ
Redis Sentinel、HAProxy、IP Sharing を利用することで、高可用性の Redis サーバーを提供できます。利用するデータセンターの地域によって IP Sharing を利用したフェールオーバーの方式が変わることがありますので、ドキュメントを注意深く確認しましょう。