IL-0196 Palark · 2020-03-13 (게시일)kubernetes
Palark 는 고객 애플리케이션의 Redis 를 쿠버네티스 안에서 Spotahome 의 Redis Operator 로 운영했다. 이 오퍼레이터는 RedisFailover 커스텀 리소스를 바탕으로 Redis 설정 ConfigMap, Redis StatefulSet, Sentinel Deployment 를 만든다. 한 대형 웹사이트에서 Redis 를 인메모리 저장소, 캐시, 상태 저장소로 함께 쓰면서 가장 큰 데이터베이스의 .rdb 파일이 5 Gb 를 넘었다. 이 인스턴스는 디스크에 저장할 때 최대 약 16 Gb 의 RAM 을 썼고, 처음에는 레플리카를 더 띄울 노드 여유가 없어 레플리카 하나로 돌렸다.
데이터센터에 서버가 늘자 신뢰성을 높이려고 레플리카를 두 개로 늘리기로 했다. 파드가 너무 커서 장애가 나도 다른 노드로 옮겨 가기 어려웠다. 그래서 옮겨 갈 가능성을 높이려고 같은 변경에서 메모리 requests 와 limits 도 22 GB 에서 19 GB 로 낮췄다. 백업을 준비한 뒤 롤아웃했다.
새 인스턴스가 복제를 시작하자마자 ping 뿐인 레디니스 프로브를 통과했다. 리소스 값이 바뀌었으므로 롤링 업데이트는 데이터를 가진 유일한 파드를 재시작했다. Sentinel 은 마스터가 사라졌다고 보고 아직 데이터가 없는 레플리카를 마스터로 올렸다. 재시작한 원래 파드가 이 빈 마스터에 연결해 복제하면서 데이터가 모두 지워졌다. 서비스가 멈췄고 백업에서 복원했다.
Palark 는 오퍼레이터의 레디니스 프로브를 주된 원인으로 보고 이슈를 올렸고, 개발자들에게서 수정을 받아 시험을 마쳤다. 이 오퍼레이터에서는 레플리카가 하나인 구성이 여러 개인 구성보다 오히려 데이터 손실에 강했다. 새 Redis 노드가 생기는 동안 마스터가 어떤 이유로든 재시작되면 데이터가 사라진다. 복원 뒤 데이터를 분석해 보니 키 27402900개 가운데 16236021개가 패턴 하나에 몰려 있었고, 개발자들은 애플리케이션 설계 문제로 생긴 것으로 보이는 불필요한 키를 1800만 개 넘게 찾아냈다.
RedisFailover 리소스에 바뀐 설정을 적용하자 고객 웹사이트의 가장 큰 Redis 데이터베이스에서 데이터가 모두 사라졌다. 이 데이터베이스는 TTL 없이 영속 저장소로도 쓰였고, .rdb 스냅숏이 5 Gb 를 넘었다. 서비스가 멈췄고 백업에서 데이터를 복원해야 했다.
롤아웃 과정은 이랬다. StatefulSet 이 두 개로 늘었고 새 인스턴스가 슬레이브가 되어 복제를 시작했다. 곧바로 새 인스턴스가 레디니스 프로브를 통과했는데, 이 프로브는 ping 하나만 확인했다. 리소스가 바뀌었으므로 롤링 업데이트가 데이터를 가진 유일한 파드를 재시작했다.
Sentinel 은 마스터가 없다고 바로 판단하고 빈 레플리카를 마스터로 올렸다. 그때 마스터는 전체 재동기화에 필요한 첫 BGSAVE 도 거의 끝내지 못한 상태였다. 롤링 업데이트가 끝나자 원래 파드는 새로 마스터가 된 빈 인스턴스에 레플리카로 연결됐고, 복제가 곧바로 끝나면서 데이터가 모두 지워졌다.
원인 ? 소프트웨어 결함
–
핵심 인프라를 쿠버네티스 오퍼레이터로 관리할 때는 그 오퍼레이터가 얼마나 성숙하고 검증됐는지 따져 봐야 한다. 레플리카 수와 리소스 값을 한 번에 바꾸면 롤링 업데이트가 예상하지 못한 순서로 파드를 재시작할 수 있다. 레디니스 프로브가 ping 만 보면 복제가 끝나지 않은 빈 인스턴스도 준비됐다고 판단한다. Redis 클러스터를 바꾸기 전에는 반드시 dump.rdb 파일을 백업해야 한다.
같은 원인 · 공통 애플리케이션 데이터베이스
같은 원인 · 공통 애플리케이션 데이터베이스
같은 원인 · 공통 컨테이너 메모리 한도
같은 원인 · 공통 영구 볼륨과 스테이트풀셋