이 글과 관련된 다른 글 보기
- CockroachDB in Production - CockroachDB에 대한 소개와 킹덤에서 CockroachDB를 사용한 이유 설명
- 쿠키런: 킹덤 데이터베이스 스토리지 레이어 복원기 - 엔지니어 관점 기록한 개괄적인 장애 대응 과정과 회고
- CTO가 커리어를 걸고 비트 레벨까지 내려가서 DB를 해킹했던 이야기 - CockroachDB의 소스코드를 참고하며 바이너리 파일로부터 데이터를 복구한 이야기
- 입사 첫날에 36시간 점검 경험하기 - 신규입사자의 관점에서 서술된 장애 대응 기록
- 쿠키런: 킹덤 AWS AZ 장애 아웃라인 - AWS AZ 장애로부터 서비스를 복구한 이야기
- 쿠키런: 킹덤 길드 업데이트 이후 서비스 이슈 되돌아보기 - 쿠키런: 킹덤에 길드 기능이 추가된 이후 발생한 서비스 이슈 회고
안녕하세요, 저는 데브시스터즈 서비스기술그룹 인프라셀에서 데브옵스 엔지니어로 일하고 있는 이창원입니다. 저희 팀은 데브시스터즈에서 제공하고 있는 모든 게임의 Ops와 기술적 결정에 깊게 관여하고 있습니다. 작년 저희 팀의 가장 큰 미션은 쿠키런: 킹덤을 런칭하고 안정적으로 운영하는 체계를 구축하는 것이었는데요. 당시 어떤 과정을 거쳐 쿠키런: 킹덤이 여러분께 전달되었지를 공유드리고, 이어지는 글들에서 엔지니어로서 특별히 기억에 남는 주요 사건들에 대해 전해드리고자 합니다.
이 글의 내용은 박새미님과 NDC22에서 공동 발표한 쿠키런: 킹덤, 총 56시간의 긴급 점검 회고 - 그때 그 명검은 왜 뽑아야 했는가 세션에서 다뤄진 바 있습니다. 다만, 아무래도 발표는 시간 제한을 고려해야 하는 사정이 있다보니 자세한 정보를 담지 못했다는 아쉬움이 남아 글의 형식으로 다시 한 번 풀게 되었습니다. 보다 생동감 있는 짧은(?) 버전으로 일련의 이야기를 접하고자 하는 분들은 발표 영상을 보시는 것을 권해드립니다.
Step 1. 기술환경질의서: 게임 스튜디오와의 첫 소통
데브시스터즈 퍼블리싱을 결정하면 가장 먼저 “기술환경질의서”를 바탕으로 게임 스튜디오에서 선택한 기술스택과 아키텍쳐를 리뷰하게 됩니다. 이 때가 개발 스튜디오의 기술적 실무진들과 게임 Ops를 주로 담당하는 저희 팀이 공식적으로 대면하는 첫 자리입니다. 게임의 기술 스택에 대해서도 이야기를 나누고, 각각의 컴포넌트와 아키텍쳐를 살펴보며 운영 관점에서 취약한 구조 또는 최적화할 여지는 없는지 Scalability와 Resiliency 관점에서 면밀히 살펴보고 개선점이 있다면 함께 보완합니다.
쿠키런: 킹덤 프로젝트의 기술질의서를 바탕으로 데브옵스 조직인 저희 인프라셀에서 파악한 리스크 포인트는 크게 두 가지였습니다. 첫번째는 팀에서 처음 운영해보는 Stateful 서버라는 것입니다. 이 당시의 인프라셀은 이미 쿠키런 For Kakao, 쿠키런: 오븐브레이크, 쿠키워즈, 쿠키런: 퍼즐 월드, 그리고 파티파티 데코플레이까지 총 5개의 모바일 게임에 대한 런칭 경험을 보유한 팀이었습니다. 그러나 이 게임들은 모두 Stateless 서버구조를 차용하였기 때문에 여기서 쌓은 노하우를 쿠키런: 킹덤 런칭에 그대로 적용하기에는 무리가 있었습니다. 저희 팀에서는 이 질의서를 바탕으로 스튜디오 킹덤의 서버 개발자들과 지속적으로 교류하며 Stateful 서버 구조, Akka 클러스터에 대한 이해도를 높였습니다. 또한 클라우드 환경에서 Stateful 서버를 운영하기 위해 필요한 제반 기술들을 연구하여 준비해두었습니다.
두번째 리스크 포인트는 데브시스터즈에서 기존까지 사용해본 적 없었던 새로운 데이터베이스인 CockroachDB를 쿠키런 킹덤에서 사용하였 다는 것입니다. 쿠키런: 킹덤에서 채택한 CockroachDB는 전통적인 RDBMS와 NoSQL의 장점을 접목한 분산 NewSQL 데이터베이스로, 데브시스터즈에서 사용하던 Couchbase, MySQL 등과는 완전히 다른 특성을 가지고 있습니다. 게임 서비스에서 데이터베이스는 사용자의 추억과 노력이 담겨 있으므로 당연히 가장 안정적이어야 하며, 팀의 경험을 바탕으로 가장 보수적으로 접근하는 것이 일반적입니다. 새로운 데이터베이스의 안정성을 담보하기 위해 데브옵스 엔지니어들은 CockroachDB의 설계와 동작에 초점을 두어 심도 깊은 스터디를 진행했고, 이를 바탕으로 클라우드 환경에서 Cloud-Native 철학과도 맞는 운영 방법을 고안하였습니다.
이 시리즈물은 CockroachDB와 깊은 연관이 있는데, 앞으로의 이야기를 이해하시는데 도움이 되게끔 당시 스터디했던 자료를 엮어 기술블로그 글로 작성해 두었습니다. 데브시스터즈가 CockroachDB를 선택하게 된 과정에 대해 궁금하시다면 이 글(CockroachDB in Production)을 읽으시는 것을 권해드립니다.
Step 2. 여러 개의 게임을 안정적으로 서비스하기: Kubernetes 인프라 구축의 여정
게임 스튜디오에서 희망하는 아키텍쳐에 대해 공유를 받았다면, 그 다음에 풀어야 할 숙제는 이를 어떤 추상화 단계에서 구축할 것인지 결정하는 일입니다. 데브시스터즈에서는 2019년에 이미 향후 출시되는 모든 게임을 Kubernetes 환경에서 운영하기로 결정했습니다. 이러한 결정의 배경에는 2014년 처음 Kubernetes R&D를 시작하여 2016년부터 게임 개발용 플랫폼으로 지속적으로 사용해오고 있던 경험이 크게 뒷받침되었다고 할 수 있는데요. 게임을 퍼블리싱하는 입장에서 Kubernetes를 사용하면 다양한 아키텍쳐와 컴포넌트를 가진 여러 개의 게임을 비슷한 방식으로 배포하고 운영할 수 있는 장점이 있습니다. 지금 시점에서야 Kubernetes를 프로덕션 서비스에 활용하고 있는 사례들이 많이 있지만, 그 당시에는 아직 Kubernetes의 안정성에 대해 의심스러운 눈길이 많았습니다. 이 부분을 검증하기 위해 저희는 AWS EC2 인스턴스 기반 아키텍쳐로 짜여져 잘 운영 중이던 쿠키런 for Kakao를 2019년 Kubernetes 환경으로 이전하였습니다. 결과적으로 모든 컴포넌트를 최소한의 영향으로 이전하는데 성공하여 인프라 운영에 필요한 기본적인 구성을 EC2와 동일한 안정성 수준에서 Kubernetes 위에서도 구성할 수 있다는 사실을 확인했습니다.
이 경험을 바탕으로 2020년 1월에는 쿠키런: 퍼즐월드(당시 안녕! 용감한 쿠키들)를 런칭했습니다. 저희에게 쿠키런: 퍼즐월드는 인프라 컴포넌트와 배포 방법을 선택할 때부터 Kubernetes 환경을 고려한 최초의 프로젝트로써 일종의 De facto 패턴을 정립한 것에 의의가 있습니다. 기존에는 AWS EC2과 Route53, LoadBalancer를 사용하였다면 Kubernetes 리소스와 externalDNS, Envoy, Istio를 사용하는 식으로 패러다임이 달라졌고, 배포 방법의 경우 과거에는 Terraform과 Spinnaker를 사용하였다면 그에 더해 Helm과 ArgoCD를 추가로 사용하여 Kubernetes 환경에 보다 적합한 방향으로 확장하였습니다. 또 모니터링 관점에서 도 Kubernetes 클러스터 내부에서 발생하는 메트릭 역시 추적이 필요했기에 Prometheus와 Thanos를 도입했습니다. 데브시스터즈의 프로덕션 Kubernetes 사용을 향한 여정과 그 과정에 풀어야 했던 고민들은 저희 팀 용찬호님께서 NDC21에서 발표한 게임 서버를 품은 쿠버네티스 발표에 보다 자세히 담겨 있습니다.
쿠키런: 킹덤은 2021년 1월에 런칭되었으므로 안녕! 용감한 쿠키들 런칭 이후로 딱 1년 간의 텀이 있었습니다. 사업적 관점에서도 쿠키런: 킹덤은 안녕! 용감한 쿠키들보다 더 넓은 지역의 더 많은 유저들에게 다가가고자 하였기 때문에 저희가 추가적으로 신경써야 할 부분도 많아졌습니다. 더 넓어진 서비스 지역을 고려하여 AWS Global Accelerator를 도입하여 Istio Service Mesh와 연결하기도 하였고, 더 커진 서비스 규모에 발맞추어 Kubernetes 워커 그룹을 구성할 때 Multi-AZ를 필수적으로 활용하기도 하였습니다. 이 기간 인프라셀에서 진행한 업무는 한 마디로 팀의 내실을 다지며 다룰 수 있는 인프라 컴포넌트를 체계적으로 확장하는 작업이었다고 요약할 수 있겠습니다.
Step 3. 터지지 않는 서비스 인프라 구축하기: 적절한 예측과 부하 테스트
이제 남은 작업은 어떠한 규모의 트래픽이 들어와도 터지지 않는 서비스 인프라를 구축하는 일입니다. 앞선 절차에서 기술환경질의서를 통해 인프라 규모가 확장될 때 문제가 될 수 있는 부분들을 체크하여 개선해두었으므로 사실 비용을 최대한 끌어다 쓰면 터지지 않는 인프라를 구축할 수는 있을 것입니다. 하지만 오버프로비저닝 된 서버가 일하지 않고 있는 모습을 보는 것은 효율을 중시하는 한 명의 엔지니어로서 눈 뜨고 볼 수 없는 일입니다. 즉 너무 많지도, 너무 적지도 않은 규모의 인프라를 구축해 비용의 낭비를 최대한 줄이면서 안정적인 인프라를 구축하는 것이 중요합니다. 사용자 경험에는 영향을 주지 않으면서 서버는 효율적으로 일하는 규모의 인프라를 산정하기 위해서는 두 가지 정보가 필요한데요, 바로 사용자가 게임 내에서 여러 가지 활동을 할 때 우리 서버에 어느 정도의 부하가 발생하는지 파악하는 일과 우리 유저의 규모가 어느 정도일지에 대한 예상치입니다. 두 가지 모두 실제 서비스를 시작하기 전에는 제대로 알기 어렵지만 역설적으로 비용 효율적으로 안정적인 서비스를 제공하기 위해서는 정식 서비스를 시작하기 전에 반드시 알아야 합니다. 따라서 과거의 경험과 현재의 상황을 바탕으로 하여 적절히 예측할 수 밖에 없었습니다.
마침 런칭 인프라 규모를 산정하려고 고민할 즈음 전사 플레이 테스트를 진행하게 되었습니다. 이 테스트의 목적은 초기 경험에 대한 피드백을 수집하고 밸런스 수치를 최종 확정하기 위함이었는데요. 저희에게는 인프라에 발생하는 부하 패턴을 관측할 수 있는 소중한 기회였습니다. 사용자층에 따라 선호하는 게임 플레이 패턴이 다양할 수 있는데, 데브시스터즈의 전사 구성원이라면 그래도 어느 정도 평 균성을 가져갈 수 있는 집단이기도 하고요.
저희는 전사 테스트 기간 동안 수집한 데이터를 시간별 window로 나누어, 특정 시간에 발생한 총 요청 수와 활성 사용자(AU)를 추출하였습니다. window의 크기를 충분히 작게 선택하면 동시 접속자(CCU)가 되겠지만, 테스트 유저 수의 모수가 충분히 크지는 않으므로 적절한 대표값을 취해 단위 사용자가 발생시키는 대략적인 초당 요청 수를 근사하였습니다. 이 값은 게임의 특성에 따라, 또는 사용자의 플레이 패턴에 따라 크게 달라질 수 있는데, 아주 대략적으로 우리 게임을 플레이하는 유저층의 특성을 정의했다고도 할 수 있겠습니다. 사용자의 요청 중에는 으레 무거운 요청도 있고, 가벼운 요청도 있으므로 그렇게 단순하게 근사하는 것은 어렵지 않느냐고 궁금증을 가지실 수도 있는데요. 쿠키런: 킹덤은 다행히도 이벤트 소싱 패턴을 사용하였기 때문에 대부분의 요청에 발생하는 오버헤드가 평이한 편이어서 많은 계산을 단순화해도 큰 문제가 없었습니다. (이벤트 소싱과 쿠키런: 킹덤의 아키텍쳐와 관련된 내용은 권태국님의 NDC21 발표 〈쿠키런: 킹덤〉 서버 아키텍처 뜯어먹기!를 참고해주세요.)
시기적절한 사내 테스트를 통해 서버에 발생할 부하 패턴을 파악할 수 있었으니 이제 남은 일은 사용자의 규모를 예측하는 일입니다. 여기에는 마케팅 목표와 사전예약자 모객 현황을 모니터링하며 다소 감각적으로 설정하였습니다. 또 이 숫자는 기대와 현실 그 사이 어딘가에 존재는 목표치에 가까우므로 만일에 대비해 2~3배의 충분한 버퍼를 두 었습니다. 이제 단위 사용자에 대한 초당 요청 수(RPS)를 근사해내었고 목표로 하는 사용자 규모 또한 예측하였으므로 이 두 숫자를 곱하면 목표 RPS를 설정할 수 있습니다. 물론 이 과정이 수학적으로 엄밀하다고 말할 수는 없겠지만, 그래도 인프라 규모를 산정하기 위한 어느 정도의 기준치를 설정하였으니 소기의 목적은 충분히 달성했습니다. 남은 일은 실제로 쿠키런: 킹덤 아키텍쳐의 각 컴포넌트를 성능적으로 고려하여 이 목표 RPS를 문제 없이 소화하면서 비용 측면에서 가장 효율적인 인스턴스 타입과 사이즈의 조합을 찾는 일이고, 이 조합을 확실하게 검증하기 위해서는 부하 테스트가 필요합니다.
기록을 찾아보니 가장 최선의 조합을 찾기 위해서 인프라셀에서는 총 79회의 부하 테스트를 진행하였습니다. 부하 테스트 스크립트를 작성하여 Load Injector를 만들었는데, 최종적으로 목표로 설정된 부하 수준은 단일 머신에서 물리적으로 만들어낼 수 있는 한계를 넘어서는 수준이었기 때문에 별도 Kubernetes 클러스터에서 fleet을 구성해 부하를 발생시켰습니다. 과학적 방법에 따라 같은 테스트를 조건만 바꾸어가며 개선여부를 검증하는 작업인지라 엔지니어의 손과 시간이 많이 소요되는 고된 작업이었지만, 안정적인 서비스를 효율적으로 제공해야 한다는 엔지니어의 사명의식으로 작업에 매진하였고 결국 만족할 수 있는 검증된 결과를 얻어내었습니다.
런칭을 준비하며 야심차게 준비하였지만 일정 상의 이유로 진행하지 못한 작업으로는 서비스 공방전이 있습니다. 서비스 공방전이란 어떤 시스템이나 프로세스의 실패 사례를 가장하는 작업으로, AWS GameDay에서 모티브를 얻어 기획하였습니다. 유저들을 대상으로 하는 실제 서비스를 개시하기 전에 모의 서비스를 운영하며, 공격 측에서는 실제로 일어날 법한 여러 장애 시나리오를 준비하여 발생시키고, 방어 측에서는 이러한 장애 상황이 서비스에 영향을 미치는지 확인하며 필요한 경우 서비스 장애를 복구하는 연습을 하는 것이 의도였습니다. 서비스 장애의 원인은 매우 다양하고, 복구 과정에는 생각보다 많고 다양한 직군에 속한 사람들의 협업이 필요합니다. 마치 우리가 재난 대피 훈련을 하듯, 뜻밖의 상황을 마주했을 때 각자 맡은 역할에 따라 어떤 행동을 해야하는지 경험을 통해 체득하고 체계를 잡아나가는 과정...으로 의도했습니다만 어쩄든 실제로 진행하지 못해 아쉬움이 남습니다. 언젠가 다음 서비스를 런칭할 때는 서비스 공방전을 진행해본 소회 또한 공유드릴 수 있으면 좋겠습니다.
Final Step. 대망의 런칭과 모니터링
바쁘게 준비하였던 대망의 런칭일은 하루가 다르게 다가왔고, 2021년 1월 21일 쿠키런: 킹덤을 드디어 유저 분들께 선보일 수 있게 되었습니다. 지금까지도 이미 과할 정도로 열심히 일했지만 사실 런칭 이후에도 데브옵스 엔지니어들은 긴장을 풀 수 없습니다. 열심히 준비했음에도 문제는 얼마든지 발생할 수 있고, 만에 하나라도 무언가 문제가 생긴다면 최대한 빠르게 해결할 수 있어야 하니까요. 일반적으로 게임은 그 특성상 평일보다 주말에, 낮 시간대 보다 저녁 시간대에 활성 사용자 수가 더 많습니다. 또, 쿠키런: 킹덤은 게임 설계 상 소원나무와 같이 컨텐츠 일간 보상 획득량 제한이 해제되는 자정에 평소의 2~3배에 달하는 피크가 발생합니다. 따라서 저희는 런칭 후 첫 주말을 보내며 늦은 시간까지도 미리 구성해 둔 모니터링 대시보드를 살피며 리소스 사용량 등 주요 지표에 이상이 없는지 관찰하고 있었습니다.
앞서 들인 여러 노력 덕분인지 런칭 후 첫 주말까지도 쿠키런: 킹덤은 안정적으로 순항하고 있었습니다. 또 인프라의 주요 리소스 사용량도 정확히 설계한 범위에서 머무르는 것을 확인할 수 있었는데, 치밀하게 계산하고 공들여 테스트한 결과가 맞아떨어져 뿌듯했던 기억이 납니다. 어쨌든 이런 일도 있을 수 있다고 사전에 예상하기도 했었고 뭐가 됐든 숫자가 맞으니 기분은 좋았습니다.
이렇게 좋은 경험만 남은 런칭 회고가 되었다면 좋았으련만, 현실은 그렇지 않았습니다. 런칭 후 첫 72시간 동안 유저 수가 단조증가 하고 있었는데요. 서비스 관점에서는 당연히 너무 좋은 일이지만, Ops 관점에서 저희는 두려움에 떨고 있었습니다. 정상적인 경우라면 데이터베이스 스토리지 사용량이 일정 범위에서 안정화되어야 하는데, 저희가 상정한 수치를 한참 지났음에도 추세에 꺾임 없이 증가하고 있었기 때문입니다. 주말 동안의 상승추세를 월요일 출근시간에 그대로 적용하여 계산해보니 데이터베이스 용량이 한계치에 다다를 때까지 약 36시간이 남아있는 것으로 계산되었다는 복선과 함께 쿠키런: 킹덤의 런칭을 준비했던 이야기는 마무리하도록 하겠습니다.