Redis Sentinel on Akamai
Akamai のクラウドコンピューティング・サービスが提供するマーケットプレイスから、Redis Sentinel のクラスタ構成を簡単に作成することができます。HAProxy を配置することで、アプリケーションから常にマスターサーバーに接続して read/write することもできます。詳細については下記の記事を参照ください。
上の記事では Private IP を使ってネットワークを構成していますが、本記事は VLAN で構成する方法について記載します。まず、Private IP で構成されるネットワークを上記の記事を参考に作成します。作成されたネットワークは以下のようになります。
VLAN
Private IP を使った先程の構成から VLAN 構成に変更したものが以下の図となります。本記事ではこの構成に移行する手順を記載します。
HAProxy は冗長構成にすべきですが、本記事では解説をシンプルにするため一台構成で進めます。
進め方の大きな流れは下記のようになります。
- Marketplace から Redis Sentinel をインストールする
- HAProxy、VLAN のルーター、Redis Client に相当する Linode ノードを構築します
- Redis Sentinel の各ノード、HAProxy、 ルーター、Redis Client の全てのノードに VLAN の IP アドレスを割り当てます。
- Redis Sentinel の各ノードと HAProxy から Public IP、Private IP の割当を削除します。
- Redis Client から HAProxy 経由で常に Redis のマスターサーバーにアクセスできることを確認します。
この大きな流れの中にいくつかチェックポイントを設け、正しく動作しているかを確認します。
共通ホスト設定
最初に VLAN の IP を決めます。VLAN については下記の記事を参考にしてください。
全体的に実施することは単純で Private IP を VLAN の IP に変更することです。最初に次のようにマップするテーブルを用意すると楽になります。
Hostname | Private IP | Hostname (VLAN) | VLAN IP |
---|---|---|---|
redis_1 | 192.168.XXX.XX1 | redis-1v | 10.0.0.11 |
redis_2 | 192.168.XXX.XX2 | redis-2v | 10.0.0.12 |
redis_3 | 192.168.XXX.XX3 | redis-3v | 10.0.0.13 |
router | vlan-router | 10.0.0.1 | |
haproxy | vlan-haproxy | 10.0.0.21 | |
Redis Client | vlan-redisclient | 10.0.0.22 |
最終的に Public IP を持つのは、Redis Client と Router となります。要件によって、適切に定義してください。Router は VLAN の中から外に通信するときに必要になります。詳細は以下の記事を参照してください。
/etc/hosts
10.0.0.11 redis-1v #Redis Sentinel 1
10.0.0.12 redis-2v # Redis Sentinel 2
10.0.0.13 redis-3v # Redis Sentinel 3
10.0.0.1 vlan-router
10.0.0.21 vlan-haproxy
10.0.0.22 vlan-redisclient
これから、それぞれのホストでの作業を行います。Redis Sentinel の3つのノードでは redis.conf
、sentinel.conf
、firewalld
に関する設定を VLAN に変更します。
redis.conf
は Redis Replication に関する IP 設定を変更します。既存の Private IP で構成されている記述を VLAN に変更します。
sentinel.conf
は Redis Sentinel に関する IP 設定を変更します。既存の Private IP で構成されている記述を VLAN に変更します。
firewalld
プロセスが動作している構成に VLAN の IP アドレスを追記します。VLAN を構成した後は、firewalld
を動かす必要性は薄れますので、状況によってはプロセスを停止して確認してください。
この他にも、eth デバイスで VLAN を有効にするためにはシステムのネットワーク設定の変更も必須となります。
ルーターとなるホストは IP Forwarding の設定をします。設定は以下の記事を参照します。
Redis Server のプロセス停止
まず、Redis Server と Sentinel のプロセスを止めます。順番は次のようにします。
- レプリカサーバーの Sentinel を止める。複数台あれば、その順番は問いません。
- マスターサーバーの Sentinel を止める
- レプリカサーバーを止める。複数台あれば、その順番は問いません。
- マスターサーバーを止める
Sentinel を先に止めることによって、意図的にマスターとレプリカの変更をしないようにします。
redis_1
がマスターサーバー、redis_2
とredis_3
がレプリカサーバーである場合は次の順番で作業します。
redis_2# systemctl stop redis-sentinel
redis_3# systemctl stop redis-sentinel
redis_1# systemctl stop redis-sentinel
redis_2# systemctl stop redis-server
redis_3# systemctl stop redis-server
redis_1# systemctl stop redis-server
redis-1v
redis_1
がマスターサーバーとして動作していることを想定しています。すでにサーバー群は停止しているので、redis-1v
、redis-2v
、redis-3v
の作業の順番は問いません。
/etc/redis/redis.conf
#bind 127.0.0.1 ::1 192.168.XXX.XX1
bind 127.0.0.1 ::1 10.0.0.11
bind
の記述は Redis Server がクライアントから listen するための自分自身の IP アドレスを登録します。Private IP の記述を VLAN の IP に変更します。
/etc/redis/sentinel.conf
#bind 127.0.0.1 ::1 192.168.XXX.XX1
bind 127.0.0.1 ::1 10.0.0.11
#sentinel monitor mymaster 192.168.XXX.XX1 6379 2
sentinel monitor mymaster 10.0.0.11 6379 2
#sentinel known-replica mymaster 192.168.XXX.XX3 6379
sentinel known-replica mymaster 10.0.0.13 6379
#sentinel known-replica mymaster 192.168.XXX.XX2 6379
sentinel known-replica mymaster 10.0.0.12 6379
#sentinel known-sentinel mymaster 192.168.XXX.XX2 26379 f80d00523b7831d8362ad5cf5c60f0975057b10f
sentinel known-sentinel mymaster 10.0.0.12 26379 f80d00523b7831d8362ad5cf5c60f0975057b10f
#sentinel known-sentinel mymaster 192.168.XXX.XX3 26379 83e7fea9eab2635981d02d5ad62142653b309e08
sentinel known-sentinel mymaster 10.0.0.13 26379 83e7fea9eab2635981d02d5ad62142653b309e08
redis-2v
redis-2v
は一つのレプリカサーバーであることを想定しています。
/etc/redis/redis.conf
#bind 127.0.0.1 ::1 192.168.XXX.XX2
bind 127.0.0.1 ::1 10.0.0.12
#replicaof 192.168.XXX.XX1 6379
replicaof 10.0.0.11 6379
/etc/redis/sentinel.conf
#bind 127.0.0.1 ::1 192.168.XXX.XX2
bind 127.0.0.1 ::1 10.0.0.12
#sentinel monitor mymaster 192.168.XXX.XX1 6379 2
sentinel monitor mymaster 10.0.0.11 6379 2
#sentinel known-replica mymaster 192.168.XXX.XX3 6379
sentinel known-replica mymaster 10.0.0.13 6379
#sentinel known-replica mymaster 192.168.XXX.XX2 6379
sentinel known-replica mymaster 10.0.0.12 6379
#sentinel known-sentinel mymaster 192.168.XXX.XX1 26379 662bdc406dfb2ce3fb31d2e7b5ca0eece38910b7
sentinel known-sentinel mymaster 10.0.0.11 26379 662bdc406dfb2ce3fb31d2e7b5ca0eece38910b7
#sentinel known-sentinel mymaster 192.168.XXX.XX3 26379 83e7fea9eab2635981d02d5ad62142653b309e08
sentinel known-sentinel mymaster 10.0.0.13 26379 83e7fea9eab2635981d02d5ad62142653b309e08
redis-3v
redis-3v
はもう一つのレプリカサーバーであることを想定しています。
/etc/redis/redis.conf
#bind 127.0.0.1 ::1 192.168.XXX.XX3
bind 127.0.0.1 ::1 10.0.0.13
# Generated by CONFIG REWRITE
#replicaof 192.168.XXX.XX1 6379
replicaof 10.0.0.11 6379
/etc/redis/sentinel.conf
#bind 127.0.0.1 ::1 192.168.XXX.XX3
bind 127.0.0.1 ::1 10.0.0.13
#sentinel monitor mymaster 192.168.XXX.XX1 6379 2
sentinel monitor mymaster 10.0.0.11 6379 2
#sentinel known-replica mymaster 192.168.XXX.XX3 6379
sentinel known-replica mymaster 10.0.0.13 6379
#sentinel known-replica mymaster 192.168.XXX.XX2 6379
sentinel known-replica mymaster 10.0.0.12 6379
#sentinel known-sentinel mymaster 192.168.XXX.XX1 26379 662bdc406dfb2ce3fb31d2e7b5ca0eece38910b7
sentinel known-sentinel mymaster 10.0.0.11 26379 662bdc406dfb2ce3fb31d2e7b5ca0eece38910b7
#sentinel known-sentinel mymaster 192.168.XXX.XX2 26379 f80d00523b7831d8362ad5cf5c60f0975057b10f
sentinel known-sentinel mymaster 10.0.0.12 26379 f80d00523b7831d8362ad5cf5c60f0975057b10f
Firewalld
/etc/firewalld/zones/internal.xml
firewalld
の設定です。マーケットプレイスからプロビジョニングしたときは、Redis サーバーの Private IP 以外からはアクセスできないように設定されています。以下の行を追加します。
<source address="10.0.0.11"/>
<source address="10.0.0.12"/>
<source address="10.0.0.13"/>
<source address="10.0.0.21"/>
<source address="10.0.0.1"/>
<source address="10.0.0.22"/>
source address
以外の設定はそのまま残しておいてください。最終的には Private IP を削除します。
設定を反映します。
firewall-cmd --reload
設定を確認します。
firewall-cmd --get-active-zone
Redis-server の再起動
まず、Redis Server と Sentinel のプロセスを起動します。順番は次のようにします。
- マスターサーバーを起動する
- レプリカサーバーを起動する。複数台あれば、その順番は問いません。
- マスターサーバーの Sentinel を起動する
- レプリカサーバーの Sentinel を起動する。複数台あれば、その順番は問いません。
redis_1
がマスターサーバー、redis_2
とredis_3
がレプリカサーバーである場合は次の順番で作業します。
redis-1v
redis_1:/etc/redis# systemctl start redis-server
redis_1:/etc/redis# redis-cli --tls --cacert /etc/redis/tls/ca.crt ping
PONG
redis_1:/etc/redis# redis-cli --tls --cacert /etc/redis/tls/ca.crt role
1) "master"
2) (integer) 258540423
3) (empty array)
redis-2v
redis_2:/etc/redis# systemctl start redis-server
redis_2:/etc/redis# redis-cli --tls --cacert /etc/redis/tls/ca.crt ping
PONG
redis_2:/etc/redis# redis-cli --tls --cacert /etc/redis/tls/ca.crt role
1) "slave"
2) "10.0.0.11"
3) (integer) 6379
4) "connected"
5) (integer) 258540493
redis-3v
redis_3:/etc/redis# systemctl start redis-server
redis_3:/etc/redis# redis-cli --tls --cacert /etc/redis/tls/ca.crt ping
PONG
redis_3:/etc/redis# redis-cli --tls --cacert /etc/redis/tls/ca.crt role
1) "slave"
2) "10.0.0.11"
3) (integer) 6379
4) "connected"
5) (integer) 258540619
HAproxy ホストからの確認
# redis-cli -h redis-1v --tls --cacert redis-nj_ca.crt role
1) "master"
2) (integer) 258541333
3) 1) 1) "10.0.0.12"
2) "6379"
3) "258541319"
2) 1) "10.0.0.13"
2) "6379"
3) "258541319"
# redis-cli -h redis-2v --tls --cacert redis-nj_ca.crt role
1) "slave"
2) "10.0.0.11"
3) (integer) 6379
4) "connected"
5) (integer) 258541333
# redis-cli -h redis-3v --tls --cacert redis-nj_ca.crt role
1) "slave"
2) "10.0.0.11"
3) (integer) 6379
4) "connected"
5) (integer) 258541347
Redis-sentinel の起動
redis_1# systemctl start redis-sentinel
redis_2# systemctl start redis-sentinel
redis_3# systemctl start redis-sentinel
HAproxy ホストからの接続
haproxy# redis-cli -h vlan-haproxy --tls --cacert /etc/haproxy/tls/redis-nj_ca.crt ping
PONG
haproxy# redis-cli -h vlan-haproxy --tls --cacert /etc/haproxy/tls/redis-nj_ca.crt role
1) "master"
2) (integer) 259155340
3) 1) 1) "10.0.0.12"
2) "6379"
3) "259155340"
2) 1) "10.0.0.13"
2) "6379"
3) "259155207"
Client からの接続
haproxy:~# ip -4 a show dev eth1
4: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
inet 10.0.0.21/24 brd 10.0.0.255 scope global eth1
valid_lft forever preferred_lft forever
redisclient:~# redis-cli -h vlan-haproxy --tls --cacert redis-nj_ca.crt ping
PONG
redisclient:~# redis-cli -h vlan-haproxy --tls --cacert redis-nj_ca.crt role
1) "master"
2) (integer) 275843158
3) 1) 1) "10.0.0.12"
2) "6379"
3) "275843158"
2) 1) "10.0.0.13"
2) "6379"
3) "275843144"
Redis の Public IP を削除し、VLAN Only にする
redis-1v
before
after
/etc/systemd/network/05-eth0.network
Linode の Network Helper は様々な OS のネットワーク設定を自動で最適化してくれる便利な機能ですが、VLAN を利用するときは無効化することが推奨されています。Netowork Helper を無効化し、ネットワークの設定は以下のようにします。
[Match]
Name=eth0
[Network]
DHCP=no
Domains=members.linode.com
IPv6PrivacyExtensions=false
Address=10.0.0.11/24
Gateway=10.0.0.1
ルーティング設定
ping が動作しない場合、ルーティングを確認してください。
redis_1:/etc/systemd/network# ip r
default via 10.0.0.1 dev eth0 proto static
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.11
ping も動作します。
redis_1:/etc/systemd/network# ping linode.com
PING linode.com (69.164.200.202) 56(84) bytes of data.
64 bytes from www-loadbal2.linode.com (69.164.200.202): icmp_seq=1 ttl=48 time=50.0 ms
64 bytes from www-loadbal2.linode.com (69.164.200.202): icmp_seq=2 ttl=48 time=46.8 ms
DNS に問題があるようでしたら、/etc/systemd/resolved.conf
の DNS
を確認してください。
redis-2v
Cloud Console 上の Configuration > Network 設定を確認してください。redis-1v
同様、05-eth0.network
や ip r
も確認してください。
before
after
/etc/systemd/network/05-eth0.network
[Match]
Name=eth0
[Network]
DHCP=no
Domains=members.linode.com
IPv6PrivacyExtensions=false
Address=10.0.0.12/24
Gateway=10.0.0.1
redis-3v
after
Client からの接続
redisclient:~# redis-cli -h vlan-haproxy --tls --cacert redis-nj_ca.crt
vlan-haproxy:6379> role
1) "master"
2) (integer) 286550827
3) 1) 1) "10.0.0.12"
2) "6379"
3) "286550827"
2) 1) "10.0.0.13"
2) "6379"
3) "286550827"
HAProxy の Public IP を削除し、VLAN Only にする
Before
After
Client からの接続
redisclient:~# redis-cli -h vlan-haproxy --tls --cacert redis-nj_ca.crt ping
PONG
redisclient:~# redis-cli -h vlan-haproxy --tls --cacert redis-nj_ca.crt role
1) "master"
2) (integer) 286608397
3) 1) 1) "10.0.0.12"
2) "6379"
3) "286608264"
2) 1) "10.0.0.13"
2) "6379"
3) "286608264"
Redis マスターサーバーを計画停止する
Redis Client から HAProxy 経由で Redis マスターサーバーに接続します。
redisclient:~# redis-cli -h vlan-haproxy --tls --cacert redis-nj_ca.crt
vlan-haproxy:6379> role
1) "master"
2) (integer) 286765792
3) 1) 1) "10.0.0.12"
2) "6379"
3) "286765792"
2) 1) "10.0.0.13"
2) "6379"
3) "286765792"
vlan-haproxy:6379> set scott tiger
OK
vlan-haproxy:6379> get scott
"tiger"
マスターサーバーが動作している redis_1
の redis-server
を停止します。
redis_1:~# systemctl stop redis-server
Redis クライアント(redisclient
)から HAProxy(vlan-haproxy
)に接続している redis-cli
でコマンドをいくつか打ちます。一瞬接続エラーがでましたが、その後、正常に動作しています。Redis Server が切り替わるまでは接続エラーになるはずですが、切り替わった後は HAProxy 経由で正常に接続し、書き込みもできています。
vlan-haproxy:6379> role
Could not connect to Redis at vlan-haproxy:6379: SSL_connect failed: unexpected eof while reading
not connected> role
1) "master"
2) (integer) 286782638
3) 1) 1) "10.0.0.13"
2) "6379"
3) "286782505"
vlan-haproxy:6379> role
1) "master"
2) (integer) 286783170
3) 1) 1) "10.0.0.13"
2) "6379"
3) "286783037"
vlan-haproxy:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=10.0.0.13,port=6379,state=online,offset=286787720,lag=0
master_failover_state:no-failover
master_replid:d73bba0408b89d4481305c1a90cf2ee662079b32
master_replid2:7c0b274d9fa87ba0c2328927591112715b687d09
master_repl_offset:286787720
second_repl_offset:286781538
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:286550660
repl_backlog_histlen:237061
vlan-haproxy:6379> get scott
"tiger"
vlan-haproxy:6379> set scott lion
OK
vlan-haproxy:6379> get scott
"lion"
Redis マスターサーバーが計画停止したときにレプリカサーバーがマスターに昇格しています。Redis クライアントからは HAProxy を経由して、常にマスターサーバーに接続できており、マスターサーバーがどこで動いているかを気にする必要がありません。
まとめ
最終的に以下のような構成を取ることができました。Redis Server には他のネットワークからは接続することができません。Redis を必要とするアプリケーションは同じ Region で同一の VLAN ネットワーク上である必要があります。