kubernetes(reids sentinel)

임재성·2026년 1월 4일

쿠버네티스 Redis Sentinel 적용

gemini 통해 생성된 기본 설정 파일 수정본

  1. 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
  1. 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이 붙어있지 않아야 함)
  1. 데이터 복제(Replication) 확인
    마스터에 쓴 데이터가 슬레이브로 잘 넘어가고 있는지 확인합니다.
  • 마스터에 데이터 쓰기:
    Bash
    kubectl exec -it redis-0 -c redis -- redis-cli set mytest "Success"
  • 슬레이브에서 읽기:
    Bash
    kubectl exec -it redis-1 -c redis -- redis-cli get mytest
    "Success"가 출력되면 복제가 완벽하게 작동하는 것입니다.
  1. 자동 장애 복구(Failover) 테스트 (핵심!)
    마스터를 강제로 죽였을 때, Sentinel이 새로운 대장을 뽑는지 확인하는 단계입니다.
  • 실시간 로그 감시 (터미널 하나 더 열기):
    #Bash
    # 살아남을 포드(redis-1)의 로그를 미리 띄워둡니다.
    kubectl logs -f redis-1 -c sentinel
  • 마스터 죽이기:
    #Bash
    kubectl delete pod redis-0
  • 로그 관찰:
    +sdown master: "마스터 응답 없음!"
    +odown master: "다수결로 마스터 사망 확정!"
    +failover-state-select-slave: "새 대장 선출 시작"
    +switch-master: 이 메시지가 뜨면 성공입니다! 마스터가 다른 포드 IP로 바뀐 것을 볼 수 있습니다.

문제 및 해결

  1. 해당 파일을 기반으로 실행시 configmap.yaml 파일 내부에 사용되는 sentinel의 설정파일중 초기에 서비스의 이름을 가지고 마스터를 모니터링 하는 부분에서 자꾸 오류가 발생.
  2. pod 내부에 존재하는 sentinel의 컨테이너를 확인
    kubectl logs redis-0 -c sentinel
  3. 오류 발생 로그 확인.
    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.
  4. sentinel에서 호스트이름 확인 기능이 기본적으로 비활성화 되어있음.
    configmap.yaml을 통해 sentinel resolve-hostnames yes 옵션 활성화.
    https://stackoverflow.com/questions/57464443/redis-sentinel-throws-error-cant-resolve-master-instance-hostname
  5. 이후 정상적으로 pod가 뜨는것을 확인.
profile
조금씩 앞으로

0개의 댓글