[CassandraDB] 무중단 CassandraDB 클러스터 이전 방법 (멀티 데이터센터 구성)
회사에서 직접 운영하고 있는 Cassandra DB 클러스터 이관 등의 작업을 진행하였는데, 관련 방법들에 대해서 정리한 내용입니다.
참고로, 팀 내에서 운영하고 있는 여러 플랫폼의 메인 저장소로 CassandraDB를 운영하고 있으며, CassandraDB의 경우 별도의 DBA가 없어 팀 내에서 직접 운영하고 있습니다.
카산드라 클러스터 이관을 위해서 멀티 데이터센터를 구축해서 이전하는 방법으로 클러스터를 이전하였습니다.
- 아래 예시들은 기존 데이터 센터를 dc1, 신규 데이터 센터를 dc2로 가정하고 작성되어 있는 점 참고 바랍니다.
이관 전 사전 체크 사항
Cassandra DB 설정
Snitch
- SimpleSnitch인 경우 단일 DataCenter를 위한 Snitch로, 멀티 데이터 센터 사용을 위해선 GossipingPropertyFileSnitch 등의 전략으로 사용하고 있어야 합니다. (아닌 경우 변경 작업이 필요합니다)
endpoint_snitch: GossipingPropertyFileSnitch
Replication Strategy
직접 생성하는 키스페이스들은 대부분 NetworkTopologyStrategy로 생성해서 사용하지만, CassandraDB에는 User-Keyspace (사용자가 직접 생성하는 키스페이스) 이외에 기본적으로 생성되어 있는 System Keyspace들이 있는데, Replication 전략이 SimpleStrategy로 되어 있어서, NetworkTopologyStrategy으로 변경이 필요합니다.
- System Keyspace에는 system_auth, system_distributed, system_trace 키스페이스가 존재합니다. (기본적으로 SimpleStrategy로 생성되어 있음)
- NetworkTopologyStrategy은 데이터 센터 별로 구분해서 토큰 링을 구성하는 한편, SimpleStrategy는 데이터 센터를 구분해서 토큰 링을 구상하지 않음.
- NetworkTopologyStrategy으로 키스페이스를 생성하는 것을 권장하지만, Cassandra에 기본적으로 생성되어 있는 System Keyspace 들에는 그렇지 않은 것들이 있어서 변경이 필요.
- 예를 들어서 (Cassandra 인증 & 권한을 사용하는 경우) system_auth 키스페이스에 대해서 기본적인 SimpleStrategy으로 설정하고, 신규 데이터 센터의 노드를 추가하면, 운 나쁘게 일부 토큰이 신규 데이터 센터의 범위에 속하게 되고, Consistency Level은 LOCAL(LOCAL-ONE or LOCAL-QUORUM)으로 설정되어 있어서, 인증 정보를 가져오지 못해, 전면 장애를 유발할 수 있으니 주의가 필요.
변경 방법
수행 방법 (cqlsh)
ALTER KEYSPACE system_auth WITH replication = {'class': 'NetworkTopologyStrategy', 'dc1': '3'};
ALTER KEYSPACE system_distributed WITH replication = {'class': 'NetworkTopologyStrategy', 'dc1': '3'};
ALTER KEYSPACE system_traces WITH replication = {'class': 'NetworkTopologyStrategy', 'dc1': '2'};
# 단순 예시로, 기존에 사용중이던 동일한 RF 수에 맞춰서 변경해야 합니다.
# ex) SimpleStrategy: 1 -> NetworkTopologyStrategy: 1
- 기존에 사용 중이던 동일한 RF 수와 동일하게, SimpleStrategy → NetworkTopologyStrategy로만 변경
롤백 방법
- 기존의 설정으로 다시 키스페이스 설정을 변경한다.
ALTER KEYSPACE system_auth WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 3}; # 단순 예시로, 기존 설정에 맞춰서 변경해야 합니다
애플리케이션 (Cassandra Driver) 설정
LoadBalancingPolicy & Consistency Level
애플리케이션(Client)에서 카산드라로의 (직접적인) 요청이 기존의 데이터센터로 가도록 설정해야 합니다.
- 만약 아직 데이터 복제가 되기 전에, 새로운 데이터 센터로 요청이 가게 된다면, 신규 데이터 센터에는 데이터가 없어 비정상적으로 처리될 수 있습니다.
이를 위해서는 Cassandra Driver의 LoadBalancingPolicy을 DCAwareRoundRobinPolicy로 설정되어 있어야 합니다.
- DCAwareRoundRobinPolicy는 Local Datacenter와 Remote Datacenter를 구분하여, Local 유형(Local ONE, Local QUORUM 등)의 Consistency Level을 사용하려면, DCAwareRoundRobinPolicy을 사용해야 합니다.
- 또한 Consistency Level은 Local 계열의 Consistency Level로 설정되어 있어야 합니다.
- ex) ONE -> LOCAL_ONE, QUORUM -> LOCAL_QUORUM 로의 변경이 필요함.
loadBalancingPolicy: DCAwareRoundRobinPolicy
consistency-level: LOCAL_QUORUM (or LOCAL_ONE)
local-datacenter: dc1 # 기존에 운영중인 데이터 센터
요약하면 위와 같이 설정되어 있어야 합니다.
위의 멀티 데이터 센터로의 설정을 위해서, 사전 조건들에 대해서 모두 확인되면 이관 시나리오를 진행할 수 있습니다.
이관 시나리오
1. 신규 데이터 센터의 신규 노드 투입
주의 할점은, 신규 노드들을 클러스터에 투입할때는 기존의 카산드라 버전과 동일해야 한다.
만약 카산드라 버전업이 필요한 경우, 클러스터 이관 전 or 후에 클러스터에 있는 노드들로 롤링 업데이트로 버전 업그레이드를 진행해야 한다.
신규 데이터 센터의 카산드라 설정 참고 내용...
cassandra.yaml
cluster_name: 'cluster-name' # 기존 데이터 센터와 동일한 클러스터 이름
seed_provider:
- class_name: org.apache.cassandra.locator.SimpleSeedProvider
parameters:
- seeds: 1.2.3.4,2.3.4.5,3.4.5.6,4.5.6.7 # Old Dc와 New DC 모두 넣는다
## 그외 설정은 카산드라 기본 설치와 동일하니 생략한다...
- 단 seed에 클러스터의 모든 노드를 넣는 것은 좋지 못하며, 데이터 센터별 2개 정도를 Seed Node로 지정하는 것이 적정하다.
cassandra-rackdc.properties
dc=dc2
rack=rack1
수행 방법
신규 데이터 센터로 설정된 카산드라를 실행해서, 클러스터에 투입한다.
(문제 발생시) 롤백 방법
nodetool decommission
- 카산드라 클러스터에서 현재 노드를 제외하는 방법.
2. Keyspace Replication Factor 설정 변경 (Dual Write)
먼저 신규로 들어오는 증분 데이터들에 대해서 다중 데이터센터로 복제될 수 있도록, Replication Factor 설정을 변경해줍니다.
다만 아래 Replication Factor 설정을 변경한다고 해서, 변경 전의 데이터들에 대해서도 복제가 이뤄지는 것은 아니고, Replication Factor 설정 변경 후의 증분 데이터에 대해서만 복제가 이뤄진다고 보시면 되겠습니다.
수행 방법
ALTER KEYSPACE system_auth WITH replication = {'class': 'NetworkTopologyStrategy', 'dc1': '1', 'dc2': '3'};
ALTER KEYSPACE system_distributed WITH replication = {'class': 'NetworkTopologyStrategy', 'dc1': '3', 'dc2': '3'};
ALTER KEYSPACE system_traces WITH replication = {'class': 'NetworkTopologyStrategy', 'dc1': '2', 'dc2': '3'};
ALTER KEYSPACE {{your_keyspace}} WITH replication = {'class': 'NetworkTopologyStrategy', 'dc1': '3', 'dc2': '3'};
(문제 발생시) 롤백 방법
- 이전 설정으로 키스페이스 설정을 변경합니다.
ALTER KEYSPACE system_auth WITH replication = {'class': 'NetworkTopologyStrategy', 'dc1': '1'};
ALTER KEYSPACE system_distributed WITH replication = {'class': 'NetworkTopologyStrategy', 'dc1': '3'};
ALTER KEYSPACE system_traces WITH replication = {'class': 'NetworkTopologyStrategy', 'dc1': '2'};
ALTER KEYSPACE {{your_keyspace}} WITH replication = {'class': 'NetworkTopologyStrategy', 'dc1': '3'};
3. Rebuild
Keyspace의 Replication Factor 설정을 양 데이터 센터에 복제되게 설정하였다면, 이제 (Replication Factor 변경) 이전의 전체 데이터들에 대해서 기존 데이터센터에서 신규 데이터센터로 복제가 되어야 하는데요. 이때 nodetool의 rebuild 명령을 통해서 복제할 수 있습니다.
(Repair와의 차이점은 Rebuild는 멀티 데이터 센터에의 일종의 bootstrap을 위한 명령이고, (Full) Repair의 경우에는 merkle tree를 구성해서 일관성이 깨진 데이터들에 대해서 맞추는 작업으로 Repair를 통해서도 데이터를 복제할 수 있지만, 부하가 더 쌥니다)
수행 방법
(신규로 추가된 데이터 센터의 각각 노드들에서 순차로 수행)
nodetool rebuild dc1 # 기존 데이터 센터를 지정해야 합니다
- rebuild를 실행한 신규 노드 이외에 기존 데이터 센터의 노드들에도 부하가 증가함으로, 한 번에 모든 노드에 대해서 rebuild 하기보다는 순차적으로 진행하는 것을 추천.
- (경험상 Disk IO 부하가 쌤… 부하가 가장 적은 시간대에 진행하는 것을 추천함..)
- 그 외에 데이터 양에 따라서 많은 시간이 소요될 수 있는 작업.. (이전의 데이터들을 모두 복제해야하니, 이 과정에 가장 깁니다)
(문제 발생 시) 중지 방법
nodetool -h drain
4. 애플리케이션 Cassandra Driver 설정 변경
4번 부터는 기존 데이터 센터를 유지하지 않고 제거(이전)하는 내용이며, 멀티 데이터센터로 운영해야하는 경우에는 애플리케이션 Consistency Level을 운영 정책에 맞춰서 설정하고, 5번 부터는 진행하지 않으시면 됩니다.
이제 기존에 기존의 데이터센터로 요청이 가게 해뒀던 설정을 신규 데이터 센터로 요청이 가도록 변경해줍니다.
cassandra endpoint 및 local-datacenter 설정 변경
- endpoint: 기존 노드들 -> 신규 노드들로 변경
- local-datacenter: dc2 (NEW DataCenter)
5. Keyspace Replication Factor 설정 변경 (Dual Write 제거)
데이터가 dc1, dc2 두 데이터 센터에 모두 복제되게 설정해두었었는데요.
dc1 -> dc2로의 복사가 모두 완료되고, 애플리케이션의 요청이 dc2를 바라보도록 변경하였으니 dc1로는 데이터가 복제되지 않도록 Replication Factor 설정을 변경해줍니다.
진행 전, 주의 사항
- 기존의 데이터센터로의 커넥션 및 요청이 없는 것을 확인한 후, 진행해야합니다!
수행 방법
ALTER KEYSPACE system_auth WITH replication = {'class': 'NetworkTopologyStrategy', 'dc2': '3'};
ALTER KEYSPACE system_distributed WITH replication = {'class': 'NetworkTopologyStrategy', 'dc2': '3'};
ALTER KEYSPACE system_traces WITH replication = {'class': 'NetworkTopologyStrategy', 'dc2': '3'};
ALTER KEYSPACE {{YOUR_KEYSPACE}} WITH replication = {'class': 'NetworkTopologyStrategy', 'dc2': '3'};
롤백 쿼리
ALTER KEYSPACE system_auth WITH replication = {'class': 'NetworkTopologyStrategy', 'dc1': '3', 'dc2': '3'};
ALTER KEYSPACE system_distributed WITH replication = {'class': 'NetworkTopologyStrategy', 'dc1': '3', 'dc2': '3'};
ALTER KEYSPACE system_traces WITH replication = {'class': 'NetworkTopologyStrategy', 'dc1': '2', 'dc2': '3'};
ALTER KEYSPACE {{YOUR_KEYSPACE}} WITH replication = {'class': 'NetworkTopologyStrategy', 'dc1': '3', 'dc2': '3'};
6. 기존 노드 서비스 제거
이제 복제본 듀얼라이트가 끊긴 이전의 데이터센터에 대해서 클러스터에서 제거하는 작업을 진행합니다.
수행 방법
(제거할 노드에서 실행)
nodetool decomission
decomission 명령은 실행한 노드의 데이터를 다른 노드로 리밸런싱한 후, 해당 노드를 클러스터에서 빼는 명령입니다.
참고로, 이미 애플리케이션의 트래픽이 신규 데이터 센터로 변경된 상태로, 제거할 노드 이외에 노드에서 removenode 명령을 통해서 클러스터에서 제외하는 방법도 가능합니다.