개발놀이터
쿠버네티스 클러스터에 RDB배포 해? 말어? 에 대한 논쟁 본문
요즘 사이드 프로젝트 때문에 실습만 주구장창 했는데 오랜만에 이론 포스팅입니다. 쿠버네티스를 공부하다보면, 그리고 DevOps에 대해 공부하다보면 한번쯤은 보게 되는 논쟁 바로
"쿠버네티스 클러스터에 RDB배포? 시기상조다" VS "쿠버네티스 클러스터에 RDB배포 안해봤어? 겁나 편한데"
이 논쟁을 구글링하면 마땅한 답이 없습니다. 누가 시원하게 쓰면 좋아! 쓰면 나빠! 이걸 적어놓은걸 찾기 힘들었습니다. 그래서 GPT와 토론을 하면서 주장 -> 반박 -> 재반박 -> 반박에 반박 을 거듭하여 나름 정리해봤습니다.
우선 이 논쟁에 대해 짚어야 하는 부분은 크게 다섯가지입니다.
- 트랜잭션 롤백에 대한 관점
- 마스터 슬레이브 노드 선출에 대한 관점
- 네트워크 망분리로 인한 split-brain 상황에 대한 관점
- 쿠버네티스 클러스터로 로드밸런싱 되는 과정에서 생기는 네트워크 지연 이슈에 대한 관점
- CAP정리에 대한 관점
하나씩 톺아보겠습니다.
쿠버네티스 RDB배포 논쟁
토론에 들어가기 앞서 짚고 넘어가야 하는 점이 있는데요. 쿠버네티스는 초기 목표는 stateful한 애플리케이션에 대한 관리이지만 버전을 거듭하면서 점점 stateless 애플리케이션에 적합해졌다는 것입니다.
제가 오늘 언급할 RDBMS는 그 자체로 하나의 거대한 stateful 애플리케이션으로서 stateless가 조금이라도 묻으면 장애를 발생시킬 수도 있는 무서운 친구입니다. (NoSQL은 전혀 다릅니다!)
때문에 쿠버네티스에서도 이런 Stateful 애플리케이션을 관리할 수 있도록 StatefulSet이라는 오브젝트를 이용해 네트워크도 stateful하게 관리해주고 PV, PVC로 스토리지도 stateful하게 관리해주는 여러 케어가 있었지만 제가 나름대로 직접 발로 뛰어가며 여러 시니어 개발자분들한테 물어봐도 여전히 아직 시기상조라는 말이 많습니다.
그 점을 미리 알고 가시면 좋을 것 같습니다.
1. 트랜잭션 롤백에 대한 관점
쿠버네티스 = 분산시스템이죠.
분산시스템에서 트랜잭션 롤백에 대한 처리가 힘들다는 것이 첫번째 논점입니다. 만약 A라는 요청이 들어왔을 때 1단계, 2단계, 3단계에 걸쳐 커밋을 해야하는데 1단계를 파드1, 2단계를 파드2, 3단계를 파드3에서 처리하는 경우 2단계에서 실패하면 3단계로는 넘어가지 않아야하고 1단계는 롤백이 되어야하는 상황이 생기고 이를 관리하기가 힘듭니다.
"이의있소"
그런 분산 시스템에서의 트랜잭션 롤백을 위한 2PC와 SAGA패턴이라는 것이 준비되어 있습니다. 기본적으로 분산시스템에서 많이 쓰이는 것은 2PC보단 SAGA패턴인데 그 이유는 2PC의 경우 롤백을 확인하기위한 첫번째 커밋과 실제 데이터베이스에 적용되는 두번째 커밋 사이에 락이 걸리기 때문에 데드락 위험이 굉장히 높아진다는 특징이 있기 때문입니다.
SAGA패턴에서는 이런 단점을 보완해서 조금 더 유연한 트랜잭션 롤백 전략을 가지고 있는데 SAGA패턴에서는 전위회복, 후위회복이라는 두가지 개념을 이용해서 유연한 트랜잭션 롤백 전략을 가지고 있습니다.
SAGA패턴에 대해서 아래의 링크에 자세히 설명되어있습니다! 한번 들러주셔서 개념잡고 오셔도 괜찮을 것 같습니다. 물론 몰라도 전혀 상관없습니다!
https://coding-review.tistory.com/484
짧게 짚고 넘어가자면 전위 회복은 롤백시 특정 부분으로 돌아가서 트랜잭션을 재실행하는 것이고 후위 회복은 최초 시점으로 롤백하는 것입니다.
전위 회복에서 중요한 점은 트랜잭션을 재실행하는 로직이 있어야 한다는 것이고 후위 회복은 최초 시점에 대한 상태를 저장하고 있어야 한다는 것이 중요한 점입니다.
아무튼 분산 시스템에서 트랜잭션 롤백에 대한 전략은 이미 유명하고 이를 관리하는 것 또한 어느정도 보편화된 상황이죠.
"재반박 해보겠소"
쿠버네티스 클러스터에서 파드는 쉽게 종료되고 쉽게 재시작되는 존재입니다.
만약 트랜잭션이 실패한 것이 그냥 비즈니스 로직 중간에 발생한 예외 때문에 롤백되는 것이 아니라 파드가 죽어버리는 상황 때문에 발생한 것이라면 어떨까요?
일단 듣기만해도 복잡성이 엄청나게 올라갈 것 같은데요. 문제는 또 있습니다.
Istio같은 서비스 메쉬를 사용하고 있다면 네트워크 타임아웃에 따른 circuit breaker가 작동할 수도 있습니다. 이 경우에도 마찬가지로 네트워크가 제대로 흐르지 않아 예외 상황이 발생하게 되고 이 것을 관리하는 것이 또 다른 복잡성을 유발할 수 있습니다.
2. 마스터 슬레이브 노드를 선출하는 것에 대한 관점
기본적으로 RDBMS는 마스터 슬레이브 노드 선출에 대한 전략을 가지고 있습니다.
만약 이것이 분산 시스템으로 넘어오게 된다면 마스터 노드가 죽었을 경우 새로운 마스터를 선출하는 과정에서 어떤 파드를 마스터로 올려야하는지에 대한 어려움이 생깁니다.
데이터베이스가 마스터노드1개 슬레이브노드4개 이렇게 존재한다고 가정해봤을 때 마스터 노드가 죽으면 어떤 슬레이브 노드를 선출해야할까요? 이런 문제가 생깁니다.
"반박!"
그럼 흔한 RDBMS의 레플리케이션 전략을 그대로 파드로 올려버리면 되지 않나요?
그러니까 Galera 클러스터같은 동기 레플리케이션 전략을 그냥 묶음으로 올려버리면 되는 것 아닌가 하는 말입니다.
기본적으로 삼중화 전략을 선택하는 Galera클러스터는 멀티 마스터 아키텍처를 이용해서 만약 하나의 마스터가 죽더라도 Galera클러스터는 안정적으로 돌아갈 수 있습니다.
"재반박!"
데이터베이스가 마스터 노드를 선출하는 과정, 즉, 마스터 노드가 죽어있다는 그 "상태"도 stateful의 범위에 들어가있습니다.
노드가 죽어있다는 그 상태마저도 상태를 공유해야하는 것이 바론 stateful 애플리케이션의 대명사 RDBMS가 해야하는 것입니다. 만약 마스터 노드가 죽어버린 경우 Galera클러스터는 내부 로직에 따라 마스터를 재선출하는 과정을 거치게 됩니다.
만약 그 상황에서 죽어있던 노드 (혹은 파드)가 살아난다면 이 상태를 깨는 즉, stateless한 성격이 나오는 것이기 때문에 Galera클러스터 입장에서는 "선출 해? 말아? 누구를? 원래 마스터였던 애? 아니면 기존에 있던 애?" 이런 복잡성이 생기고 이것에 대해 따로 전략을 가지고 있어야합니다.
3. 네트워크 망분리로 인한 split-brain에 대한 관점
분산 시스템에서는 majority node와 minority node로 네트워크 장애가 발생해서 분리되는 경우 자칫 잘못하면 하나의 클러스터에 여러개의 마스터노드가 생기는 상황을 야기할 수 있습니다. 이것을 split-brain 상황이라고 하고 이것에 대한 자세한 내용은 아래의 링크에 정리되어있습니다!
https://coding-review.tistory.com/542
"반박 포인트!"
이는 쿠버네티스에 국한된 문제가 아닙니다. 즉, 분산 시스템에 레플리케이션 전략을 사용하는 경우 어떤 상황이던지 split-brain 상황이 올 수 있습니다.
또한, 네트워크망을 자체적으로 구축하고 있는 쿠버네티스 클러스터에서는 split-brain에 대한 문제가 완화되기 때문에 쿠버네티스에서 네트워크 장애로 인한 split-brain의 관점은 틀립니다.
이게 끝이 아니고 Galera 클러스터와 같은 레플리케이션 전략들은 majority node에서만 마스터를 선출하여 최종적으로 데이터베이스에 적용되는 커밋은 majority node에서만 일어날 수 있도록 설계되어 있기 때문에 split-brain이 일어나도 상관없을 정도로 안전합니다.
"과연 그럴까요?"
그런 split-brain 상황에서 커밋이 일어나는 노드를 선출하는 과정에서 파드가 재생성 되었을 때 문제가 되는 것입니다. 이 선출 과정이 의미가 없을 정도로 관리가 안되는 것이죠.
이 이유는 이전에 언급했던 것과 일맥상통하네요.
4. 쿠버네티스 클러스터로 로드밸런싱 되는 과정에서 생기는 네트워크 지연 이슈에 대한 관점
이건 반박할 여지가 없는 쿠버네티스의 압도적인 패배입니다.
왜냐하면 네트워크를 한 껍데기로 한 번 더 감싼 구조이기 때문에 네트워크 지연 이슈가 있을 수 밖에 없습니다.
외부 요청이 쿠버네티스 클러스터로 들어오는 과정에서 Istio나 그것과 연결된 Ingress Controller들, 그리고 그것과 연결된 Service들, 그리고 그것과 연결된 Pod들 그리고 그 안에 있는 Container들 이렇게 분리된 네트워크는 지연시간을 높일 뿐이죠.
또한, 네트워크 구현체인 calico의 경우 네트워크망을 내부망으로 만들기 위한 래핑 과정이 있고, 만약 A파드로 가야하는 트래픽이 B파드로 갔다면 B파드로 간 트래픽을 다시 DNS lookup으로 A파드를 찾아내서 A파드로 돌려보내주는 역할을 하기 때문에 트래픽이 여기갔다 저기갔다 두번 세번 이동하게 됩니다.
이 논제는 "도커 컨테이너에 데이터베이스를 띄우는 것이 맞냐?"라는 논쟁과 거의 흡사한데 도커 컨테이너로 단순하게 띄우는건 양반입니다. 쿠버네티스 클러스터는 여러겹으로 네트워크 망을 감싸고 있기 때문에 데이터베이스의 요청이 많은 일반적인 요즘 애플리케이션에서는 적합하지 않은 것이죠.
심지어 어떤 개발자분은 이 이유 하나만으로도 쿠버네티스 클러스터에 RDB를 띄우면 안된다고 주장하시는 분도 있습니다.
그만큼 이 문제는 데이터베이스 요청이 많아지는 요즘 애플리케이션에서 치명적인 약점이라고 볼 수 있습니다.
5. CAP정리에 대한 관점
CAP정리는 Partition Tolerance (장애 허용) 상황에서 C와 A를 둘 다 만족시킬 수 없다는 정리이고 이미 증명이 끝난 이론입니다. CAP정리에 대해서는 아래의 링크에 자세히 정리되어있으니 참고해주시면 감사하겠습니다!
https://coding-review.tistory.com/312
보통 CAP정리는 NoSQL을 이야기할 때 많이 등장하는 개념인데 그 이유는 NoSQL이 분산시스템에 특화되어있기 때문입니다. 하지만 RDB를 분산시스템에 올려놓고 쓰는 경우 CAP를 피해갈 수 없죠.
장애 (Partition) 상황에서 Availability를 만족시키려면 모든 노드가 쓰기작업이 가능해야합니다. 하지만 모든 노드가 쓰기 작업이 가능해지면 Consistency를 만족할 수 없습니다.
왜냐하면 모든 노드가 쓰기 작업이 가능하니까 서로 다른 데이터를 입력할 수 있기 때문에 만약 장애상황에 A노드에서 A작업을, B노드에서 B작업을 하는 경우 A에는 B작업에 대한 결과가 없고 B노드에는 A작업에 대한 결과가 없기 때문에 Consistency를 만족하지 않죠.
반대로 Consistency를 챙기는 순간 Availability를 만족할 수 없습니다. 위의 경우와 완벽히 반대죠. Consistency를 만족시키려면 모든 노드에서 쓰기 작업이 있으면 안됩니다. 하지만 그 순간 Availability를 만족시킬 수 없습니다.
위의 포스팅에서도 언급되어있지만 CP, AP 데이터베이스라고 그 반대급부에 있는 C, A를 무조건 만족시키지 않는 것은 아닙니다. 장애상황이 아니라면 C, A, P를 모두 만족하는 데이터베이스는 널리고 널렸죠.
때문에 CAP정리는 장애 상황일 때만 C, A가 동일선상에 있지 그 외에 상황에선 C, A가 동일선상에 놓여있지도 않습니다. 대표적으로 CP데이터베이스라고 알려진 HBase는 장애 상황일 때 A를 포기하고 그 외에 상황에선 A를 만족합니다. 또한, 대표적인 AP데이터베이스인 Casandra는 장애 상황에서 C를 포기하고 그 외에 상황에선 C를 만족합니다.
그렇기에 Brewer (저는 "브루어"라고 읽는데 사람 이름입니다.) 가 말한 이상적인 분산 데이터베이스는 일반적인 상황에선 C를 만족하지만 장애 상황일 땐 C를 포기하는 데이터베이스라고 말하더군요.
마치며
마지막 CAP에 대한 관점은 사실 억지인 것 같은데 어느정도는 맞는 말이니 적어놨습니다. 쿠버네티스에서 RDB를 배포하면 되냐? 안되냐? 에 대한 논쟁은 DevOps진영에서 아직까지 마땅한 답이 나오지 않은 뜨거운 감자인 것 같습니다.
우선 제 입장은 선배님들 말대로 아직은 시기상조인게 맞는 것 같습니다. 물론 MongoDB나 Redis, Elasticsearch같은 NoSQL 데이터베이스들은 띄우는 것이 가능하다고는 하지만요.
그럼 이번 포스팅도 여기서 마치도록 하겠습니다. 긴 글 읽어주셔서 감사합니다. 오늘도 즐거운 하루 되세요!
https://chatgpt.com/share/67111153-aea0-8004-b123-cf0d85ec06fd
'배포 > kubernetes' 카테고리의 다른 글
AWS EKS 모니터링 환경 구축에 슬랙 알람 추가하기 (0) | 2024.10.15 |
---|---|
AWS EKS 모니터링 환경 구축하기 (Prometheus, Grafana) (0) | 2024.10.14 |
AWS EKS HPA로 확장성 높이기 (0) | 2024.10.08 |
AWS EKS 스프링 + Nginx + SSL (0) | 2024.10.05 |
AWS EKS 스프링 프로젝트에 NGINX 붙이기 (0) | 2024.10.01 |