Amazon Web Services 한국 블로그

Sprinklr의 AWS 리전간 대용량 재해 복구 구축 사례

Sprinklr에서 통합된 고객 경험 관리 플랫폼을 통해 세계에서 가장 큰 브랜드 기업들의 마케팅, 광고, 조사, 관리, 상거래를 지원합니다. Facebook, Twitter, LinkedIn 및 전 세계 22개 기타 소셜 채널과 통합된 당사 플랫폼은 수천 개의 서버를 사용하고, 페타바이트 단위의 데이터를 조사하고, 매일 수십억 건의 트랜잭션을 처리합니다. Twitter 하나만 해도 하루에 몇 억 개의 트윗을 처리해야 합니다.

매일 처리하는 엄청난 데이터 양을 고려할 때 재해 복구(Disaster Recovery, DR)는 더없이 중요한 문제입니다. 자연재해나 인재가 발생하더라도 비즈니스 연속성이 보장되어야 합니다.

대부분의 기업은 DR 대신에 고가용성(HA)을 구현하여 서비스 가동 중지 상황에 대비합니다. HA 보장을 위한 서비스 폴백 메커니즘을 갖추고 있습니다. HA 모드로 실행되는 서비스는 여러 가용 영역에서 실행되지만 동일한 지리적 리전에 속하는 호스트가 처리합니다. 그러나 이러한 접근 방식은 리전 전체가 다운된 경우에 비즈니스의 정상적인 운영을 보장하지 않습니다. DR은 250마일 이상 떨어진 다른 리전에서 복구할 수 있다는 점에서 완전히 새로운 차원을 보여 줍니다. DR 구현은 액티브/패시브 모델로, 이는 여러 리전에서 중요성이 가장 덜한 서비스를 항상 실행하지만 필요할 때 인프라의 주요 부분이 시작 및 복원됨을 뜻합니다.

당면 과제

재해 발생 시 비즈니스 운영이 중단되는 위험을 감수하고 싶지 않습니다. 고객에 대한 약속의 일환으로 튼튼한 재해 복구 프로세스를 갖춰야 합니다. 이는 어느 비즈니스에나 매우 중요합니다. 예를 들어 허리케인 샌디가 기승을 부릴 때 미국 북동부 지역에 데이터 센터가 있는 일부 회사만이 홍수로 인해 오프라인 상태가 되었습니다. 당사 DR의 경우 복구 목표 시점(RPO)이 24시간입니다. 이는 복구할 데이터가 생성된 지 24시간이 지나지 않았음을 뜻합니다. 복구 목표 시간(RTO)은 DR이 선언된 시점으로부터 복원이 완료되기까지 걸리는 시간을 뜻하며, 당사의 경우 고객 SLA에 따라 6시간~24시간입니다. 테스트를 하면서 RTO를 4시간으로 정했습니다.

재해 복구(DR)를 위한 단계

규모 파악

Sprinklr의 리전 간 재해 복구 동기화

목표를 이해하려면 서비스 유형과 그 개수를 포함하여 현재의 작업 규모를 고려해야 합니다. MongoDB, Elasticsearch, SOLR, Mesos, RDS 등 광범위한 데이터/비데이터 서비스 목록이 있습니다. 따라서 서버가 수천 개에 이르는데, ELB는 거의 100개, route53 항목 약 4,000개, 1페타바이트 이상의 기본 데이터, 그리고 RDS 인스턴스 50개 이상이 있습니다. 이러한 서비스는 모두 복원 시점에 DR 리전에서 시작되어야 합니다.

목적 달성을 위해 사용자 지정 스크립트를 작성했는데, 이 스크립트는 주로 AWS API 호출을 통해 인스턴스를 시작하고, 스냅샷을 연결하고, elb 및 경로 항목을 생성합니다.

위 그림과 같이, 관련된 모든 백업은 복원을 위해 DR 리전으로 복사됩니다.

복사할 백업 유형은 크게 세 가지입니다.

  1. EBS 스냅샷: 사용자 지정 로직을 구축하여 사용 가능한 모든 백업과 그 진행 상황 및 완료 여부를 지능적으로 추적합니다.  AWS 한도를 넘지 않고 전체 스냅샷 사본을 얻고자 노력합니다.
  2. S3 스냅샷: cross s3 동기화를 사용하며, 이는 매우 효과적으로 작동합니다. 단 몇 분만에 기본 리전에서 DR 리전으로 데이터를 복사할 수 있습니다.
  3. RDS 스냅샷: AWS RDS CopyDBSnapshot API를 사용하여 RDS 스냅샷을 복사합니다.

DR을 위한 파일럿 라이트 설정

