깃플 기술 스택 소개 (백엔드 편)
Gitple은 SaaS(Software as a Service) 형태의 전형적인 클라우드 애플리케이션 입니다. (개발팀은 두번째의 경험이라 이번에는 더욱 정교하게 기술스택을 쌓아 나가고 있습니다.)
깃플 아키텍처 전체형상
깃플 서비스의 백엔드 기술스택을 전반적으로 설명해 보겠습니다. 각각의 기술에 대한 상세 내용은 앞으로 블로그 포스팅 할 예정입니다.
깃플 백엔드: 도커기반 마이크로서비스 아키텍처
그림의 윗부분 부터 차례로 설명하겠습니다. 깃플 서비스의 백엔드는 단위기능을 수행하는 마이크로서비스들로 구성됩니다. 마이크로서비스들은 부하분산과 장애조치failover
를 위해 여러 노드에 걸쳐 수평적확장될 수 있습니다.
마이크로서비스는 버전관리되는 도커이미지로 제작되어 여러개 노드에 배포됩니다. 마이크로서비스는 도커docker
컨테이너로 수행됩니다. 모든 백엔드의 서비스는 도커로 관리되고 있습니다.
저장장치와 컴퓨팅을 제공하는 노드들은 클라우드 인프라(IaaS)에서 수행됩니다. 오픈스택기반의 IXcloud 및 AWS 에 상관없도록 IaaS 의존성을 최소화 했습니다.
백엔드 인프라를 고민하면서,
Docker swarm 와 Kubenetes 를 검토했고 실제로 docker swarm은 한동안 사용했었지만 정교하게 배포하기 위한 기능과 네트워크 성능 때문에 직접 환경을 구축하게 되었습니다. Cloud Foundry 같은
Application PaaS
의 기능을 지향하지만, 우리의 목적에 꼭 맞는 기능만을 갖춘 인프라 환경을 만들었습니다.
Ansible : 지속적 배포
지속적 배포CD(Continuous Delivery)
를 위해 ansible을 활용합니다.
먼저, 클라우드 인프라에 기본 환경을 구축합니다. 개발환경을 위해 하나의 노드에 전체 환경을 만들기도 하고, 다수의 노드 클러스터에 자동으로 환경을 구성할 수 있습니다. 기존 클러스터에 노드를 추가할 수도 있습니다.
구축과정을 예로 들면,
- VM 인스턴스를 생성하여 노드들 클러스터를 만들고,
- 보안설정
security group
하고, - 노드 내에서, 기본 시스템 서비스(ntp, logrotated 등) 설정하고,
- 노드 내에서, 모니터링 설정하고,
- 노드 내에서, Docker 수행환경 만들기 등,
노드 구축 후의 도커이미지 빌드 및 배포과정은,
Ansible과 함께 make를 이용하여 복잡한 의존성을 확인하여 도커이미지를 빌드하고 배포를 진행합니다. 수시로 개별 서비스별로 업그레이드 해야 되는 경우가 많은데요. 이때, 서비스에 영향을 주지않도록, 마이크로서비스 컨테이너 하나씩 순차적으로 배포하고 있습니다.
Docker : 컨테이너 아키텍처
Docker swarm을 이용하지 않습니다. 편리하기는 하지만, 오버레이 네트워크overlay network
의 성능 문제로 host port binding
을 이용합니다.
Docker Registry: 배포 이미지 관리
사설 도커 레지스트리Private Registry
를 구축합니다. 마이크로서비스들은 코드 변경이 되면 빌드 후, 도커 이미지로 사설 레지스트리에 등록하여 버전관리 합니다.
Etcd : 클러스터 코디네이터
Etcd를 이용해 마이크로서비스들 사이의 조정자 역할을 구현합니다. 조정자 기능의 예를 들면,
- 리더, 매스터 선출
- 공통 설정 관리
- 마이크로서비스 등록 및 디스커버리
Etcd vs Consul
Etcd는 단순 key/value 저장만 제공하지만, Consul의 경우는 서비스 디스커버리(service discovery), 상태체크(health check)를 추가로 제공하기 때문에 간편하게 쓰기 좋은 도구입니다. 일반적인 경우는 Consul를 추천합니다.
하지만, 깃플이 사용하는 일부 모듈이 Etcd에 의존성이 있었고, Consul이 제공하는 부가기능도 Etcd를 지원하는 다른 도구로 해결 가능했습니다.
Registrator 및 Skydns : 서비스 디스커버리
Skydns는 내부 DNS 서비스를 제공합니다. Registrator는 각 노드에서 도커 컨테이너로 수행되는 마이크로서비스의 상태변화를 관리합니다. Registrator와 Skydns는 etcd를 통해 정보를 공유합니다.
룰규칙을 수행하는 Rule 마이크로서비스가 추가되는 예를 들면,
- N번째 노드에 Rule-n 이 수행됩니다.
- N전째 노드의 Registrator는 Rule-n의 service name, IP 및 PORT 정보를 etcd에 기록합니다.
- Skydns는 rule-n.rule.skydns 를 제공합니다.
- 다른 마이크로서비스들은 rule.skydns 로 전체 Rule 클러스터의 정보에서 rule-n.rule.skydns의 IP 및 PORT정보를 알 수 있습니다.
$ dig +short SRV rule.skydns.local
** ** ***** rule-1.rule.skydns.local.
** ** ***** rule-2.rule.skydns.local.
** ** ***** rule-3.rule.skydns.local.
Reverse Proxy : 리버스 프록시
기본적으로 Haproxy를 활용합니다. 이를 통해, 외부로 제공되는 웹서비스의 로드분산과 장애조치failover
를 제공합니다. 웹소켓을 통한 MQTT, REST API 등의 요구사항에 따라 정교한 설정이 필요합니다. 또한, Etcd에 관리되고 있는 마이크로서비스들의 동적인 추가/삭제를 동적으로 반영합니다.
Rsyslog / ELK : 로그 통합 및 분석
백엔드에서 운영되는 서비스의 severity에 따른 로그 관리는 무엇보다 중요합니다. 특히, 다수의 마이크로 서비스로 구성되는 환경에서는 로그를 통한 빠른 문제해결이 무엇보다 중요합니다.
그래서,
- 모든 마이크로 서비스에서 발생하는 로그는 rsyslog를 통해 한 곳으로 통합합니다.
- 또한, Logstash로 해당 로그를 전송하여 ELK(Elasticsearch, Logstash, Kibana)를 통한 복잡한 로그를 쉽게 분석할 수 있도록 합니다.
Zabbix: 모니터링 및 알람
Zabbix는 서버의 각종 자원을 모니터링하고, 문제가 발생했을 때 알람을 발생할 수 있는 오픈소스 도구입니다.
다음 대상을 모니터링하고, 지정된 임계치를 넘으면 알람이 발생합니다.
- 전체 노드별 자원(CPU, Disk, Network 등)
- 모든 도커 컨테이너의 자원 및 해당 마이크로서비스 상태확인 결과
- Redis, Mongo 등의 알려진 도구들: 커뮤니티에 공개된 template을 이용함
- Zabbix web monitoring 기능을 이용한 웹서비스 모니터링
마이크로서비스의 상태 모니터링을 위해서,
docker run
의 상태체크(health check) 기능을 이용합니다.
마이크로서비스 상태 체크 예)
docker run \
... \
--health-interval 10s \
--health-retries 2 \
--health-timeout 2s --health-cmd "curl --connect-timeout 1 -sf localhost:$(PORT)/api/status | grep -w ok"
Docker 모니터링을 위해 zabbix-docker-monitoring 이용합니다.
마이크로서비스 애플리케이션
백엔드의 단위 기능들은 부하에 따라 컨테이너 수가 증감될 수 있는 마이크로서비스로 구현합니다.
다음의 가이드라인을 따릅니다.
- 도커 컨테이너로 제공한다.
- 가능하면 nodejs 기반으로 구현합니다.
- 구현언어는 javascript입니다. 형
type
체크가 명확한 Typescript 언어를 사용합니다. - 동일기능을 하는 어느 마이크로서비스들은 Master/Slave보다는 Active/Active 구성을 지향합니다.
- 상태체크
health check
를 위한 REST API를 제공합니다.
데이터 저장
Mongo : NO SQL DB
MongoDB는 JSON 형태의 도큐먼트 단위로 데이터를 저장하는 NoSQL DB입니다.
- Query, Index, Aggregation 기능 지원
- Replica set으로 구성하여 고가용성 제공
- 샤딩
sharding
구성하여 수평 확장 제공
깃플에서는 주로 채팅 로그 기록 및 통계 처리 데이터 저장합니다.
Redis : 인메모리 DB
Redis는 Key-Value Store로 대용량의 데이터 처리를 위해 설계된 인메모리 DB입니다
- Strings, Hashes, Lists, Sets, Sorted Sets 등의 다양한 데이터 타입을 지원
- 만료 시각이 되면 데이터를 삭제하는 Expire 기능 지원
- 메모리에 있는 데이터를 파일에 저장할 수 있는 Persistence 기능 지원
- Redis Sentinel 구성으로 고가용성 제공
- Redis Cluster 구성으로 샤딩 제공
깃플에서는 Redis Sentinel을 구성하여 운영중이며, 세션 데이터 공유 및 간단한 Job queue 등의 용도로 활용합니다
이상 백엔드의 기술스택을 살펴보았습니다.
프론트엔드 기술스택에 대해서는 다음편을 기대해 주세요~
별도의 깃플 기술블로그( http://tech.gitple.io ) 를 방문해 보세요. 매주 새로운 기술글들이 올라옵니다~