토스의 백엔드는 어떻게 자동화가 되는가 - Tirrilee/TechTalk GitHub Wiki
토스의 백엔드는 어떻게 자동화가 되는가 라는 글을 보면서 이해하지 못하는 부분이나 단어, 기술들을 정리하기 위해서 정리하였다.
리소스 배분
하나의 서비스가 사용하는 리소스 양은 일반적으로 운용하는 서버 한대의 가용 리소스 대비 매우 적다. 그렇다고 하나의 서버에 모두 올리면 서버가 갑자기 죽어나가면서 장애를 맞을 수도 있다. 따라서 서버가 죽지 않도록 서비스를 각 서버에 배치하는 것 은 매우 조심스럽고 어려운 일이다.
Metric & Log 수집
내가 개발한 서비스가 정확하게 동작하고 있는지, 얼마만큼의 리소스를 요구하고 있는지, 어떤 부분에서 무슨 이유로 장애가 발생했는지 알기 위해서는 Matric & Log 수집이 중요하다. 일반적으로 Agent 를 설치해서 수집하지만
시스템 정보를 통해 확인할 수 있는 메트릭에 비해 각 서비스 별로 수집해야하는 로그는 보통 파일 로 쓰고 Agent가 그 파일의 변경을 추적해서 중앙에 집중 시키는데
로그 파일이 디스크를 꽉 채워서 서버를 죽이는 일도 번번하고 서버에 새로운 서비스를 배치할 때마다 로그 수집 환경을 추가해야하는 것도 번거롭다.
무정지 배포
Rest API를 중심으로 서비스하는 환경에서는 새로운 버전을 배포할 때 기존의 배포된 버전이 새로운 버전으로 교체되기 전에 기존의 사용자 요청에 대해 안전하게 응답을 마치고 종료되기를 희망 한다. 그러나 여러가지 시나리오 때문에 쉽게 가능한 일은 아니다.
서비스 변화와 확장에 따른 Routing 설정 변경
앞서 이야기한 적절한 리소스의 배분과 무정지 배포를 신경쓰면서 추가와 삭제, 스케일링 되는 서비스를 유기적으로 로드 밸런서에 연결하기란 쉽지 않다.
게다가 마이크로 아키텍처에서 Rest API 서비스를 위해서는 Host Domain과 URL Path에 따라 다양하고 복잡한 라우팅 변경이 빈번하게 요구된다.
해결 방법을 보는 중 모르는 용어가 너무 많고 이해가 되지 않아 정리를 진행하였다. 줄 별로 진행하였으며 모르는 용어를 강조 표시를 한 뒤 아래에서 설졍하였다.
- 리소스 배분
DC/OS 는 Mesos Cluster 를 기반으로 Marathon 을 결합한 가장 오래되고 성숙한 Container Orchestration System 이다.
: 분산 커널 시스템으로 프로그램을 여러 머신들이 묶여있는 pool에서 효율적으로 동작하도록 한다.
기존 분산 환경 : 특정 머신이 어떤 일을 할 것인지 정해져있고, 이용자가 각 머신에게 명령을 내려 작업을 수행
Mesos : 프레임워크에 명령을 내리고 Mesos 시스템이 알아서 작업을 분배해서 실행
위의 이미지와 같이 여러 대 머신의 자원을 묶어 하나의 pool처럼 관리함으로써 자원의 종류에 따라 작업의 시간대에 따라 최대의 자원 효율을 뽑을 수 있다.
Framework
Task를 Scheduling하고 Master에게 Task 실행을 요청하는 일을 한다. +) Task는 Process나 Docker Container를 의미
Framework는 주어진 API를 이용해 Scheduler와 Executor를 작성하여 만들수 있는 데 실제로 Framework를 작성할 일은 없고 잘 만들어진 Framework인 Marathon 이나 Chronos 같은 것을 이용한다.
Master
Agent 자원을 관리하며 Framework에게 사용할 수 있는 자원 정보를 알려준다. Framework가 Task에게 수행을 요청하면 다시 Agent에게 Task 수행을 요청하는 역할을 한다. (Framework -> Task -> Agent)
예)
Master -> Framework
"현재 사용할 수 있는 자원은 CPU 16개 Memory 32GB야"
Framework -> Task
"CPU 2개 Memory 4GB가 필요한 웹서버 4개를 띄워줘"
Master -> Agent
Agent를 골라서 해당 작업 수행
Master는 Active-StandBy 방식으로 구성되어있어 Zoo-Keeper를 이용해 하나의 서버만 Leader로 선출해서 사용한다
Active-StandBy는 서버의 가동률을 높이기 위한 서버 다중화에 사용된다.
- Active-Active : 다중화된 요소를 모두 사용할 수 있음
- Active-StandBy : 다중화된 요소 중 한쪽은 사용할 수 없음
Hot StandBy
: StandBy 측은 가동 후 즉시 이용 가능한 구성
Warm StandBy
: StandBy 측은 가동 후에 즉시 이용 가능하게 하기 위해서 나름대로 준비가 필요한 구성
Cold StandBy
: StandBy 측을 정지시켜 두는 구성
분산 시스템을 설계하다 보면 가장 문제점 중 하나가
- 분산된 시스템 간의 정보를 어떻게 공유할 것이고,
- 클러스터에 있는 서버들의 상태를 체크할 필요가 있으며,
- 분산된 서버들 간에 동기화를 위한 락(lock)을 처리하는 것들이 문제가 된다.
이 문제를 해결하는 시스템을 Coordination Service System 이라고 하는데 Apache Zookeeper 가 대표적이다.
이 서비스는
- 분산 시스템 내에서 중요한 상태 정보나 설정 정보를 유지해주면서 전체 시스템의 장애를 유발하지 않기 위해 이중화 등 고가용성을 제공한다.
- 데이터 엑세스가 빠르고
- 자체적으로 장애에 대한 대응성가져 클러스터링을 제공하며
- 장애에도 데이터 유실 없이 fail over / fail back이 가능하다.
디렉토리 구조 기반으로 znode라는 데이터 저장 객체를 제공하고 객체에 데이터를 넣고 빼는 기능만을 제공한다. 디렉토리 형식을 사용하기 때문에 데이터를 계층화된 구조로 저장하기 용이하다.
Agent
Agent는 실제로 Task를 수행하는 노드이다. Zoo-Keeper의 주소를 알고 있기 때문에 Master의 주소도 알 수 있고 스스로 Master 서버에 직접 연결하여 본인의 자원 정보를 알린다.
Data Center Operating System으로 Mesos에 몇 가지 Framework를 얹힌 시스템이다.
Mesos Framework for Docker Orchestration, DockerSwarm 이나 Kubernetes 와 같은 역할을 한다. App이름으로 Mesos Task를 생성하는데 App은 Docker Image + 각종 설정으로 구성되고 HAProxy 로 로드밸런싱 이 가능하며 RESTful API를 통해 쉽게 App을 생성/수정/중단 등을 요청할 수 있다.
컨테이너 배포 관리를 말한다. Container Orchestration의 목적은 Container의 배포 Process를 최적화 하는데 있으며 이것은 Container와 host 수가 증가함에 따라 점점 더 가치가 있게 되고 이러한 유형의 자동화를 Orchestration이라고 한다.
기능
1. Container 자동 배치 및 복제
2. Container 그룹에 대한 로드밸런싱
3. Container 장애 복구
4. 클러스터 외부에 서비스 노출
5. Container 추가 또는 제거로 확장 및 축소
6. Container 서비스 간의 Interface를 통한 연결 및 Network Port 노출 제어
가장 많이 알려진 Orchestration 도구
- Kubernetes
- 구글에서 개발, 기능이 풍부하고 널리 사용, Orchestration Framework
- 베어 메탈, VM 환경, 퍼블릿 클라우드 등의 다양한 환경에서 작동하도록 설계되어 있음
- Container의 롤링 업그레이드 지원
- Docker Swarm
- 여러개의 Docker Host를 함께 클러스터링 하여 단일 가상 Docker Host 생성
- Host OS에 Agent만 설치하면 간단하게 작동하고 설정이 쉬움
- Docker 명령어와 Compose를 그대로 사용 가능
- Apache Mesos
- 수만 대의 물리적 시스템으로 확장할 수 있도록 설계
- Hadoop, MPI, Bypertable, Spark와 같은 응용프로그램을 동적 클러스터 환경에서 리소스 공유와 분리를 통해 자원 최적화 가능
- Docker Container를 저극적 지원
여기서 Docker Orchestration이라고 지칭하지 않은 이유는 Docker Swarm이나 Kubernetes가 Docker의 관리와 제어만을 위한 Orchestration System이라면, Mesos는 None Docker Container도 노드에 올릴 수 있기 때문이다. 어쨌거나, DC/OS는 서비스가 요구한 Resource (CPU, Memory, Disk 등)을 충분히 제공할 수 있는 적절한 HW Node를 찾아 자동으로 실행해주기 때문에 서비스를 어느 서버에 설치해야하는지에 대해 고민하거나 서비스의 과도한 리소스 사용으로 서버가 죽는 상황을 미연에 방지해준다.
- Metrix & Log 수집
Metrix는 Telegraf 를 통하여 Docker 메트릭을 동시에 수집한다.
Telegraf란 Go lang으로 쓰여진 Agent이며 돌아가고 있는 System으로부터 performance metrics를 모으는 것이다. 디자인의 목표는 plugin system에서 최소한의 log를 가져서 개발자들이 쉽게 많이 사용되는 서비스나 third party Web API에서 metrics를 모으는 것을 지원하는 것이다.
이 때, Docker Container의 메트릭은 docker name 또는 DC/OS에 배포한 서비스 ID를 통해 Grafana 에서 쉽게 검색할 수 있다.
Grafana (Site)
Grafana란 쌓여있는 데이터를 효과적으로 시각화 할 수 있도록 해주는 오픈소스이자 시각화 도구 중 한 종류이다.
InfluxDB는 Time-serie 데이터를 저장하는 데이터저장소이다. Time-series Data란 시간의 흐름에 따라 저장하는 데이터로써 Server, DB, Newtwork, Storage와 같은 IT Infra Monitoring을 위한 각종 데이터들, 서비스 반응을 확인하기 위한 각종 지표들 (동시접속자, PV 등), 요즘 뜨고 있는 IoT 기기들의 각종 수집 데이터들 등 활용 목적에 따라 무척 다양화될 수 있다. Time-series DB는 이러한 데이터들을 효율적으로 저장할 목적으로 사용대며 Grafana(대쉬보드) 와 같은 DashBoard Tool과 연계하여 Monitoring 용도로 사용된다.
Time-series DB를 선택함에 있어 가장 중요하게 고려할 점은 저장 및 조회 성능, 저장 공간 효율성, 유연한 확장 가능성을 들 수 있다.
보통 Telegraf (수집) + InfluxDB (저장) + Grafana (시각화 도구) 으로 쓰인다.
전자는 DC/OS를 통하지 않은 단독 실행시 검색 방법이며, 후자는 DC/OS에 의해 실행된 서비스 Container들을 검색하는 방법이다. 따라서 후자의 경우 Service ID를 통해 새로운 서비스의 Matric을 즉각적으로 추적할 수 있다. 또한, 로그에서는 stdout, stderr에 log를 출력하고 Filebeat 를 통해 수집하는 방법과 Kafka 로 로그를 Producing하는 방법이 있는데, 어느 쪽을 선택하던지 개별 서버에 접근하여 추가적인 조작을 가할 필요 없이 배포만으로 ElasticSerach 에서 즉각적인 로그의 실시간 추적이 가능하다
Logstash-Forwarder 소스 코드에 기반한 log data shipper이다. 기본적으로 수집하려는 서버(DB Server)에 Agent 형태로 설치하여 사용하는데, log directory, 특정 log, tail log 결과를 빠르게 전달한다. 전달 대상은 logstash로 보내서 추가적인 parsing을 할 수도있고 elasticsearch로 보내서 중앙집중형으로 저장하게 할 수도 있다.
위의 그림처럼 filebeat는 여러개의 prospector를 띄우고 이 prospector에 할당된 log들은 각각 harvester에 의해 1개의 log가 관리되는데 최신본의 log data가 있으며 spooler에 보내서 취합한다. 그리고 취합된 결과를 설정된 곳(elasticsearch, logstash)로 전달한다.
lohstash는 실시간으로 수집할 수있는 오픈소스 데이터 수집 엔진이며 4가지 강점이 있다.
1. input : 분산된 곳에 저장된 다양한 형태의 데이터들을 실시간으로 한곳에 수집이 가능하다.
2. filter : 로그를 원하는 형태로 customizing이 가능하다.
3. output : 내가 정한 곳으로 보내서 저장할 수 있다. (elasticsearch, mongodb, influxdb, iot 등)
4. plugin & flexibility : 다양한 플러그인이 지원되므로 다양하게 확장할 수 있다.
간단하게 Graph를 보여주는 도구이다. Kibana는 opensource 분석, 시각화 platform이며 elasticsearch와 같이 동작하도록 설계되어있다.
Apache luncene 기반으로 json으로 표현되는 document 기반의 저장 구조로 되어있는 분산 가능 오픈소스 full-text 검색 및 분석 엔진이다. 대용량의 데이터를 빠르게 저장하고 검색하고 분석할 수 있도록 해주며 거의 실시간으로 가능하다.
사용되는 케이스
1. online webstore를 운영할 때 고객이 물품을 선택하면 elasticsearch를 이용해서 전체 product catalog를 저장하고 검색과 자동 완성 추천을 제공할 수 있다.
2. trand, 통계, 합계 또는 특이 사항들을 분석하기 위해 logstash를 이용해 데이터를 수집, 통합 및 parsing하고 이 데이터를 elasticsearch로 보내면 그 때부터는 검색이 가능하며 관심있는 주제를 뽑기 위해 aggregations할 수 있다.
3. 가격 알림 플랫폼 : 가격에 민감한 고객이 제조사에 관계없이 다음달까지 일정 가격 밑으로 떨어지면 알림을 받고싶다고 한다면 제조사의 가격을 긁어와 elasticsearch에 저장할 것이고 고객의 요구사항에 맞는 가격 변동이 있는지 matching 시킬 것이다.
Apache Kafka는 LinkdIn에서 개발된 분산 Messaging System으로써 2011년에 오픈소스로 공개되었다. 대용량의 실시간 로그처리에 특화된 Architecture 설계를 통하여 기존 메시징 시스템보다 우수한 TPS를 보여주고 있다.
kafka는 크게 producer, consumer, broker로 구성된다.
Broker : topic을 기준으로 메시지를 관리
Producer : 특정 topic의 메시지를 생성한 뒤 해당 메시지를 broker에게 전달
consumer : 해당 topic을 구독하는 consumer들이 메시지를 가져가서 처리
kafka는 확장성과 고가용성을 위해 broker들이 cluster로 구성되어 동작하도록 설계되어있다. 심지어 broker가 1개밖에 없을 때에도 cluster로써 동작한다. cluster 내의 broker에 대한 분산처리는 zookeeper가 담당한다.
- 무정지 배포
DC/OS에서는 기본적으로 Canary Deployment 와 Blue-Green Deployment 를 할 수 있는 기능이 있다.