재해 복구 미리 설정빠른 시작을 위해, 재해 복구를 위한 게이트웨이를 얻으려면 몇 가지 서비스가 실행 중이어야 합니다. VPC, 서브넷, Route53 항목을 설정하는 것도 여기에 포함됩니다. 이를 위해 사용자 지정 도구를 구축했습니다. 비슷한 CIDR 구성과 서브넷 마스킹으로 VPC를 만들고, 경로 항목의 경우 새 서브넷이 생성될 때마다 DR 리전에도 자동으로 생성되도록 합니다. 이를 위해 AWS API 호출을 통해 기본 리전의 서브넷 정보를 파악하고, 서부 리전에 해당하는 서브넷을 만들었습니다.

없을 경우 복원을 시작하기 위한 항목을 얻을 수 없는 필수 서비스를 파악합니다. 이는 인증 서버(ldap/IPA, 있는 경우), 빌드 서버 또는 모니터링 서버일 수 있습니다. 이러한 서비스는 항상 실행 중이어야 합니다. 즉 시작 및 설정한 후 어떠한 예기치 못한 상황에서도 항상 DR 리전으로 항목을 가져올 수 있도록 이러한 서비스를 계속 실행함을 뜻합니다.

또한 종속된 AWS 서비스를 사용할 수 있어야 합니다. 예를 들어 S3 버킷을 DR 리전에서 사용할 수 있어야 하고 항상 기본 리전과 동기화해야 합니다. 많은 구성, 속성 파일, 바이너리가 S3에 있기 때문에 이 단계는 중요합니다. 애플리케이션이 계속 작동되도록 하려면 DR 리전에서 이를 사용할 수 있도록 해야 합니다. 이를 위해 S3 교차 리전 복제 기능을 사용합니다. 이는 객체를 빠르고 거의 동시에 동기화하여 놀라운 작업을 수행합니다.

재해 복구 용량 계획의 그림

용량 계획

이제 규모를 고려하여 DR의 필요 용량을 알아내야 합니다.

애플리케이션 관점에서 첫 단계는 DR 리전에서 필요한 구성을 사용할 수 있는지 확인하는 것입니다. 이때 필요한 구성이란 DB별로 다른 파라미터일 수도 있고 사용자 지정된 설정 관련 파라미터일 수도 있지만, 기본적으로 애플리케이션이 작동하는 데 필요한 모든 것을 말합니다. 위 그림과 같이, 복원하는 각 파트너가 당사 DB에 저장한 속성을 토대로 다양한 서비스의 필요 용량을 파악합니다. 예를 들어 파트너 Z는 ES 클러스터 70개, MongoDB 40개, RDS 30개, SOLR 20개가 필요합니다. 다음 단계에서는 모든 서비스를 종합적으로 고려하여 특이한 것을 찾아냅니다. 파트너 간에 클러스터 DB를 공유하므로, 최초의 필요 용량에 있던 클러스터 중 일부를 실제로 다른 파트너들도 공유할 수 있기 때문입니다. 이렇게 해서 최종적인 필요 용량을 파악하고, 이를 인스턴스 유형별로 나눕니다. 위 그림과 같이 Elasticsearch 등 서비스마다 인스턴스 유형이 서로 다릅니다. 마지막으로 해당 인스턴스 유형의 총 필요 용량을 파악하는 일이 남았습니다.

첫 번째 단계가 명확해지면 ELB 및 경로 항목을 몇 개나 생성해야 하는지 알아냅니다. AWS API로 얻은 ELB 및 경로 항목 정보에 대한 메타데이터를 보유하고 있습니다. 이 정보는 서부에 항상 준비되어 있습니다. 이 방법으로 필요 용량의 정확한 수를 알아내고, 인프라를 추정합니다. 여기에는 EC2, ELB 및 경로 항목을 위한 용량 계획도 포함됩니다.

원활한 복구를 위해서는 위 단계 모두 중요하고 서로 밀접하게 관련되어 있으며, 가급적 이를 자동화하는 것이 좋습니다. 우리는 AWS API 호출을 사용한 Perl로 사용자 지정 스크립트를 작성하여 이 모든 단계를 자동화했습니다.

재해 발생 시

우선 순위 정하기

존재하는 여러 서비스 중에 가장 중요한 서비스를 기준으로 시작의 우선 순위를 정하고 서비스의 EC2 인스턴스를 시작해야 합니다. 서비스를 세 가지 세트로 나누는 것이 좋습니다. 이는 핵심적인 서비스를 쉽게 시작할 수 있도록 하기 위한 중요한 결정입니다. 우리가 피하고자 하는 주요 방해 요소는 AWS의 용량 또는 한도 문제입니다.  서비스를 나누면 API 호출 수가 적어지며, AWS가 그 시점에 보유하고 있는 티어 1 서비스에 사용 가능한 인스턴스 유형을 모두 활용할 수 있습니다. 두 번째 세트와 세 번째 세트는 다음에 시도합니다. 이러한 접근 방법의 장점은 우선 AWS API 호출을 너무 많이 사용하지 않고, 복원이 충돌하지 않는다는 것입니다. 이를 위해 다시 사용해야 할 것 같은 AWS API 호출 출력을 캐시하는 캐싱 로직을 개발했습니다. 이를 통해 API 호출 수를 50% 줄일 수 있습니다. 두 번째는 사용 가능한 용량이 대부분 가장 핵심적인 서비스에 할당된다는 점입니다.

