쿠버네티스(Kubernetes) 환경에서 Redis 구축 가이드 ③


  레디스 구축 준비  

☸️ Redis Docker 이미지 준비 방법 (온라인 vs 폐쇄망)

1) 인터넷 연결 환경 (Online)

쿠버네티스 매니페스트(YAML) 내에 'image: redis:8.8.2'을 명시하고 'imagePullPolicy: IfNotPresent'를 주면 자동으로 Docker Hub에서 최신 이미지를 다운로드합니다.

2) 폐쇄망 환경 (Air-Gapped) - Rocky Linux 9.5 적용 방식

외부 인터넷 접속이 불가능한 폐쇄망 서버에서는 이미지 패키징 및 K3s 수동 로딩 작업을 수행해야 합니다.

  • [1단계] 인터넷 가능 PC/서버에서 이미지 추출
    # Docker를 이용하여 저장
    $ docker pull redis:8.8.2
    $ docker save -o redis-8.8.2.tar redis:8.8.2
  • [2단계] 폐쇄망 Rocky Linux 9.5 서버로 파일 이관 및 K3s 이미지 로드
    # 방법 A: k3s ctr(containerd CLI) 이용 직접 임포트 (추천)
    $ sudo k3s ctr images import redis-8.8.2.tar
    # 방법 B: K3s 자동 에이전트 이미지 디렉토리에 복사
    $ cp redis-8.8.2.tar /var/lib/rancher/k3s/agent/images/
  • ⚠️ 주의: StatefulSet YAML 파일 작성 시 'imagePullPolicy: IfNotPresent'로 설정하여, 쿠버네티스가 외부 인터넷으로 이미지를 다시 당겨오려다 실패하는 오류('ErrImagePull')를 방지해야 합니다.

구축 및 테스트 환경 명세

본 가이드 시리즈의 모든 테스트는 아래 사양의 환경에서 실증 검증되었습니다.

  • OS: Rocky Linux 9.5 (Blue Onyx) - 64bit
  • Kubernetes: K3s (v1.x, CNCF Certified Lightweight Kubernetes)
  • Redis Version: Redis 8.8.2 (Latest Open Source Release)
  • StorageClass: local-path (K3s 내장 Persistent Volume)
  • Service Ports: Redis Port: 18504, Sentinel Port: 28504, Cluster Bus Port: 28504
  • Network: Headless Service Dynamic DNS Resolution

쿠버네티스 Redis 구성 및 테스트 목차

본 가이드는 3개의 세부 구성 페이지와 1개의 종합 결론 페이지로 이어집니다. 아래 링크를 통해 각 아키텍처별 구축 방법, YAML 설정, 그리고 실제 Failover 검증 로그를 확인하실 수 있습니다.

💻 Redis-Cluster (6pods) 구성 및 테스트

  • 개요: 3 Master + 3 Replica 구조의 고성능 샤딩 아키텍처.
  • 핵심 요소: StatefulSet + Headless Service 기반 구성, 'cluster-announce-hostname'을 이용한 IP 변동 대응, 'create-redis-cluster.sh' 자동화 스크립트 제공.
  • 🔗 [Redis-Cluster (6pods) 상세 구축 가이드 바로가기]

💻 Redis-Sentinel (6pods) 구성 및 테스트

  • 개요: Redis 전용 Pod 3개와 Sentinel 전용 Pod 3개를 완벽히 분리한 고가용성(HA) 구성.
  • 핵심 요소: 센티널 간 Pub/Sub 대화를 통한 자동 Failover, 'replica-priority' 제어를 통한 우선순위 기반 마스터 승격.
  • 🔗 [Redis-Sentinel (6pods) 상세 구축 가이드 바로가기]

💻 Redis-Sentinel Sidecar 패턴 (3pods) 구성 및 테스트

💻 Redis-Cluster 용 Java(Spring) App 구현/테스트

💻 Redis-Sentinel 용 Java(Spring) App 구현/테스트

💻 맺음말: 어느 아키텍처를 선택할 것인가?

⚠️ Spring(Java) 환경에서 반드시 주의해야 할 점(JVM DNS 캐싱)📍

여기서 레디스 개발자가 꼭 알고 계셔야 하는 아주 중요한 Java/Spring 특성이 하나 있습니다. Java Virtual Machine(JVM)은 성능 향상을 위해 한 번 조회한 DNS 결과를 기본적으로 일정 시간 동안 메모리에 캐싱(Caching)해 둡니다.

💥 발생 가능한 문제 시나리오

  • 1. 레디스/센티널 파드가 죽어서 재시작되어 IP가 '10.244.1.20' → '10.244.2.35'로 변경되었습니다.
  • 2. K8s CoreDNS는 새 IP('10.244.2.35')를 알고 있습니다.
  • 3. 하지만 Spring App의 JVM이 옛날 IP('10.244.1.20')를 계속 캐싱하고 있다면, CoreDNS에 물어보지도 않고 옛날 IP로 계속 접속을 시도하다가 커넥션 에러('UnknownHostException' 또는 'Connection Refused')가 터질 수 있습니다.

💡 해결 방법 (JVM DNS TTL 설정)

Spring App이 켜질 때 JVM의 DNS 캐시 유지 시간(TTL)을 짧게(예: 1초~3초) 설정해 주어야 합니다.
여기서는 1초로 설정했습니다. 1초면 너무 짧지 않나? 매초 다시 조회해서 설정하려면 JVM에 부하를 주는 것 아닌가?   이렇게 생각할 수도 있습니다. 하지만, 다음과 같이 총 장애복구(Failover) 시간을 고려했을 때 결코 짧지 않습니다.
① 레디스 자체 Failover 소요 시간: 'cluster-node-timeout'을 3초로 설정해도 4~5초 정도 걸립니다.
② Java(Spring Lettuce): Redis-Cluster 정보 업데이트 시간: 2초
③ JVM DNS 캐시 유지 시간을 10초 한다면 5초+2초+10초 = 17초 걸립니다.
17초 동안 명령을 처리하지 못한다는 것은 작은 문제가 아닙니다.   따라서 'JVM DNS 캐시 유지 시간'을 1초로 설정해서 총 8초 이내에 완전 복구해야 합니다.

  • Java 옵션(JVM 옵션) 추가(deployment.yaml): -Dsun.net.inetaddr.ttl=1 📍
    (DNS 조회 성공 결과를 1초만 캐싱하고 이후엔 CoreDNS에 다시 물어보라는 설정입니다.)
  • Spring App 시작 코드(Java)에 추가:
    java.security.Security.setProperty("networkaddress.cache.ttl", "1"); 📍


<< Kubernetes k3s ② K8s Redis-Cluster 준비 ① >>

Email 답글이 올라오면 이메일로 알려드리겠습니다.