はじめに
IBM Application Gatewayのセッション情報を保存できるRedisサーバー冗長化は、構成パターンがいくつかいくつかあります。
IBM Application GatewayがRedis Clusterをサポートしていないため、Standalone構成、Replication(マスター/スレーブ)構成、あるいは、Sentinel構成が候補となります。
Redisの冗長化についてはこちらを参考にさせて頂きました。
https://www.sraoss.co.jp/tech-blog/redis/redis-ha/
今回は、Kubernetesのガイドにあるyamlをベースにマスター/レプリカ構成を組んでみました。
例: Redisを使用したPHPのゲストブックアプリケーションのデプロイ
https://kubernetes.io/ja/docs/tutorials/stateless-application/guestbook/
悩みポイント1:Imageを変えると、レプリカ側もマスターとして動作してしまう。
KubernetesのガイドにあるYamlファイルは、imageが次のように指定されていました。
マスター:image: k8s.gcr.io/redis:e2e
レプリカ:image: gcr.io/google_samples/gb-redisslave:v3
imageをDocker HubのRedisイメージに変更したところ、レプリカ側もマスターとして起動しました。
https://hub.docker.com/_/redis
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-slave
labels:
app: redis
spec:
selector:
matchLabels:
app: redis
role: slave
tier: backend
replicas: 2
template:
metadata:
labels:
app: redis
role: slave
tier: backend
spec:
containers:
- name: slave
image: redis:latest
resources:
requests:
cpu: 100m
memory: 100Mi
env:
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 6379
以下の記事を拝見して、レプリカとして動かすためにはRedisの設定が必要な点がわかりました。
最終系のマスター/レプリカをデプロイするためのYAMLファイルはこちらです。
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-master
labels:
app: redis
spec:
selector:
matchLabels:
app: redis
role: master
tier: backend
replicas: 1
template:
metadata:
labels:
app: redis
role: master
tier: backend
spec:
containers:
- name: master
image: redis:latest
command:
- "redis-server"
args:
- "--protected-mode"
- "no"
resources:
requests:
cpu: 100m
memory: 100Mi
ports:
- containerPort: 6379
スレーブとして動作させるため、slaveof <マスターのサービス名> <ポート番号> のコマンドを追加しています。
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-slave
labels:
app: redis
spec:
selector:
matchLabels:
app: redis
role: slave
tier: backend
replicas: 2
template:
metadata:
labels:
app: redis
role: slave
tier: backend
spec:
containers:
- name: slave
image: redis:latest
command:
- "redis-server"
args:
- "--slaveof"
- "redis-master"
- "6379"
- "--protected-mode"
- "no"
resources:
requests:
cpu: 100m
memory: 100Mi
env:
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 6379
サービスの設定はKubernetesのガイドと同じです。
apiVersion: v1
kind: Service
metadata:
name: redis-master
labels:
app: redis
role: master
tier: backend
spec:
ports:
- port: 6379
targetPort: 6379
selector:
app: redis
role: master
tier: backend
apiVersion: v1
kind: Service
metadata:
name: redis-slave
labels:
app: redis
role: slave
tier: backend
spec:
ports:
- port: 6379
selector:
app: redis
role: slave
tier: backend
悩みポイント2:"Failed opening the RDB file dump.rdb (in server root dir /data) for saving: Permission denied"が出力されて、マスター/レプリカ間で同期できない。
マスター側のログに"Failed opening the RDB file dump.rdb (in server root dir /data) for saving: Permission denied"が出力されていました。
1:M 06 Apr 2022 04:14:02.271 * Replica 172.30.169.41:6379 asks for synchronization
1:M 06 Apr 2022 04:14:02.271 * Full resync requested by replica 172.30.169.41:6379
1:M 06 Apr 2022 04:14:02.271 * Replication backlog created, my new replication IDs are 'a5cd3c705f8a0b324f44971ca6fc7d8043ce482b' and '0000000000000000000000000000000000000000'
1:M 06 Apr 2022 04:14:02.271 * Starting BGSAVE for SYNC with target: disk
1:M 06 Apr 2022 04:14:02.272 * Background saving started by pid 11
11:C 06 Apr 2022 04:14:02.272 # Failed opening the RDB file dump.rdb (in server root dir /data) for saving: Permission denied
1:M 06 Apr 2022 04:14:02.369 # Background saving error
1:M 06 Apr 2022 04:14:02.369 # Connection with replica 172.30.169.41:6379 lost.
1:M 06 Apr 2022 04:14:02.369 # SYNC failed. BGSAVE child returned an error
パーミッションの問題にみえるため、必要な権限を確認したところ、anyuidのSSCが必要でした。
> oc get pods
NAME READY STATUS RESTARTS AGE
redis-master-84f49d559d-q678p 1/1 Running 0 8m31s
redis-slave-5f7bc5fb7c-d26f5 1/1 Running 0 7m38s
redis-slave-5f7bc5fb7c-psh4q 1/1 Running 0 7m38s
> oc get pod/redis-master-84f49d559d-q678p -o yaml|oc adm policy scc-subject-review -f -
RESOURCE ALLOWED BY
Pod/redis-master-84f49d559d-q678p anyuid
このため、anyuidのSSCを持つサービスアカウントを作成して、デプロイメントに設定します。
> oc create serviceaccount redis-sa
serviceaccount/redis-sa created
> oc adm policy add-scc-to-user anyuid -z redis-sa
clusterrole.rbac.authorization.k8s.io/system:openshift:scc:anyuid added: "redis-sa"
> oc describe serviceaccount redis-sa
Name: redis-sa
Namespace: test-redis
Labels: <none>
Annotations: <none>
Image pull secrets: redis-sa-dockercfg-q8w5d
Mountable secrets: redis-sa-token-sqcdj
redis-sa-dockercfg-q8w5d
Tokens: redis-sa-token-4llgf
redis-sa-token-sqcdj
Events: <none>
> oc set serviceaccount deployment/redis-master redis-sa
deployment.apps/redis-master serviceaccount updated
> oc describe deployment/redis-master |grep Service
Service Account: redis-sa
> oc set serviceaccount deployment/redis-slave redis-sa
deployment.apps/redis-slave serviceaccount updated
> oc describe deployment/redis-slave |grep Service
Service Account: redis-sa
設定することでエラー解消しました
1:C 06 Apr 2022 04:27:53.749 # Configuration loaded
1:M 06 Apr 2022 04:27:53.751 * monotonic clock: POSIX clock_gettime
1:M 06 Apr 2022 04:27:53.752 * Running mode=standalone, port=6379.
1:M 06 Apr 2022 04:27:53.752 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1:M 06 Apr 2022 04:27:53.752 # Server initialized
1:M 06 Apr 2022 04:27:53.753 * Ready to accept connections
1:M 06 Apr 2022 04:27:55.130 * Replica 172.30.115.4:6379 asks for synchronization
1:M 06 Apr 2022 04:27:55.130 * Full resync requested by replica 172.30.115.4:6379
1:M 06 Apr 2022 04:27:55.130 * Replication backlog created, my new replication IDs are '9d966da84bc748f7df876a47339d13ff678d045d' and '0000000000000000000000000000000000000000'
1:M 06 Apr 2022 04:27:55.130 * Starting BGSAVE for SYNC with target: disk
1:M 06 Apr 2022 04:27:55.130 * Background saving started by pid 11
11:C 06 Apr 2022 04:27:55.136 * DB saved on disk
11:C 06 Apr 2022 04:27:55.137 * RDB: 0 MB of memory used by copy-on-write
1:M 06 Apr 2022 04:27:55.164 * Background saving terminated with success
1:M 06 Apr 2022 04:27:55.164 * Synchronization with replica 172.30.115.4:6379 succeeded
1:M 06 Apr 2022 04:27:55.650 * Replica 172.30.169.41:6379 asks for synchronization
1:M 06 Apr 2022 04:27:55.650 * Full resync requested by replica 172.30.169.41:6379
1:M 06 Apr 2022 04:27:55.650 * Starting BGSAVE for SYNC with target: disk
1:M 06 Apr 2022 04:27:55.651 * Background saving started by pid 12
12:C 06 Apr 2022 04:27:55.654 * DB saved on disk
マスター側のRedisサーバーに/data/dump.rdbファイルがあること、2つのスレーブと接続できていること(connected_slaves)を確認します。
> oc get pods
NAME READY STATUS RESTARTS AGE
redis-master-5c69db88c4-g6glq 1/1 Running 0 4m1s
redis-slave-6dcb7cdcd5-8lrl6 1/1 Running 0 3m49s
redis-slave-6dcb7cdcd5-pzxbm 1/1 Running 0 3m55s
PS C:\temp-openshift\iag> oc rsh redis-master-5c69db88c4-g6glq
# ls /data
dump.rdb
# redis-cli info replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.30.169.42,port=6379,state=online,offset=350,lag=0
slave1:ip=172.30.115.19,port=6379,state=online,offset=350,lag=0
master_failover_state:no-failover
master_replid:9d966da84bc748f7df876a47339d13ff678d045d
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:350
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:350
マスター側でテストデータを書き込みします。
> redis-cli set aaa 111
OK
> redis-cli get aaa
"111"
レプリカ側でも同様に確認します。
master_link_statusがupになっているため、マスター側とリンクできています。
> oc get pods
NAME READY STATUS RESTARTS AGE
redis-master-5c69db88c4-g6glq 1/1 Running 0 7m40s
redis-slave-6dcb7cdcd5-8lrl6 1/1 Running 0 7m28s
redis-slave-6dcb7cdcd5-pzxbm 1/1 Running 0 7m34s
PS C:\temp-openshift\iag> oc rsh redis-slave-6dcb7cdcd5-8lrl6
# ls /data
dump.rdb
# redis-cli info replication
# Replication
role:slave
master_host:redis-master
master_port:6379
master_link_status:up
master_last_io_seconds_ago:9
master_sync_in_progress:0
slave_read_repl_offset:698
slave_repl_offset:698
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:9d966da84bc748f7df876a47339d13ff678d045d
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:698
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:15
repl_backlog_histlen:684
先ほどマスター側で登録したテストデータの同期が確認できました。
> redis-cli get aaa
"111"
最後に
今回は、Redisサーバーの冗長化構成を試しました。
今後IBM Applicatio Gatewayと組み合わせて動作確認していきたいと思います。