용량에 대비한 플랜 B

당장 재해가 발생하면 원하는 인스턴스를 마음대로 시작하지 못할 수 있으므로 실행 시간 인텔리전스를 구축할 필요가 있습니다.

우선 순위가 두 번째나 세 번째인 서비스를 할 때쯤이면 사용 가능한 용량을 다 써버렸을 수도 있습니다. 따라서, 용량 한도를 이미 늘렸습니다. 그러나 어떤 인스턴스 유형은 DR 시점에 AWS에서 사용하지 못할 수 있고, 이로 인해 전체 DR 작업이 위험에 빠질 가능성이 있습니다.

이러한 위험을 완화하기 위해 플랜 B를 수립했습니다. 플랜 B가 준비되고 자동화를 통해 인텔리전스를 구축하여 동일한 패밀리의 다른 인스턴스 유형을 시작합니다. 이 인텔리전스를 구축하기 위해 AWS CloudWatch를 사용합니다. AWS CloudWatch 측정치의 정보를 사용하여 기본 리전의 인스턴스 사용량을 분석합니다. 이를 통해 현재 인스턴스 패밀리 및 유형을 사용할 수 없는 경우에 사용할 수 있는 인스턴스 패밀리 및 유형을 알아낼 수 있습니다. 다시 말해 r3.xlarge 인스턴스 유형을 사용하는 특정 서비스를 예로 들면, CloudWatch 측정치 덕분에 이 서비스가 사용하고 시작해 볼 수 있는 다음 인스턴스 유형을 정하기 위한 모든 정보를 확인할 수 있습니다.

새 인스턴스 유형을 결정하고 나면 인스턴스 개수를 계산해야 합니다. 예를 들어 r3.2xlarge에서 r3.xlarge로 한 단계 아래로 가면 용량을 두 배로 늘려야 할 수 있으며, 한 단계 위로 가면 용량을 절반으로 줄여야 할 수 있습니다. 따라서 실행 시 이를 계산해야 합니다.

다른 AWS 서비스 복원 및 시작

ELB, Route 등 EC2 이외의 서비스 시작이 이제 트리거됩니다. 기본 리전의 S3에서 동기화된 메타데이터를 사용하여 이러한 서비스를 불러옵니다. 메타데이터 정보에는 이 서비스를 시작하는 데 필요한 정보가 들어 있습니다. ELB의 경우 ELB 유형(내부 또는 외부), 인증서 정보, 연결된 서브넷, 연결된 인스턴스입니다. 경로 항목의 경우 DNS 레코드 유형과 그 값입니다.

구성을 위해 EC2 인스턴스 정보가 필요할 수 있으므로 EC2를 시작한 후 이를 시작합니다. 예를 들어 경로 항목에는 EC2 인스턴스의 퍼블릭 IP 주소 정보가 필요할 수 있습니다.

애플리케이션 복원

위 단계를 실행했으면 절반은 온 것입니다. AWS에서 리소스를 가져왔고 애플리케이션 요구 사항에 따라 이를 구성할 수 있었기 때문입니다. AWS에서 얻고자 하는 필요 용량이 대부분 처리되었습니다. 나머지는 주로 애플리케이션 및 로직과 관련이 있습니다. 코드베이스를 사용할 수 있게 준비해 두는 것과 필요 시 DR 리전에 바로 빌드를 배포할 수 있도록 하는 것도 여기에 포함됩니다.

직면한 문제 및 수정

위 모델을 구현한 후 API 호출과 관련된 몇 가지 문제에 직면했습니다. 복원 규모로 인해 엄청난 수의 API 호출이 발생했고, AWS에서는 이를 조정했습니다. API에서 보내는 막대한 정보를 캐시하기 위해 인텔리전트 캐싱 시스템을 개발했습니다. 그 결과 AWS API 호출이 처음의 4분의 1로 줄었습니다.

이 블로그 게시물에서 DR 프로세스의 계획 방식에 대한 아이디어를 얻으시기 바랍니다. DR 계획을 수립하고 주기적으로 테스트하는 것은 자연재해나 인재 발생 시 비즈니스 운영이 중단되지 않도록 하는 데 매우 중요합니다. 자세히 알아보려면 Sprinklr 웹 사이트를 방문하십시오.

이 글은 소셜 미디어 통합 관리 서비스인 Sprinklr의 책임 설계자인Senthilkumar Ramaswamy와 DevOps 책임 엔지니어 Rakesh Pillai가 작성한 AWS Startup 블로그의 Large scale disaster recovery using AWS regions의 한국어 번역입니다.