Blue Green Deployment는 동일하게 구성된 두 개의 운영 환경을 구성하여 문제를 해결한다 파란색의 환경이 실제 운영 중이라면, 새로운 버전의 Software Release를 준비하고 있을 때 최종 테스트는 초록색 환경에서 이루어진다. 초록색 환경에서 Software가 문제없이 잘 작동한다면 모든 요청이 초록색 환경으로 가도록 Router 설정을 변경한다. 이 접근법은 hot-standby 환경을 구성하는 것과 기본 개념이 동일하다.
새로운 버전의 소프트웨어를 운영환경에서 배포할 때 전체 사용자들이 사용하도록 모든 인프라에 배포하기 전에 소규모의 사용자들에게만 먼저 배포함으로써 리스크를 줄이는 기법이다.
새로 배포한 버전이 문제가 없다고 판단되면 소수의 선택된 사용자들이 들어오도록 할 수 있다. 어떤 사용자들부터 오픈할 것인지는 여러가지 전략이 있는데 가장 간단한 방법은 무작위로 사용자를 뽑거나 내부 직원에게 오픈하거나 사용자의 프로필이나 인구통계학적 속성 기반으로 선택하는 좀 더 복잡한 방법을 쓸 수 있다.
신규 버전에 대해서 좀 더 확신이 서게 되면 더 많은 서버에 배포하여 더 많은 사용자들이 들어올 수 있도록 할 수 있다. 배포하는 방법으로는 PhoenixServer를 이용하여 기존 서버들을 용도 변경하여 배포하거나 ImmutableServers를 사용하여 새로운 서버들에 배포하고 기존 서버를 폐기시키는 것이다.
Canary Deployment는 모든 사용자들이 신규 버전의 소프트웨어를 사용하게 될 때까지 migrate 단계를 유지한다는 점에서 Parallel Change Pattern이 적용되었다고 볼 수 있다.
장점
- 문제시 언제든 안전하게 RollBack
- 신규 버전 테스트 가능
- 부하를 서서히 증가시키면서 monitoring 및 수치 측정 가능
- 성능 테스트 = 운영 환경 : 분리된 성능 테스트 환경을 만들 필요 없음
단점
- 동시에 여러개의 Software Version 관리 -> 배포 버전의 개수를 최대한 작게 가져가는 것이 유리
- 사용자 PC나 Mobile에서 Software를 설치하는 경우에도 활용이 힘듬 -> 신규 버전의 Software Upgrade를 직접 통제하기 힘듬
그러나 이 방식이 REST API가 안전하게 응답을 완료할 수 있도록 하는 기본적인 보호를 제공하지는 않는다. 그러나 토스 서비스의 Backend에서는 Marathon-LB 의 특성을 이용하여 완벽한 무정지 배포를 완성하였다.
HAProxy 에 기반된 rapid proxy와 load balancer이다. HAProxy는 SSL지원, HTTP compression, health checking 등과 함께 TCP와 HTTP에 기반된 application을 위해 proxying과 load balancing을 제공한다. Marathon-LB는 Marathon의 이벤트 버스와 HAProxy configuration의 업데이트를 실시간으로 제공한다.
부하 분산을 위해 Virtual IP를 통해 여러 서버에 접속하도록 분배하는 기능을 말한다.
예시
1. NAT(Network Address Traslation) : 사설 IP 주소를 공인 IP 주소로 바꾸는 데 사용하는 통신망의 주소 변조기 이다.
2. DSR(Dynamic Source Routing Protocol) : load balancer 사용 시 Server에서 Client로 되돌아가는 경우 목적지 주소를 Switch의 IP 주소가 아닌 Client의 IP 주소로 전달해서 Network Switch를 거치지 않고 바로 Client를 찾아가는 개념이다.
3. Tunneling : 인터넷 상에서 눈에 보이지 않는 통로를 만들어 통신할 수 있게 하는 개념으로, 데이터를 캡슐화해서 연결된 상호간에만 캡슐화를 해제할 수 있다.
- load balancing 동작 방식
네트워크에서 IP 주소와 MAC 주소를 이용해 목적지(destination) IP 주소를 찾아가고 되돌아오는 구조.
기본적으로 reverse proxy 형태로 동작한다. 우리가 브라우저에서 사용하는 proxy는 client 앞에서 처리하는 기능으로 forward proxy라고 한다. reverse proxy란 실제 서버 요청에 대해서 서버 앞 단에 존재하면서, 서버로 들어오는 요청을 대신 받아서 서버에 전달하고 요청한 곳에 그 결과를 다시 전달하는 것이다.
HAProxy는 기본적으로 VRRP(Virtual Route Redundancy Protocol)을 지원한다. 하지만 Software 기반의 Solution이기 때문에 HAProxy가 설치된 서버에 문제가 발생하면 불안정해질 수 있다. 따라서 HA 구성으로 mast HAProxy에 문제가 생기는 경우에도 Slave HAProxy에서 서비스가 원활하게 제공될 수 있도록 한다.
- 서비스 변화와 확장에 따른 Routing 설정 변경
Marathon-LB는 Marathon과 연계하여 서비스 배포 옵션에 맞추어 동적인 load balancing을 제공한다. Toss Service에서는 Host와 URL Path 정보를 통해 동적으로 Routing을 확장하고 변경하고 있다. 따라서 REST API 변화에 따라 load balancer를 조작하다가 서비스에 장애를 일으키는 상황을 최대한 제거할 수 있게 되었다.
요약하자면, Toss Serve의 Backend에서는 개발한 서비스를 DC/OS에 배포하는 즉시 가장 안전한 노드에 자동으로 배치되고, 서비스가 시작됨과 동시에 Metric과 Log 수집이 시작된다. 또한 내가 지정한 Host Doamin과 URI Path에 맞춰 load balancer에 연결되어 바로 원하는 형태의 RES API를 서빙할 수 있다. 여기에 Filover는 덤이고 이 모든것이 자동이다.
DC/OS를 중심으로 한 Micro Service Architecture와 DevOps환경 구성의 목적은 절대로 서버에 SSH Terminal로 로그인하지 않는 것이다.






