5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Redis+Sentinel を Kubernetes で動かしたメモ

Last updated at Posted at 2019-07-30

Redis+Sentinelを構成する理由

Redisキャッシュサーバーのアクセスの集中を軽減して、スケールするために、読書き可能なRedisマスターと読取り専用のRedisスレーブを組み合わせた構成を取ることがあります。これを Kubernetes上で実現する方法について、確認したのでメモとして残します。今更、HelmやOperatorで構築さればいいじゃない? と言われるかもしれませんが、Redisで高可用性を組む時のRedisの内容を理解しておきたいと思います。

redis-master-slave.png

IKS(IBM Cloud Kubernetes Service) https://cloud.ibm.com/ のK8sクラスタ上で動かしたのですが、使用しているマニフェストは、クラウド中立なマニフェストなので、どのクラウドでも動作すると思います。

Redisの監視とマスター選出の機能をになったSentinelが、Redisのプロジェクトから提供されています。Sentinelも可用性とマスター選出投票のために、複数プロセスが機能するようになっています。

Sentinelは、全てのRedisを監視しておき、マスターの停止に対して、次のマスターを選出します。そして、Sentinelに問い合わせることで、その時点でのマスターを教えてくれます。もちろん、Slaveも知ることができます。

Redisのクライアントであるアプリは、Sentinelに問い合わせて、RedisマスターのIPアドレスを求め、Redisのマスターへ書き込みます。また、読取りでは、スレーブをアクセスして、マスターが過負荷になることを回避します。Sentinelに問い合わせるための、プログラム言語のクライアントライブラリは、参考資料 にリンクを挙げておきます。

redis-sentinel.png

Redis + Sentinel の高可用性構成を起動する。

それでは、上図の構成をKubernetes上で作っていきます。

Kubernetesのクラスタが作られ、kubectlコマンドで操作できる状態を想定して、書いていきます。
それから、この構成は、参考資料 1 を、そのまま利用しています。 ここではフォークしたリポジトリをクローンしています。

git clone https://github.com/takara9/examples
cd examples/staging/storage/redis

# 起動用 Redisマスター + Sentinel のポッドをスタート
kubectl create -f redis-master.yaml

# Sentinelのサービスを起動  Sentinelにリクエストする時は、これにアクセスする
kubectl create -f redis-sentinel-service.yaml

# Redisサーバーを、レプリケーションコントローラー下で起動する
kubectl create -f redis-controller.yaml

# Sentinelサーバーも、レプリケーションコントローラー下で起動する
kubectl create -f redis-sentinel-controller.yaml

# レプリカ数を増やして、冗長化と性能アップを実施
kubectl scale rc redis --replicas=3
kubectl scale rc redis-sentinel --replicas=3

起動後に、Sentinelのサービス名とIPアドレスを確認しておきます。

$ kubectl get svc
NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)     AGE
kubernetes       ClusterIP   172.21.0.1       <none>        443/TCP     4d8h
redis-sentinel   ClusterIP   172.21.195.107   <none>        26379/TCP   92s

さらに、RedisサーバーとSentinelのポッドのIPアドレス付きリストを確認する。

i$ kubectl get po -o wide
NAME                   READY   STATUS   AGE     IP               NODE
redis-d62nc            1/1     Running  5m28s   172.30.94.152    10.193.10.14
redis-master           2/2     Running  6m2s    172.30.222.152   10.193.10.58
redis-sentinel-f49jh   1/1     Running  5m37s   172.30.94.150    10.193.10.14
redis-sentinel-m6dq8   1/1     Running  5m20s   172.30.222.153   10.193.10.58
redis-sentinel-p4jtb   1/1     Running  5m20s   172.30.94.153    10.193.10.14
redis-vnmsq            1/1     Running  5m28s   172.30.94.151    10.193.10.14

Sentinelに繋いでRedisマスターを求めて、Redisマスターに、テスト用データを書き込む

アプリケーションのクライアント相当としてredis-cliで、Redis+Sentinelの構成へ繋ぎます。

$ kubectl run -it redis-cli --rm --image redis --restart=Never -- bash
If you don't see a command prompt, try pressing enter.
root@redis-cli:/data# 

Sentinelへ繋いで、RedisマスターのIPアドレスを求めます。Sentinelのコマンドは参考資料 2 にあります。

root@redis-cli:/data# redis-cli -h redis-sentinel -p 26379
redis-sentinel:26379> SENTINEL get-master-addr-by-name mymaster
1) "172.30.222.152"
2) "6379"

Redisマスターからスレーブへのデータ同期を確認するために、RedisマスターにKeyとValueをセットします。

redis-sentinel:26379> connect 172.30.222.152 6379
172.30.222.152:6379> set abc 1000
OK
172.30.222.152:6379> get abc
"1000"
172.30.222.152:6379> incr abc
(integer) 1001
172.30.222.152:6379> incr abc
(integer) 1002

Redisスレーブをリストして、IPアドレスとポート番号を確認します。

redis-sentinel:26379> SENTINEL slaves mymaster
1)  1) "name"
    2) "172.30.94.151:6379"
<中略>
2)  1) "name"
    2) "172.30.94.152:6379"   

スレーブに繋いで、データが同期されているか確認します。目論見通りにデータが取り出せます。

172.30.222.152:6379> connect 172.30.94.151 6379
172.30.94.151:6379> get abc
"1002"
172.30.94.151:6379> connect 172.30.94.152 6379
172.30.94.152:6379> get abc
"1002"

マスター停止のテスト

RedisマスターのIPアドレスを調べて、kubectlコマンドで、マスターとなっているポッドを削除して、
フェイルオーバーを確認します。

redis-sentinel:26379> SENTINEL get-master-addr-by-name mymaster
1) "172.30.222.152"
2) "6379"

別のターミナルから、マスターのポッドを削除します。
起動時に、ポッドだけで立ち上げたものですが、後から追加したレプリケーションコントローラーのセレクターのラベルと同じにしているため、レプリケーションコントローラーは、このポッドも管理下として見なし、削除されると、新たなポッドを起動して、レプリカ数を維持するように振舞います。

$ kubectl delete po redis-master
pod "redis-master" deleted

レプリケーションコントローラーから起動されたポッドは、Redisスレーブとして参加します。そして、Sentinelの働きで、マスターに昇格するために投票が行われ、新たなRedisマスターが決まります。

redis-sentinel:26379> SENTINEL get-master-addr-by-name mymaster
1) "172.30.94.156"
2) "6379"

まとめ

既にビルドしたコンテナを使っているので、本番利用を考えるには、コンテナのビルドから考えないといけません。これに対して、参考資料1のGitHubに含まれています。
マスタースレーブ方式のスケール可能なキャッシュサーバを Kubernetes上で利用できることが、確認できました。

参考資料

  1. k8s redis例題, https://github.com/kubernetes/examples/tree/master/staging/storage/redis
  2. センチネルクライアント, https://redis.io/topics/sentinel-clients
  3. PHP Redisクライアントライブラリ、https://github.com/jamescauwelier/PSRedis
  4. Java Redisクライアントライブラリ、https://github.com/redisson/redisson
5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?