▲ 데브시스터즈 박새미 리드(좌) 이창원 엔지니어(우)

  • 주제: 쿠키런: 킹덤, 총 56시간의 긴급 점검 회고 - 그때 그 명검은 왜 뽑아야 했는가
  • 강연자 : 이창원, 박새미 - 데브시스터즈 / Devsisters
  • 발표분야 : 프로그래밍 / 서버 엔지니어링
  • 권장 대상 : 서버 엔지니어, 데브옵스 엔지니어
  • 난이도 : 기본적인 사전지식 필요


  • [강연 주제] 쿠키런: 킹덤은 2021년 출시되어 많은 사랑을 받았지만, 안타깝게도 런칭 초창기 긴 시간에 걸친 임시점검을 진행하기도 했습니다. 이번 발표에서는 작년 초 도합 56시간 동안 점검을 진행했던 경험을 전해드리고자 하는데요. 긴급 점검에 들어가게 된 전후 배경, 해결 과정, 그리고 문제를 해결하며 얻은 교훈을 공유해드리겠습니다.

    정기점검, 임시점검, 긴급점검, 연장점검. 유저들 사이에서 흔히 온라인 게임 4대 명검이라 불리는 '점검'의 종류다. 개중 정기점검은 게임의 안정적인 운영 및 업데이트, 패치를 위해서 정해진 루틴이라는 인식이 자리잡았지만, 나머지 세 종류는 유저들의 루틴과 예상에서 벗어난 상태이니만큼 개발사에서도 어지간하면 사용하고 싶지 않은 검이기도 하다. 그러나 게임의 안정적인 운영을 위해서는 종종 뽑을 수밖에 없는 상황이 발생하곤 한다.

    지난 2021년 1월 출시된 쿠키런: 킹덤은 런칭 초기에 이러한 문제에 직면했다. 1월 25일 36시간, 2월 19일 20시간 점검 총 56시간의 점검은 커뮤니티뿐만 아니라 일부 매체에서 기사화되기도 했다. 데브시스터즈는 왜 어지간하면 뽑고 싶지 않은 긴급점검과 연장점검이라는 칼을 두 번이나 뽑아들었으며, 그때 내부에서는 어떤 일이 있었을까? 데브시스터즈의 박새미 리드와 이창원 엔지니어는 당시 문제의 원인과 대응 과정, 그리고 깨달은 점을 타임라인으로 정리해서 소개했다.




    ■ DB 용량 차는 속도가 예상보다 빨라지면서 발생한 1차 점검, 7TB 이상의 데이터를 이관하기까지

    ▲ 출시 전, 데브옵스 팀과 서버 개발팀은 안정적인 서비스를 위해 여러 조치를 취해뒀다

    강연에 앞서 쿠키런: 킹덤의 안정적인 서비스를 위해 데브시스터즈에서 취한 조치들이 일부 소개됐다. 데브시스터즈에서는 데이터베이스 사용자 데이터를 7중 레플리카로 복제해서 보관하고, 주기적으로 데이터베이스 백업을 진행한다. 또한 AWS 글로벌 액셀러레이터로 통신망 장애에 대응하고, 데이터베이스와 게임 서버 인프라에 필요한 워크로드를 예측한 뒤 3개의 IDC에 분산되어 구축한 서버 인프라에 배포하는 등 각종 조치를 취하고 있다. 그외에도 클라이언트-서버 실시간 분석 로그도 적재하는 등 최적화와 관련된 사항들이 적용되어있다.

    데브옵스팀은 서버 개발팀과 협업해 런칭 전까지 79회의 부하 테스트를 진행, 쿠키런: 킹덤의 워크로드에 적합한 인스턴스 타입과 사이즈를 찾아 선택, 조합했으며 아키텍쳐의 문제를 발견해 개선하는 사이클을 진행했다. 이러한 과정을 거쳐서 작년 1월 25일 쿠키런: 킹덤이 출시됐으며, 출시 당시 트래픽을 모두 소화하는 것에 성공했다. 상정한 것보다 훨씬 많은 유저가 유입됐음에도 부하 목표를 여유롭게 설정한 덕에 안정적으로 서비스를 이어나갈 수 있었으며, 매출에서도 호조를 보였다.

    ▲ 출시 후 호성적을 보이며 승승장구했으나

    ▲ 그래서 DB 용량 차는 속도가 예상보다 훨씬 빨라서 대응이 필요했다.

    런칭 직후 첫 주말이 보통은 서버 관리할 때 가장 이슈가 많이 불거지는 시기인 만큼, 데브시스터즈에서도 모니터링을 지속적으로 이어나갔다. 다행히 첫 주말은 이슈 없이 지나갔으나, 문제의 불씨는 남아있었다. 쿠키런 : 킹덤은 분산 환경에서 동작하는 SQL 데이터베이스인 CockroachDB를 채택했는데, 그 데이터베이스 스토리지가 늘어나는 속도가 생각보다 빨랐던 것이다. 개발팀에서는 DB 스토리지는 상정하지 않은 상태였으나, 주말 모니터링 중에 데이터베이스 용량이 차는 속도를 확인하고 월요일에 최우선 대응을 하기로 하고 전략을 세우기로 결정했다.

    월요일 출근 시점의 DB 스토리지 리스크를 파악한 결과, 36시간이면 Catastrophic Failure 상태에 도달한다는 계산이 나왔다. 유저가 인입되는 추세를 보면 보통 기울기가 꺾여야했지만, 쿠키런: 킹덤에서는 유저 수가 지속적으로 증가하다보니 이러한 예상도 맞을지 확신하기 어려웠다. 그래서 디스크 풀이 발생했을 때를 대비한 보험을 준비해둘 필요가 있었다.

    어쨌든 36시간 내로 조치하지 않으면 치명적 오류 발생이 확정이었던 만큼, 런칭 준비 및 모니터링으로 2주간 크런치 모드를 했던 엔지니어링팀이 대응에 나섰다. 그 과정에서 의도치 않게 Configuration 이슈가 발생, 클러스터에 비일관성이 발생해서 자동적으로 트랜잭션 처리가 중단됐다. 그로 인해 당일 오후 4시 52분, 긴급 점검에 돌입했다.

    ▲ 대응 중 의도치 않게 Configuration 이슈 발생, 결국 긴급 점검을 뽑을 수밖에 없었다

    박새미 리드는 당시 상황을 데이터가 있는데 클러스터가 데이터를 인식하지 않고 읽기를 거부한 상황이라고 요약 설명했다. 이를 해결하기 위해 Cockroach Labs에 노드에 들어있는 데이터 Storage Layer에서 데이터를 뽑을 수 있을지 문의했으나, 몇 주가 걸리고 성공할지 확신할 수 없다는 답변을 받았다. 그래서 작업 시간을 단축하면서도 문제를 해결할 수 있는 다른 방안을 찾아야만 했다.

    그러다가 Configuration 이슈의 영향을 받지 않은 노드 중 하나가 AWS Host Status Failure로 내려가버리는 돌발 상황까지 발생했다. 이런 상황에서 구 클러스터가 데이터를 읽기를 거부하는 상황인 만큼, 새 클러스터를 만들어서 데이터를 옮기자는 안이 나왔다. 바이너리 데이터를 CSV로 포팅해야 하는데, Shell Script에 Coackroch DB 커맨드를 조합하면 포팅이 가능하다는 걸 확인한 터라 이사를 시키면 된다는 결론이 나온 것이었다.



    문제는 바이너리 파일의 전체 규모가 약 7,577GB였고, 이를 CSV로 포팅하는 것만으로도 24시간이 걸린다는 점이었다. 그래서 CockroachDB가 오픈소스인 점을 활용, 소스 코드를 보고 직접 바이너리 커맨드를 커스터마이징하는 작업을 거쳤다.

    이튿날 오전 10시 30분, CockroachDB 소스 코드 수정이 완료되어 기존 대비 10배 빠른 crdb2csv 커스텀 빌드가 완성됐다. 이 빌드를 활용해 1시간 반만에 바이너리 데이터가 CSV로 포팅이 완료됐다. 그럼에도 처리해야 할 바이너리 규모가 너무 방대했던 터라 분산 처리 환경이 필요했다. 데브시스터즈에서는 도쿄 리전을 주로 사용했는데, 포팅 작업을 진행하면서 오후 3시 정도에 도쿄 리전에 있던 모든 r 계열 인스턴스를 소진한 상황이었다. 작업을 빨리 진행해야 하던 만큼, 이 문제는 기존에 사용하던 다른 인프라 일부까지 철거해가면서 리소스를 확보하는 것으로 조치를 취했다. 당시 r5.8xlarge 350대를 끌어썼는데, CPU로 환산하면 11,200코어에 메모리는 89,600BG 분량이다.

    그렇게 확보한 리소스로 포팅해서 백업된 데이터와 로그를 체크한 결과, 백업된 데이터가 기존 데이터가 100% 일치한다는 것을 확인할 수 있었다. 이를 기반으로 이튿날 오후 10시 2분부터 전사 대상 선행 테스트를 진행, 문제가 없다는 것을 재차 확인하고 점검 시작으로부터 31시간 45분이 지난 시점에서 점검 완료를 고려하게 됐다.

    ▲ 방대한 데이터를 옮기기 위해 여러 수단을 강구하고

    ▲ 이전 완료 후 검사까지 완료, 문제가 없다는 걸 확인하고 서버를 열었다

    이후 오후 11시 37분에 점검을 종료했으나, 이용자의 폭증으로 당시 1분당 약 70만 개의 API 콜이 발생하는 등 플랫폼 서버가 과부하되는 일이 발생했다. 자연히 DB에도 부하가 가서 플랫폼 로그인 서버에 DB 데드락이 발생하고, 결국 페일 오버를 수행할 수밖에 없었다. 플랫폼에서 대응하는 동안 데브옵스팀의 엔지니어들은 이사간 Cockroach DB 클러스터를 모니터링하고 있었는데, 전반적으로 상황이 좋지 못했다. 에러율이 높았고, 특히 DB가 정해진 시간 내에 요청을 처리하지 못하는 타임 아웃 에러가 많이 발생했었다. 뚜렷한 방법이 없어 모니터링만 하던 중, 새벽 2시 40분에 임계치를 넘어가게 되자 결국 2차 긴급 점검에 돌입하게 됐다.

    2차 긴급 점검에서는 두 번째 클러스터에서 발생한 상황을 참고해 최적화를 적용한 다음 새로운 클러스터를 준비, 데이터를 이사시키는 작업을 진행했다. 해당 작업에는 2시간이 소요됐으며, 데이터 이전 이후 DB 최적화에 좀 더 집중하는 과정을 거쳐 점검 시간 약 36시간 30분만인 3일차 오전 8시 반에 점검을 종료했다.

    ▲ 그러나 사용자 폭증으로 플랫폼 서버가 과부하가 발생, 결국 2차 점검에 돌입하고

    ▲ 문제 발생 후 약 36시간 30분만에 점검이 종료된다

    이용자가 폭증하는 상황에서 안정적인 데이터베이스 운영을 위한 작업을 진행했으나, 의도치 않은 이슈 발생으로 클러스터 동작이 중지되면서 발생한 첫 번째 이슈는 결국 기반이 된 CockroachDb의 소스 코드와 기술 문서를 총동원, 바이너리 파일을 새 클러스터로 빠르게 이전할 수 있는 방안을 찾아 100% 이전하는 것에 성공하면서 일단락됐다. 그 과정에서 트래픽 과부하 등 문제가 있었으나, 이 역시도 최적화와 수정을 거친 뒤 세 번째 클러스터로 이전 후 조치를 완료할 수 있었다.

    데브시스터즈에서는 점검이 끝난 뒤, DB 용량 추가 확보가 필요하다고 판단해 60대 규모의 클러스터로 확장했으며, 또 추가로 증설해서 현재는 총 90대의 DB로 운영 중이다. 아울러 Configuration 이슈가 발생하지 않도록 인프라 작업 프로세스를 개선, 명문화했다. 36시간 내에 해야 하는 작업이더라도 작업자가 화면을 쉐어해야 하고, 한 명 이상 관전자가 필요하도록 지침을 만들었다. 그리고 비상시에 사용할 접속자 대기열 서버도 마련했다.

    ▲ 현재는 DB 클러스터가 90대 규모로 확장됐다



    ■ 데이터센터 정전으로 발생한 2차 점검, 흑마법(?)까지 써서 DB를 복구하다

    ▲ 회식 후 뒷풀이 중에 날아온 한 통의 슬랙이 문제의 시작을 알리는 신호탄이었다고

    1차 장기 점검이 일단락 된지 3주 뒤, 데브시스터즈에서는 런칭 축하 및 장기 점검을 위로하기 위해 회식을 진행했다. 그러던 중 킹덤 DB 노드 한 대가 하드웨어 Failure로 내려갔다는 오류 메시지가 한 통 온 것을 시작으로 6대의 DB 노드가 내려가면서 급작스럽게 문제가 발생했다. 문제의 원인은 AWS 데이터 센터 도쿄 리전의 냉각 유닛이 정전으로 작동하지 않은 것이었다. 그로 인해 서버실 온도가 급격히 상승했고, 약 12분만에 쿠키런: 킹덤 DB 6대가 작동 불능이 되어버렸다.

    쿠키런: 킹덤은 CockroachDB를 쓰긴 하지만, 내부적으로는 key-value 스토어라 데이터가 일정한 바이너리 포맷으로 디스크에 저장이 되어있다. 이 데이터를 내부에서 적절한 크기로 쪼개어 Range 단위로 관리하는 방식이었다. 6대의 DB가 내려가면서 25000개의 Range 중 34개가 소실됐으며, 그 중 유저 데이터 관련 Range는 2개였다. 특히나 소실된 Range의 레플리카 7개 중 4개 이상이 그때 내려가버린 6대에 분포되어있어 문제가 컸다. 그래서 긴급 점검에 들어갈 수밖에 없었다.

    ▲ 원인은 AWS 데이터 센터 도쿄 리전의 냉각 유닛이 정전되면서 서버실 온도가 급상승, DB가 다운된 것이었다


    ▲ 원인을 파악한 뒤, 그 DB 안에 있던 데이터를 복구하기 위해 조치에 들어갔다

    점검 돌입과 함께 데이터 복구를 시도하는 한편, 일부에서는 노드에서 바이너리 데이터를 추출했다. 그러는 사이에 다른 팀에서는 복구한 데이터의 정합성을 어떻게 검사할 것인지 검사 계획을 수립했으며, 한 명이 AWS의 냉각 시스템 장애 해결 상황을 모니터링하고 공유하는 업무를 맡았다.

    이러한 과정을 거쳐 이튿날 오전 1시 56분에 AWS 데이터 센터 장애로 망가진 레플리카에서 유실된 데이터 추출이 일부 성공했다. 그러나 백업을 이용한 복구는 시간이 굉장히 오래 걸린다는 문제가 있었고, 이미 점검을 시작한지 8시간 30분이 지난 상황이었다. 그래서 극약처방을 내릴 수밖에 없었다.

    데브옵스팀은 CockroachDB의 소스코드를 살펴보던 중, unsafe-remove-dead-replica 명령을 발견했다. 해당 명령은 데이터를 복구하는 최후의 수단으로, 이걸로 데이터가 복구된다고 해도 그 데이터가 정합성이 맞다는 보장이 없었다. CockroachDB 엔지니어들의 주석에 따르면, 노드가 계속 죽어서 난리가 날 때 자신들이 보는 앞에서만 사용하라는 코드로 남긴 것이었다.

    ▲ 진행 속도가 아무리 해도 예상보다 느린 터라 비장의 수단을 강구하게 되고

    ▲ CockroachLabs 엔지니어들이 꼭 자기들 앞에서 쓰라고 명시한 unsafe-remove-dead-replica 명령어를 발견

    ▲ 그들의 감독 하에 명령어를 실행해 한 대는 복구하고 나머지 한 대는 커스텀빌드로 복구했다

    당시 점검 시작으로부터 12시간이 지난 상황이었는데, 결국 CockroachLabs의 서포트들과 줌으로 화면을 공유하면서 unsafe-remove-dead-replica를 사용하기로 결정됐다. 실행 결과 2개 중 1개의 Range가 복구에 성공했다. 복구하지 못한 Range 1개는 1차 점검 때와 동일하게 crdb2csv 커스텀 빌드를 활용, 복구하는 것에 끝내 성공해 점검 시작으로부터 17시간 뒤인 이튿날 오후 7시에 서버를 오픈했다.

    2차 점검 때는 데이터가 날아간 상황에서 유저 데이터를 100% 복구했으며, 오픈 후 1차 점검 때처럼 많은 트래픽이 몰렸으나 미리 스케일아웃을 해두어서 플랫폼, 서버, DB 모두 대응했다는 점에서 고무적이었다. 다만 데이터가 너무 커져서 복구 작업에 시간이 너무 오래 걸렸다는 문제가 남아있었다. 1차 때는 7TB 정도였다면, 2차 때는 10TB로 50% 이상 증가했기 때문이었다.

    2차 점검 이후 확인 결과 CockroachDB의 Locality 기능을 활용 못했던 점도 아쉬움으로 남았다. 해당 기능은 당시 발생했던 AWS 데이터센터 이슈 같은 일을 처리해줄 수 있는 기능이었는데, 런칭을 준비하는 과정에서 이러한 이슈를 상정하지 않고 우선순위를 낮게 설정했기 때문에 제대로 활용하지 못했던 것이다. 다만 서포트 과정에서 실행한 커맨드가 도움이 된 데다가. 문제 발생 즉시 엔지니어들이 모여있던 상황에서 빠르게 대처할 수 있기 때문에 대응도 빠르게 진행할 수 있어 심각한 상황에서도 조치가 가능했었다는 점은 다행이라고 평가했다.

    ▲ 아쉬운 점은 있었으나, 데이터가 소실된 상황에서 데이터를 100% 복구하고 점검 종료 후 이슈 대응도 성공했다

    이렇게 1, 2차에 걸친 56시간의 점검이 데브시스터즈에 어떤 것을 남겼을까? 두 개발자는 팀원들이 위기 상황에서 가져야 할 자세를 깨닫게 됐다고 설명했다. 고객을 위해 수단과 방법을 가리지 않고 포기하지 않으면, 어떻게든 방법이 있었고 극복할 수 있었기 때문이었다. 그리고 마치 한 바구니에 계란을 다 담지 말라는 것처럼 한 곳에 데이터를 다 담기보다는, 이곳저곳 분산저장해두는 것의 중요성을 깨달았다고 덧붙였다.

    또한 사고를 방지하고 관리하기 위한 문화와 프로세스, 그리고 장애를 효과적으로 해결하기 위한 조직 구조의 중요성도 강조했다. 데브시스터즈는 분석 인프라를 이미 갖춘 상태였고, 문제를 해결할 역량이 있는 개발자들이 같은 조직에 속해있어 문제 대응과 관련한 커뮤니케이션이 빠르게 진행됐다.

    해당 사건 이후 1년이 지난 지금의 쿠키런: 킹덤은 어떨까? 이창원 엔지니어는 런칭 후 1종류를 제외하고 같은 장애가 반복되는 일은 없었다고 설명했다. 고객이 공급업체로부터 기대하는 서비스 수준을 나타내는 SLA 지표는 연장 점검까지는 95%였으나, 2022년 2월 3일부터 강연 녹화 시점까지는 100% 가동률을 보여주고 있다.

    데브시스터즈는 두 차례의 연장점검으로 글로벌 규모의 인프라 운영에 대한 노하우가 생겼고, 이론상 완벽한 설계를 해도 언제든 무너질 수 있고 확률이 아무리 낮다고 해도 문제가 발생할 수 있다는 걸 파악했다. 두 개발자는 마지막으로 책임자를 찾아서 질책하기보다는, 문제 해결에 집중해서 최선을 다하는 자세가 DB가 날아가고 Catastrophic Failure 직전에 클러스터 안의 데이터를 통째로 이전해야 하는 심각한 문제가 발생해도 조치할 수 있었던 비결이라고 덧붙였다.