쿠버네티스 Redis Sentinel 적용
gemini 통해 생성된 기본 설정 파일 수정본
- setup.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-config
data:
redis.conf: |
port 6379
bind 0.0.0.0
dir /data
sentinel.conf: |
port 26379
bind 0.0.0.0
# 핵심: redis-0.redis 주소를 사용하며, 쿼럼(2)을 설정합니다.
sentinel monitor mymaster redis-0.redis.default.svc.cluster.local 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
sentinel resolve-hostnames yes
---
apiVersion: v1
kind: Service
metadata:
name: redis
spec:
clusterIP: None # Headless Service: redis-0.redis 주소를 가능하게 함
publishNotReadyAddresses: true
selector:
app: redis
ports:
- name: redis
port: 6379
- name: sentinel
port: 26379
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
serviceName: redis
replicas: 3
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
# Sentinel은 설정 파일에 쓰기 권한이 필요하므로 초기화 컨테이너로 복사합니다.
initContainers:
- name: config-init
image: redis:6.2-alpine
command:
- sh
- -c
- |
cp /readonly-conf/redis.conf /conf/redis.conf
cp /readonly-conf/sentinel.conf /conf/sentinel.conf
volumeMounts:
- name: readonly-config #아래에서 정의한 볼륨을 사용할것이다.
mountPath: /readonly-conf #컨테이너내 /readonly-conf 에 연결
- name: conf
mountPath: /conf
containers:
- name: redis
image: redis:6.2-alpine
command:
- sh
- -c
- |
echo "My host name ${HOSTNAME}"
# 2. 만약 내가 0번 포드가 아니라면, 0번을 마스터로 설정합니다.
if [ "${HOSTNAME}" != "redis-0" ]; then
echo "I am a slave. Pointing to redis-0.redis..."
# --replicaof 옵션을 사용해 실행 시점에 관계를 맺습니다.
exec redis-server /conf/redis.conf --replicaof redis-0.redis 6379
else
echo "I am the master (redis-0)."
exec redis-server /conf/redis.conf
fi
ports:
- containerPort: 6379
volumeMounts:
- name: conf
mountPath: /conf
- name: data
mountPath: /data
- name: sentinel
image: redis:6.2-alpine
command:
- sh
- -c
- |
# redis-0.redis가 IP를 반환할 때까지 무한 루프 (최대 30초 권장)
echo "Waiting for DNS..."
sleep 10
nslookup redis-0.redis.default.svc.cluster.local
echo "DNS is ready! Starting Sentinel..."
exec redis-sentinel /conf/sentinel.conf
ports:
- containerPort: 26379
volumeMounts:
- name: conf
mountPath: /conf
- name: data
mountPath: /data
volumes: #해당 볼륨은 spec에서 사용할 공통 볼륨의 준비 설정
- name: readonly-config #이름은 마음대로
configMap: # 위에서 정의한 configMap 설정중
name: redis-config #redis-config 라는 이름의 설정들 사용
- name: conf
emptyDir: {} # 여기에 설정파일을 복사해서 쓰기 권한을 확보함
# 빈 폴더로 사용할것이다.
- name: data
emptyDir: {} # PVC 대신 테스트용 임시 디렉토리
정상확인
# 처음 마스터 정보 확인
kubectl exec -it redis-0 -c sentinel -- redis-cli -p 26379 sentinel get-master-addr-by-name mymaster
- Sentinel이 서로를 인식했는지 확인 (Quorum 체크)
가장 먼저, Sentinel 3형제가 서로의 존재를 알고 마스터를 제대로 감시 중인지 확인해야 합니다.Bash
# redis-0 포드의 sentinel 컨테이너에게 마스터 상태를 물어봅니다.
kubectl exec -it redis-0 -c sentinel -- redis-cli -p 26379 sentinel master mymaster
- 체크 포인트:
- num-slaves: 2 (마스터 외에 2개의 복제본이 보여야 함)
- num-other-sentinels: 2 (자신을 제외한 다른 2개의 Sentinel이 보여야 함)
- flags: master (s_down이나 o_down이 붙어있지 않아야 함)
- 데이터 복제(Replication) 확인
마스터에 쓴 데이터가 슬레이브로 잘 넘어가고 있는지 확인합니다.
- 자동 장애 복구(Failover) 테스트 (핵심!)
마스터를 강제로 죽였을 때, Sentinel이 새로운 대장을 뽑는지 확인하는 단계입니다.
문제 및 해결
- 해당 파일을 기반으로 실행시 configmap.yaml 파일 내부에 사용되는 sentinel의 설정파일중 초기에 서비스의 이름을 가지고 마스터를 모니터링 하는 부분에서 자꾸 오류가 발생.
- pod 내부에 존재하는 sentinel의 컨테이너를 확인
kubectl logs redis-0 -c sentinel
- 오류 발생 로그 확인.
1:X 04 Jan 2026 13:58:01.651 # Failed to resolve hostname 'redis-0.redis-service'
*** FATAL CONFIG FILE ERROR (Redis 7.0.15) ***
Reading the configuration file, at line 4
\>>> 'sentinel monitor mymaster redis-0.redis-service 6379 2'
Can't resolve instance hostname.
- sentinel에서 호스트이름 확인 기능이 기본적으로 비활성화 되어있음.
configmap.yaml을 통해 sentinel resolve-hostnames yes 옵션 활성화.
https://stackoverflow.com/questions/57464443/redis-sentinel-throws-error-cant-resolve-master-instance-hostname
- 이후 정상적으로 pod가 뜨는것을 확인.