Tech-Verse 2022에서 한우형 님이 발표한 쿠버네티스를 활용한 선언형 클라우드 DB 서비스 세션 내용을 옮긴 글입니다.
안녕하세요. LINE Plus Cloud Native 팀에서 DBaaS(DB as a service) 개발 및 운영을 담당하고 있는 한우형입니다. 이번 글에서는 쿠버네티스를 활용한 선언형 클라우드 DB 서비스에 대해 말씀드리겠습니다.
글은 먼저 왜 선언형으로 DBaaS를 개발했는지와 선언형 시스템이 무엇인지 말씀드리고, 선언형 DBaaS를 구현하기 위한 기술 세부 사항을 살펴본 뒤, 이와 같이 구현한 선언형 DBaaS가 어떻게 작동하는지 공유하는 순서로 진행하겠습니다.
운영 비용 절감을 위한 선언형 DBaaS
LINE에서는 개발자가 DB를 쉽게 생성하고 사용할 수 있도록 DBaaS를 제공하고 있습니다. 현재 My SQL과 Redis, Elasticsearch, 세 종류의 DB를 제공하고 있으며, 앞으로 MongoDB 등 다양한 DB를 추가할 예정입니다. 전체 DB 서비스의 수는 8500개 이상이고, 이 DB를 위해 3만 7000개 이상의 VM을 사용하고 있습니다. 이는 LINE에서 사용하는 전체 VM의 약 35%에 해당하는 수치입니다.
이와 같이 LINE 내 다양한 서비스에서 저희가 제공하는 DB를 사용하고 있기 때문에 DB를 빠르고 안정적으로 제공해야 하는데요. 이렇게 많은 DB를 안정적으로 제공하는 데에는 상당히 높은 운영 비용이 필요합니다.
비용과 관련해서 가장 저희를 괴롭힌 문제는 VM 장애였습니다. VM이 많아지면 당연히 VM 장애도 많아집니다. 단순히 VM 내부 소프트웨어에서 발생하는 문제부터 하이퍼바이저 장애와 같은 하드웨어 문제에 이르기까지 다양한 이유로 VM에서 장애가 발생하는데요. DBaaS에서는 이런 VM 장애가 일반적인 서비스에서보다 더 큰 운영 비용 증가를 초래합니다.
왜 DBaaS에서 일반적인 서비스에 비해 운영 비용이 더 늘어나는지 살펴보겠습니다. 아래 그림은 일반적인 웹 서비스와 DBaaS를 비교한 그림입니다. 그림 좌측은 일반적인 웹 서비스의 모습으로 웹 서버는 VM에서 기동되고 VM은 원격 DB와 연결돼 있습니다. VM 웹 서버로 접근할 때는 로드밸런서를 통해 접근하며, VM에 장애가 발생하면 단순히 새 VM을 생성하고 웹 서버를 생성하면 됩니다. 데이터를 원격 스토리지에 저장하기 때문에 새 VM을 만들어도 별도 작업 없이 데이터를 사용할 수 있습니다.
그림 우측은 DB가 배포된 모습입니다. 가장 큰 차이점은 성능 때문에 많은 DB가 원격 저장소 대신 로컬 저장소를 사용한다는 점이고, 이 때문에 VM 교체가 어렵습니다. VM을 교체하기 위해서는 먼저 대량의 데이터를 복제해야 합니다. 또한 스테이트리스(stateless)인 웹 서버와 달리 DB 인스턴스는 스테이트풀(stateful)이기 때문에 단순히 VM을 생성하고 DB 인스턴스를 실행하기만 하면 되는 게 아니라 DB 연결을 위해 다양한 명령어를 수행해야 합니다.
이와 같이 DB는 일반적인 웹 애플리케이션과는 달리 VM 교체에 많은 작업이 필요하기 때문에 결과적으로 DBaaS의 규모가 커지면 새로운 방법을 강구해야만 하며, 이 문제를 해결하기 위해 생각한 해답이 바로 선언형 시스템입니다.
선언형 시스템과 명령형 시스템의 차이
그렇다면 선언형 시스템은 무엇이고 기존 시스템과 어떻게 다를까요? 선언형 시스템과 대조되는 것이 바로 명령형 시스템입니다. 각 시스템이 어떻게 다른지 실생활에서 접할 수 있는 예제와 함께 알아보겠습니다.
먼저 대표적인 명령형 시스템으로 운전이 있습니다. 운전 시스템은 운전자에게 가속, 감속, 조향 등 다양한 명령을 제공합니다. 운전자는 목적지에 다다르기 위해서 현재 위치나 장애물 여부 등을 직접 판단하고 운전해 목적을 달성합니다.
이에 반해 대표적인 선언형 시스템으로 자율 주행 시스템이 있습니다. 자율 주행 시스템에서는 사용자가 직접 판단하고 명령하는 대신 최종 목적지를 선언하기만 합니다. 운전은 시스템이 현재 위치나 장애물 등을 스스로 파악해서 수행합니다.
이 두 가지 시스템은 사용자 측면에서 시스템을 어떻게 사용해야 하는지가 다릅니다. 명령형 시스템에서는 목적을 달성하기 위해 사용자가 직접 판단하고 명령을 내려야 한다면 선언형 시스템에서는 목적을 선언하기만 합니다. 이후는 시스템이 스스로 판단해서 목적을 달성합니다. 결과적으로 선언형 시스템은 운영에 필요한 판단이나 명령 등 관리자의 개입을 최소화할 수 있습니다.
컨트롤 플레인은 쿠버네티스, 데이터 플레인은 VM 활용
그렇다면 이런 선언형 시스템을 어떻게 만들까요? 선언형 시스템은 새로운 개념이 아닙니다. 시스템을 어떤 관점으로 설계하느냐에 달려 있으므로 어떤 도구로도 선언형 시스템을 만들 수 있습니다.
저희는 쿠버네티스를 확장해 선언형 시스템을 만드는 것을 선택했습니다. 쿠버네티스는 선언형 설정을 통해 컨테이너 워크로드를 관리하는 오픈 소스 플랫폼입니다. 컨테이너 관리를 목적으로 시작됐지만 최근에는 쿠버네티스 커스텀 컨트롤러를 활용해 선언형 시스템을 만들기도 하는데요. 저희 역시 쿠버네티스의 커스텀 리소스와 커스텀 컨트롤러를 활용해서 선언형 DBaaS를 만들었습니다.
쿠버네티스의 컨테이너 관리 기능을 활용하지 않은 이유
이때 쿠버네티스의 유용한 기능 중 하나인 컨테이너 관리 기능은 활용하지 않기로 결정했는데요. 그 이유는 다음과 같습니다.
먼저 LINE에서 이미 대규모로 VM을 사용하면서 오랜 시간 검증했고 대규모 시스템에서도 잘 작동하고 있었습니다. 이런 VM으로 많은 수의 DB를 생성해서 사용하고 있었는데요. 이를 따로 마이그레이션하지 않고 새로운 DBaaS에 통합하고 싶었습니다.
두 번째로 컨테이너를 데이터 플레인(data plane)으로 사용할 경우 쿠버네티스가 단일 장애점(single point of failure)이 될 수 있었습니다. 쿠버네티스의 컴포넌트는 물론 다중화돼 있지만, CoreDNS 같은 주요 컴포넌트에 장애가 발생하거나 글로벌 설정 변경을 잘못할 경우 클러스터 전체 장애를 초래할 수 있습니다. DB는 안전성이 가장 중요하기 때문에 컨트롤 플레인(control plane)의 장애가 데이터 플레인에 영향을 끼치면 안 됩니다. 물론 이를 해결하기 위한 멀티 클러스터 같은 다양한 방법이 연구되고 있지만 시스템이 너무 복잡해진다고 판단해 선택하지 않았습니다.
마지막으로 쿠버네티스의 컨테이너 관리 기법이 DBaaS에는 그다지 유용하지 않았습니다. 대표적으로 파드의 오토스케일링은 DB 인스턴스가 스테이트풀 특성이기 때문에 사용하기 어려웠고, 파드 스케줄링 역시 로컬 스토리지를 사용할 때에는 한계가 있었습니다. 물론 이를 해결하기 위해 쿠버네티스에서 스테이트풀셋을 제공하고 있지만 DBaaS의 다양한 기능을 모두 구현하기에는 한계가 있다고 판단했습니다.
이와 같은 이유로 DBaaS의 컨트롤 플레인은 쿠버네티스 커스텀 컨트롤러를 활용하되 데이터 플레인은 VM을 활용하는 것으로 결정했습니다.
선언형 DBaaS 기술 세부 사항 소개
지금까지 선언형 시스템이 무엇이고 왜 DBaaS를 선언형 시스템으로 만들었는지와 어떤 식으로 만들었는지 소개했습니다. 이제 선언형 시스템을 만들기 위해 고려했던 기술 세부 사항을 살펴보겠습니다.
VM 및 VM 내부 DB 인스턴스 관리를 선언형으로 변경
선언적 VM 관리
선언형 DBaaS를 만들기 위해 가장 먼저 한 일은 VM을 선언적으로 관리하게 만든 것입니다. 쿠버네티스에서 파드는 kubelet이라는 프로세스로 선언적으로 관리됩니다. 이와 마찬가지로 VM을 선언적으로 관리하기 위해 먼저 VM에 해당하는 쿠버네티스 커스텀 리소스를 만들었습니다.
아래 예시를 보겠습니다. 두 개의 가상 코어와 8GB 메모리, dbaas-agent라는 프로세스가 있는 VM을 선언했습니다.
위와 같이 선언한 VM 커스텀 리소스를 VM Operator가 관찰하고 명세를 만족하기 위해 작동하기 시작합니다.
VM Operator는 선언한 명세를 따라 두 개의 가상 코어와 8GB 메모리인 VM을 생성하고 내부에 dbaas-agent라는 프로세스를 실행해 놓을 것입니다.
그런데 만약 VM 생성 작업에 일시 장애가 발생해 생성에 실패한다면 어떻게 될까요?
사용자는 VM의 최종 명세를 선언했고 VM Operator는 이 명세를 따라야 하므로 자동으로 VM 재생성을 백오프(backoff, 데이터 재전송 전 일정 시간 대기)와 함께 반복합니다. 따라서 VM을 생성하기 위한 명령을 입력하고 생성에 실패하면 또 다른 명령을 입력하는 번거로운 과정 대신, VM 최종 명세를 선언하는 것만으로 혹시나 실패한다고 하더라도 언젠가는 선언한 대로 VM이 생성될 것을 보장받을 수 있습니다.
선언형 DB 인스턴스
다음으로 VM 내부의 DB 인스턴스를 선언형으로 만들었습니다(아래 그림에서 오른쪽 위 회색 네모 영역은 바로 전 슬라이드에서 설명한 부분으로 이 영역에서 VM이 정상적으로 생성됐다고 가정하겠습니다).
먼저 DB 인스턴스 하나를 위한 커스텀 리소스를 만들었습니다. DB는 일반적으로 샤딩이나 복제 때문에 여러 프로세스로 기동되는데요. 이번 글에서는 그와 같은 DB의 각 프로세스를 DB 인스턴스라고 부르겠습니다. DB 인스턴스 커스텀 리소스는 한 DB 프로세스의 파라미터로 구성됩니다. 이 파라미터는 DB마다 다른데요. 여기서는 쉽게 설명하기 위해 최대 클라이언트 수를 제한하는 maxclient
와 시간제한을 설정하는 timeout
이 있다고 가정하겠습니다.
앞서 설명한 VM 커스텀 리소스와 마찬가지로 각 노드마다 실행되는 VM 인스턴스를 위한 커스텀 리소스가 존재합니다. 여기서는 각 DB 인스턴스의 설정을 담습니다.
이제 dbass-agent는 이 커스텀 리소스를 관찰하고 로컬 DB에 반영하기 위해 작동합니다. dbass-agent 프로세스 자체의 기동은 앞서 VM Operator가 보장한다고 말씀드렸는데요. 그렇다면 이 상태에서 DB 설정을 바꾸고 싶다면 어떻게 해야 할까요? 선언한 DB 인스턴스 커스텀 리소스의 명세를 바꾸기만 하면 됩니다. 예를 들어 아래와 같이 제한 시간을 5초에서 1초로 수정하면 됩니다.
그러면 dbass-agent가 선언된 명세와 자신의 DB 설정이 다르다는 것을 인지하고 선언된 명세를 만족하기 위해 DB에 필요한 명령을 보냅니다.
명령형과 비교한 선언형의 장점
여기서 명령형과 비교해 선언형에 어떤 장점이 있는지 알아보겠습니다. 만약 VM 장애로 VM이 삭제되거나 사용자나 관리자의 실수와 같은 이유로 VM 내 DB 설정을 잃어버리면 어떻게 될까요?
먼저 dbass-agent는 선언된 명세와 자신의 DB 설정이 다르다는 것을 알아차립니다. 따라서 선언된 명세를 만족하기 위한 명령어를 자신의 DB에 보내고, 이를 통해 결과적으로 최초에 선언된 상태로 복구됩니다.
이와 같이 선언형 시스템은 사용자의 의도로 수정하는 것뿐 아니라 실수나 장애로 불일치가 발생해도 작동하므로 전체 시스템을 더욱 견고하게 만듭니다.
여러 VM을 그룹화하기 위한 커스텀 리소스 생성
지금까지 하나의 VM과 그 VM 내부의 한 DB 인스턴스가 어떻게 작동하는지 살펴봤습니다. 그런데 앞서 말씀드린 것처럼 DB는 샤딩이나 복제를 위해 보통 VM을 여러 개사용합니다. 이에 따라 여러 개의 VM을 그룹화하기 위해 최상위에 DB 서비스라는 커스텀 리소스를 만들었습니다. 이 커스텀 리소스는 실제 DBaaS 사용자가 생성하는 DB와 일대일로 대응합니다. 아래는 DB를 구성하는 VM 개수(vmCount
)와 VM 설정(vmConfig
), DB 설정(dbConfig
)을 선언한 예제입니다.
이와 같이 명세를 선언하면 DBaaS Manager가 이를 보고 필요한 수만큼 VM 커스텀 리소스와 DB 인스턴스 커스텀 리소스를 생성합니다. 이 예제에서는 DB 서비스에서 VM 수를 3개로 선언했기 때문에 각 3개의 커스텀 리소스를 생성한 것을 확인할 수 있습니다. 여기서 DBaaS Manager는 VM이나 DB 인스턴스 커스텀 리소스를 그저 생성하기만 할 뿐입니다. 이후 작동은 VM Operator와 dbass-agent가 책임지고 진행합니다.
별도 DB나 메시지 큐가 필요 없는 시스템
지금까지 설명한 내용을 종합해 보면 다음과 같습니다. 먼저 사용자는 DB 서비스를 선언합니다. DBaaS Manager는 선언된 명세를 보고 VM과 DB 인스턴스 커스텀 리소스를 생성합니다. 각 리소스는 VM Operator와 dbass-agent가 처리합니다.
여기서 데이터를 저장하기 위한 별도 DB나 비동기 처리를 위한 별도 메시지 큐가 없다는 사실을 주목해야 합니다. 쿠버네티스를 배포와 컨트롤 플레인 목적으로 사용했기 때문에 쿠버네티스 리소스를 데이터 저장소로, API 서버를 비동기 처리에 사용하고 있습니다.
선언형 DBaaS를 위한 쿠버네티스 최적화
그렇다면 이런 구조가 쿠버네티스에는 어떤 영향을 미칠까요? 이런 디자인에서 VM 개수가 늘어나더라도 쿠버네티스에 문제는 없을까요? 쿠버네티스는 일반적으로 확장성이 높지만 저희 구조에서는 쿠버네티스를 일반적인 패턴과는 조금 다른 패턴으로 사용합니다. 일반적인 쿠버네티스에서 한 종류의 커스텀 리소스는 하나의 컨트롤러로 관리하기 때문에 50종류의 커스텀 리소스를 만들어도 컨트롤러는 50개밖에 되지 않지만, 이런 구조에서는 DB를 구성하는 모든 VM에 각각 하나씩 컨트롤러가 필요합니다.
아래는 컨트롤러와 API 서버의 관계를 대략적으로 나타낸 그림입니다. 하나의 DB 서비스를 다수의 VM으로 구성했으며, 각 VM에는 컨트롤러가 하나씩 있어서 결과적으로 VM 수만큼 컨트롤러가 기동됩니다. 이때 각 컨트롤러는 쿠버네티스 API 서버에 명령을 보내므로 서버에 상당한 부하가 될 수 있습니다.
이와 같은 대량의 컨트롤러가 실제로 어느 정도의 부하를 만드는지, 또 이와 같은 구조가 어느 정도의 규모까지 제대로 작동할 수 있을지 알고 싶어서 간단한 PoC(proof of concept)를 진행했습니다.
PoC를 진행하기 위해 먼저 확장 목표를 잡았습니다. 대규모 시스템은 물론 중요하지만, 시스템이 너무 커지면 장애가 발생했을 때 대규모 데이터 손실로 이어질 수 있습니다. 또한 필요한 것보다 더 큰 확장 목표는 시스템을 불필요하게 복잡하게 만들 가능성이 있었습니다. 현재 LINE에서 DBaaS를 위해 사용하는 VM이 3만 7000개 정도이므로 쿠버네티스 클러스터 약 두 개 정도로 전체를 감당할 수 있도록 약 2만 개의 VM을 확장 목표로 잡았습니다.
필드 셀렉터와 네임스페이스를 이용한 컨트롤러 최적화
확장 목표를 수립한 뒤 컨트롤러 최적화를 진행했습니다. 예를 들어 VM이 1000개 있다고 가정하겠습니다. VM이 1000개면 VM에 대응하는 커스텀 리소스도 1000개 필요합니다. VM 안의 dbass-agent는 커스텀 리소스를 관찰(watch)하는데요. 이때 일반적으로 모든 커스텀 리소스 변경을 감지하므로 실질적으로 watch 하나는 리소스 1000개를 관찰한다고 볼 수 있습니다. 그렇다면 VM 개수가 1000개이고 각 VM에서 1000개의 리소스를 관찰하므로 총 100만 개의 요청이 필요한 것을 알 수 있습니다.
하지만 dbaas-agent는 모든 커스텀 리소스를 관찰할 필요가 없습니다. 자신이 담당하는 DB 인스턴스만 관찰하면 되기 때문에 필드 셀렉터를 통해 하나의 리소스만 관찰하도록 변경했습니다.
그런데 필드 셀렉터는 쿠버네티스 저장소인 etcd에서는 작동하지 않습니다. 필드 셀렉터는 API 서버에서 모든 목록을 가져온 뒤 메모리에서 필요한 부분만 응답으로 돌려주는 형태로 작동하기 때문에 최적화했을 때 API 서버와 dbaas-agent 사이의 부하는 감소했지만 etcd와 API 서버 사이의 부하는 감소하지 않았습니다.
이 문제를 해결하기 위해 코드를 분석했고, 현재 쿠버네티스에서는 etcd 수준에서 필드 셀렉터를 지정할 수 없다는 것을 확인했습니다. 대신 etcd에서는 네임스페이스별로 자원을 따로 관리한다는 사실을 발견했습니다. 이에 네임스페이스를 대량으로 만들어 부하를 줄이기로 결정했습니다.
사용자는 자신의 논리적 네임스페이스에 DB 서비스를 생성하는데요. 이 논리적 네임스페이스는 쿠버네티스 네임스페이스와 일대일로 대응합니다. 따라서 사용자 네임스페이스에서 생성할 수 있는 DB 서비스 수를 제한하면 모든 커스텀 리소스를 관찰하는 것과 비교해 큰 폭으로 부하를 줄일 수 있습니다. 예를 들어, 네임스페이스가 100개이고 각 네임스페이스마다 10개의 VM을 생성한다면 총 VM 개수는 1000개로 동일하지만 Watch 개수는 1만 개가 됩니다. Watch 개수 100만 개에 비해 충분히 적다고 할 수 있습니다.
최적화 후 테스트 결과
이와 같은 최적화를 수행한 후 간단한 실험을 진행했습니다. 테스트 환경은 다음과 같습니다. 쿠버네티스 API 서버 5개를 구성하고 2만 개의 컨트롤러와 10만 개의 커스텀 리소스를 생성했습니다. 이후 커스텀 리소스를 조금씩 수정하는 요청을 보내서 쿠버네티스 API 서버의 부하를 확인했습니다.
아래는 API 서버의 CPU 사용량을 보여주는 그래프입니다. 처음에 연결할 때 CPU 사용률이 잠시 40%까지 치솟은 뒤 이후 커스텀 리소스 10개 변경, 20개 변경, 40개 변경할 때의 결과가 차례대로 보입니다. 변경 개수가 작다고 느끼실 수 있지만 일반적인 웹 서버와 달리 DB 생성과 삭제, 변경에 해당하는 API이기 때문에 사실 상당히 높은 수준의 부하를 가한 것이라고 볼 수 있습니다.
테스트 결과 40개 변경에서도 CPU 사용률은 40% 미만이었습니다. 테스트에서 사용한 API 서버가 가상 코어 두 개와 메모리 8GB로 매우 낮은 사양임에도 이 정도 성능을 보여줬기 때문에 실제로 충분히 사용할 수 있는 구조라고 판단했습니다.
선언형 DBaaS 작동 방식
지금까지 선언형 DBaaS를 만들면서 겪었던 기술 문제와 그 문제를 어떻게 해결했는지 말씀드렸습니다. 이제 그 결과물인 선언형 DBaaS가 어떻게 작동하는지 예제와 함께 알아보겠습니다. 예제로 살펴볼 부분은 선언형 DBaaS의 대표 기능으로 DB 확장과 DB 파라미터 변경, 노드 교체, 오토 힐링입니다.
DB 확장 작동 방식
먼저 DB 확장 작동 방식입니다. 이 예제에서는 사용자가 기존에 선언한 명세에서 VM 수를 3개에서 4개로 변경했습니다.
그럼 DBaaS Manager는 명세와 실제 커스텀 리소스 개수 사이에 차이가 있는 것을 감지하고 VM과 DB 인스턴스 커스텀 리소스를 하나씩 생성합니다.
다음으로 VM Operator와 dbaas-agent가 VM을 생성하고 DB를 동기화합니다. 결과적으로 전체 DB가 4개로 확장됩니다.
이와 같이 사용자는 DB 서비스 명세를 변경해 다시 선언했을 뿐인데 시스템이 스스로 명세에 맞게 컴포넌트들을 업데이트합니다.
DB 파라미터 변경 작동 방식
다음은 DB 파라미터 변경입니다. DB 파라미터 변경 역시 DB 확장과 비슷하게 작동합니다.
먼저 사용자가 파라미터를 변경한 후 명세를 선언했습니다. 이 예제에서는 타임아웃을 5초에서 1초로 변경했습니다.
DBaaS Manager가 변경을 감지하고 자신이 관리하는 모든 DB 인스턴스 커스텀 리소스로 전파합니다.
그럼 dbaas-agent가 DB 인스턴스 커스텀 리소스 변경을 감지하고 로컬 데이터베이스에 필요한 명령을 보냅니다.
결과적으로 모든 DB의 타임아웃이 1초로 설정됩니다. 각 컴포넌트 간 통신은 선언되는 명세, 즉 커스텀 리소스를 통해서만 전파된다는 점에 주목해야 합니다. 이는 각 컴포넌트 간 결합을 느슨하게 만들어서 의존성을 감소시키는 역할을 합니다.
노드 교체 작동 방식
다음으로 특정 VM을 유지 보수해야 하거나 소프트웨어 에러가 발생해 관리자가 수동으로 노드를 교체할 때 작동하는 방식입니다.
먼저 관리자는 교체해야 하는 VM 커스텀 리소스를 그냥 삭제하면 됩니다. 아래를 보시면 원래 VM 커스텀 리소스가 세 개 있었는데 관리자가 하나를 삭제해서 두 개가 된 것을 확인할 수 있습니다.
DBaaS Manager는 선언된 명세에는 VM 개수가 3개인데 자신이 관리하는 VM 커스텀 리소스는 두 개뿐이라는 것을 감지합니다. 따라서 새 VM 커스텀 리소스를 생성할 것입니다.
그럼 VM Operator는 생성된 VM 커스텀 리소스를 감지하고 새 VM을 생성한 뒤 dbaas-agent를 실행합니다. dbaas-agent는 DB 인스턴스 커스텀 리소스를 확인하고 로컬 DB에 필요한 명령을 보냅니다.
결과적으로 관리자가 노드를 삭제한 것만으로 전체 DB 시스템이 복구됐습니다. 선언형 DBaaS에서는 시스템이 최초에 선언한 명세를 만족하기 위해 끊임없이 작동하기 때문에 노드를 교체하고 싶다면 단순히 노드를 삭제하는 것만으로 충분합니다.
오토 힐링 작동 방식
마지막으로 오토 힐링 기능입니다. 수동 노드 교체를 확장한 것으로 노드를 교체할 때 관리자가 직접 교체하는 게 아니라 시스템이 교체하도록 만드는 것입니다.
이를 위해서는 먼저 오토 힐링하기 위한 이벤트를 받아야 합니다. 이벤트는 다양한 방법으로 받을 수 있고, 대표적으로 노드 DB 상태를 모니터링하는 방법이 있는데요. 이 방법은 DB 상태를 잘못 모니터링할 경우 오토 힐링이 잘못 작동돼 대규모 장애가 발생할 가능성이 있습니다. 저희는 데이터가 극도로 중요한 DB를 다루고 있기 때문에 이보다는 조금 보수적인 방법을 선택했습니다. LINE에서 VM을 교체할 때 발생하는 메인터넌스 이벤트를 활용해서, 이 이벤트가 감지되면 교체해야 할 VM 커스텀 리소스 삭제가 트리거되도록 설정했습니다.
일단 VM 커스텀 리소스가 삭제되면 이후 과정은 수동 노드 교체와 동일하게 DBaaS Manager와 dbaas-agent가 이후 과정을 진행합니다.
결과적으로 VM 메인터넌스 이벤트가 발생하는 시점에 시스템이 자동으로 노드를 교체하기 때문에 관리자 개입을 최소화할 수 있습니다.
마치며
이번 글에서는 DBaaS를 왜 선언형으로 만들었고 선언형 DBaaS가 어떻게 작동하는지 말씀드렸습니다. DBaaS를 선언형으로 구현해 제공하면서 DB를 더욱 견고하게 만들고 운영의 많은 부분을 자동화할 수 있었습니다. 또한 쿠버네티스를 프레임 워크로 사용했기 때문에 배포하기도 쉽고, 별도로 DB나 메시지 큐 등을 추가해 관리할 필요도 없었습니다.
저희는 프로젝트를 진행하며 수개월간 디자인을 논의한 뒤 성능을 검증해서 이제 DB를 선언형 DBaaS로 다룰 수 있게 됐습니다. 앞으로 관리하고 있는 다른 종류의 DB 역시 같은 방법으로 구현할 예정입니다. 저희는 선언형 시스템이 운영 비용을 최소화하기 위한 가장 좋은 방법이라고 믿고 있으며, 앞으로 LINE의 다양한 서비스를 선언형으로 구현해 운영 비용을 최소화하고 개발 효율을 극대화해 나갈 예정입니다. 긴 글 읽어주셔서 감사합니다.