무중단, 무장애! 잦은 릴리즈!

출처:wikipedia

스페인 바르셀로나에 위치한 사그라다 파밀리아 대성당을 받치고 있는 기둥입니다. 사그라다 파밀리아 대성당은 이미 성당으로서의 기능을 하고 있지만, 사진속 기둥위의 건물은 아직도 건설되고 있다는 점에서 지속적 개선이 요구되는 클라우드 애플리케이션 아키텍처와 닮은 점이 많습니다.
이점에 착안하여 터플(Turple)이라는 이름을 짓게 되었습니다.
Tur(Turtle base for) + ple(Gitple)

사그라다 파밀리아 대성당 - 나무위키

천재 건축가로 알려진 안토니오 가우디가 설계한 건축물이자 그가 심혈을 기울인 야심작으로, 기존 성당 건축의 특징을 잘 계승하면서도 가우디 특유의 개성이 잘 융합된 건물이라는 평가를 받고 있다. 1882년부터 착공에 들어간 이래 136년이 지난 지금도 계속 건축되고 있다. 가우디 사망 100주기인 2026년에 완공이 예정되어 있다. 그런데 가우디는 이 성당의 건설기간을 200년으로 잡았다. 한마디로 예상 완공년도를 2082년으로 잡은 것.

여러분의 클라우드 애플리케이션에 대해 다음 두 가지 질문에 대해 답해 보세요.

첫번째 질문: 다운 타임 1시간, 어떤 일이 발생할까요?

짧은 시간의 다운타임도 엄청난 손실을 유발합니다.

클라우드 서비스를 이용하는 일반 기업별, 1시간 다운타임에 대한 직접적인 경제 손실입니다.

  • 중소기업: 6만 달러 ~ 10만 달러
  • 대기업: 50만달러 ~100만달러

출처: Aberdeen Report: 78% Of Enterprise Websites Suffer Four Or More Disruptions Per Month

하지만, 추가적인 피해는 더욱 심각합니다.

  • 고객이 떠납니다.
    이용자는 참을 성이 없습니다. 최종 이용자는 웹사이트가 3초 이상 서비스가 원할하지 않으면 40%는 그 사이트를 떠납니다. 실망한 최종 이용자는 손쉽게 경쟁 클라우드 서비스로 이전합니다.
  • 기업 평판에 치명적입니다.
    웹사이트가 완전히 기능 을 상실할 경우 그 기간이 길든
    짧든 상관없습니다. 해당 기업은 거의 확실하게 소셜미디어와 뉴스 등에서 부정적 이미지를 얻게 됩니다. 브랜드 이미지 및 신뢰도가 하락합니다.

출처: 웹 다운타임을 심각하게 생각해야 하는 4가지 이유 - CIO korea

두번째 질문: 몇 시간 내로, 긴급 소프트웨어 릴리즈 가능한가요?

서비스 영향없이 잦은 소프트웨어 개선 릴리즈를 하는 것이 지속적인 경쟁 우위 확보의 핵심입니다.

사실, 일반적인 기업의 소프트웨어 릴리즈는 적어도 며칠 걸립니다. 다음은 일반적인 기업의 긴급 서비스 개선 패치 절차 입니다.

  1. 개발팀에서 긴급 패치를 작성하고 유닛 테스트 후, QA팀에 테스트를 의뢰합니다.
  2. QA팀은 테스트 완료 후,
  3. 운영팀과 협조하여 고객에게 “30분간 서비스 중단 PM(정기 유지보수)”을 공지 합니다.
  4. 운영팀은 절차에 따라 서비스 이용률이 적은 새벽 시간에 정기유지보수(PM)를 실시 합니다.

하지만, 클라우드 서비스를 하는 팀은 다음의 우려 없이 몇 시간내로 긴급 릴리즈 해야 합니다.

서비스 내리고 공지하고 릴리즈 해야 해요!

성급한 릴리즈는 장애 발생시켜요. 충분한 테스트 후에 진행 해요!

깃플팀은...

클라우드 애플리케이션 서비스는 튼튼한 기반 위에서 안정적으로 수행하면서도 지속적으로 개선하는 것이 핵심경쟁력입니다.

깃플은 클라우드 아키텍처 뿐아니라 DevOps를 포함한 다양한 방법으로 해결하였습니다.

깃플 서비스는 지난 한 해동안, 5분이상 다운타임이 단 한번도 없었습니다!

깃플 서비스는 매주 정기 릴리즈하고, 긴급 패치는 1시간 이내에 가능합니다!


깃플의 해결책은 터플 = 솔루션 + 컨설팅 + 매니지드서비스 입니다.

DevOps 팀의 조건

깃플팀은 소규모 SaaS 개발팀입니다. 언제나 사용자스토리, 버그, 태스크, 기술부채들이 쌓이고 넘칩니다. 이상황을 헤쳐가는 깃플팀의 방법을 소개합니다.

언제나 사용자스토리/버그/태스크가 넘치는 스크럼 플래닝 보드

애자일하게, 린하게

깃플은 기민한agile 방법론인 깃플팀은 스크럼을 합니다.
PO는 고정, 스크럼 매스터는 번갈아 가면서 맡습니다.
스프린트의 리듬에 따라 2주 사이클을 돌립니다.
이 리듬을 잘 타게 되면 스프린트를 거듭할수록 지치지 않고 속도감있게 나아가는 팀이 됩니다.

개발 뿐 아니라 모든 일은 린하게 진행합니다. 가설을 세우고 신속히 검증하고, 다시 개선해 나갑나다.

다음 두 책은 항상 곁에 두길 바랍니다.

5명 내외의 단단한 팀!

5명 내외의 단단한 팀으로 구성합니다. 경험상 5명을 넘기게 되면, 서로가 무슨 일을 하는 지 속속들이 알기 힘들어 집니다.
스프린트 기간 동안, 앞만 보고 전력질주 하려면 서로의 일들이 아귀가 맞도록 커뮤니케이션이 원할해야 합니다.

5명이 넘어가면 팀을 나누는게 좋습니다.
빠르게 구성원이 늘어가는 조직이라면, 처음에 5명의 단단한 한팀으로 개발 문화를 정착시킵니다. 다음 단계로 5명 각자가 새로운 팀에 소속되면 같은 문화를 가진 팀 최대 5개를 만들수 있을 것입니다.

풀스택 개발

풀스택 개발은 선택이 아니라 필수입니다.
물론 각자 전문 분야는 프론트엔드, 백엔드 서버, 서버 아키텍트, 안드로이드, 아이폰 개발자로 구분 될 수 있습니다. 하지만, 다른 분야의 코드를 이해하고 버그를 찾을 수 있는 능력은 되어야 합니다. 대부분의 기능 추가나 버그해결은 한 분야만 국한되어 있지 않기 때문입니다.

풀스택 개발을 용이한 기술을 선택해야 합니다. 깃플의 예를 들면, 프론트엔드와 백엔드 모두 주언어는 타입스크립트typescript 입니다. 개발 언어가 동일하므로 문맥전환context switch가 별로 없어 분야를 넘나들면서 기능을 구현할 수 있습니다. 또한, 공통 코드를 활용하고 코드를 공유할 수 있습니다.

CI, CD, DevOps

지속적 통합하고 ,빈번한 릴리즈하고, 직접 서비스 운영합니다.

항상 자동 Smoke 테스트는 돌고 있고, 매 코드 커밋 마다 단위테스트 돌립니다. 테스트 케이스를 지속적으로 유지보수하고 추가합니다.

그래야, 예정대로 매주 릴리즈를 할 수 있습니다. 매주 수요일은 정기 릴리즈 날입니다. 물론 핫픽스는 바로 적용합니다.

자동화된 배포와 운영을 합니다. 개발환경과 상용환경 모두 하나의 명령으로 구축 및 배포할 수 있습니다.
서비스의 각종 상태를 모니터링하고, 비정상상황은 알람 트리거 되도록합니다. 이를 통해, 문제가 발생할때 선제적으로 조치를 취할 수 있습니다.


깃플 개발팀은 오랜 기간 애자일을 진행해 본 경험이 있습니다. 저희들의 경험을 꾸준히 포스팅으로 공유 하겠습니다.

터플 프론트엔드 기술스택

Gitple은 SaaS(Software as a Service) 형태의 전형적인 클라우드 애플리케이션 입니다. 개발팀은 두번째의 경험이라 이번에는 더욱 정교하게 기술스택을 쌓아 나가고 있습니다.

이전 글에 이어서 기술스택 프론트엔드 부분을 설명해 보겠습니다. 각각의 기술에 대한 상세 내용은 앞으로 블로그 포스팅 할 예정입니다.

프론트엔드 애플리케이션

깃플 서비스에서는 다음 기술 사용합니다.

깃플 서비스의 프론트엔드 기술은 SPA(Single Page Application)[^1]을 기본으로 하고 있습니다.
SPA 방식은 서버 렌더링 방식에 비해서 빠른 인터랙션가 서버의 부하를 줄일 수 있고 서버의 심플한 구조와 클라이언트 단의 뷰를 완전히 분리하는 등의 장점이 있습니다.

반면에 초기 로딩 속도가 느리고 검색 엔진 최적화가 어렵다는 단점이 있지만 깃플 서비스는 로그인한 사용자 위주의 사용으로 SPA가 더 적합하다고 판단되어서 선택을 하게 되었습니다.

Angular 2+ & Typescript

SPA를 위한 대표적인 자바스크립트 프레임워크은 몇 가지가 있습니다.

다양한 프레임워크가 있고 각각의 장단점이 있지만 깃플 서비스에서는 Angular를 사용하고 있습니다.

angular big picture

Angular는 2009년 구글에서 만든 자바스크립트 프레임워크로 DOM에 대한 직접 조작 보다는 데이터의 바인딩에 초점을 맞추어 개발되었습니다. 그 후로 MVC구조, 양방향 데이터 바인딩등 여러가지 장점으로 많이 사용되어 오다가 성능 문제등으로 인해서 Angular2를 새롭게 릴리즈 했습니다.(버전관리 방식이 변경되어서 현재는 Angular 4 버전까지 릴리즈 되어 있습니다.)

새로운 버전에서는 Typescript 기반으로 코어부터 다시 만들어져서 버전 1.x 과는 전혀 다른 프레임워크가 되었습니다.

Angular 새로운 출시에서 가장 화제가된 부분은 Typescript를 기본으로 지원이였습니다.

typescript superset

Typescript는 Microsoft에서 2012년 발표한 오픈소스로 정적 타이핑을 지원하며 ES6(ECMAScript 2015)의 클래스, 모듈 등과 ES7의 Decorator 등을 지원합니다.

Typescript는 기본적으로 Javascript의 슈퍼셋으로 ES5, ES6의 장점을 그대로 가지고 정적 타입체크와 Type annotation, Interface 을 추가로 제공함으로 생산성을 높일 수 있어서 깃플 서비스에서는 프론트엔드 뿐만 아니라 서버에서도 Typescript를 기본으로 사용하고 있습니다.

Bootstrap 4+ & Sass

부트스트랩은 트위터의 개발자와 디자이너가 웹 사이트를 쉽게 만들수 있도록 CSS, Javascript로 만든 프레임워크입니다. 기본적인 레이아웃과 메뉴, 버튼, 리스트, 탭등의 다양한 컴포넌트를 제공하고 반응형 웹과 모바일 지원등 다양하게 활용 가능합니다.

현재 안정 버전인 v3과 v4.0.0-beta 두 가지 버전이 있는데 v4.0.0은 아직 베타 상태이지만 Sass 지원, 향상된 Grid 시스템, Flexbox[^3] 지원등의 장점으로 인해서 깃플 서비스는 v4.0.0 버전을 사용하고 있습니다.

Sass(Syntactically Awesome StyleSheets)는 CSS를 사용할 때 복잡한 Selector와 CSS Value들의 중복적인 사용들의 문제를 해결하기 위해서 만들어진 CSS pre-processor 입니다.

부트스트랩과 함께 Sass의 variable, extend, mixins 기능을 유용하게 사용하고 있습니다.

Ionic : 스마트폰 UI look&feel

Ionic은 다양한 플랫폼에 모바일 앱을 만드는 프레임워크입니다. HTML, CSS, Javascript를 이용해서 모바일에서 사용하는 컴포넌트를 제공하고 Apache Cordova 이용해서 모바일의 플랫폼의 API를 사용할 수 있습니다.

깃플 서비스에서는 채팅앱에 사용자 친화적인 모바일 UI를 제공하기 위해서 사용하고 있습니다.

Ionic의 기본앱을 만들기 위해서 다음과 같이 쉽게 테스트앱을 만들어 실행할 수 있는 CLI를 제공하고 있습니다.

  • Ionic Install

    npm install -g cordova ionic
  • Start an App

    ionic start myApp tabs
  • Run App

    cd myApp
    ionic serve

Webpack: 모듈 bundler

프론트엔드 개발에서는 Angular, bootstrap, Sass, Images 등의 다양한 리소스들을 사용하고 이 리소스를 하나의 패키지로 만들어서 배포하여서 사용합니다. 이렇게 정적인 파일들로 만들기 위해서 다양한 번들러들('Grunt', 'Gulp'..)이 있는데 그 중에 깃플 서비스에서는 webpack 번들러를 사용합니다.

webpack 번들러

웹팩은 모듈 번들러 입니다. 웹팩은 상호 의존성이 있는 모듈들을 사용해 그 모듈들과 같은 역할을 하는 정적 에셋들을 생성해냅니다. (Webpack is a module bundler. Webpack takes modules with dependencies and generates static assets representing those modules.) - 공식 사이트

깃플 워크스페이스와 채팅앱의 Typescript 컴파일, 여러개의 Sass 파일을 CSS로 컴파일, 이미지 그리고 그외 파일을 배포가능 하나의 번들로 만들어서 배포를 합니다.

Yarn : 패키지 관리

Yarn은 페이스북에서 만든 자바스크립트 패키지 매니저입니다.

기존의 널리 사용되는 패키지 관리자인 npm을 사용할 때 일관성, 보안, 성능에 문제를 겪에 되었서 이를 해결하기 위해서 만들어졌습니다. 깃플 서비스는 다른 문제보다도 일관성에서 npm 사용시에 문제가 발생하여서 프론트엔드와 서버에 yarn으로 변경하였습니다.

yarn의 사용은 이미 npm을 사용하고 있다면 크게 부담없이 사용할 수 있습니다.

  • 초기화
    yarn init
  • 패키지 설치
    yarn install
  • 패키지 추가
    yarn add {패키지명}
  • 패키지 삭제
    yarn remove {패키지명}
  • 패키지 업그레이드
    yarn upgrade {패키지명}

Nightwatch.js : 브라우저 자동 테스트

나이트와치는 프론트엔드의 브라우저 테스트(End-to-End)를 위해서 사용합니다.

나이트와치 초기화 동작 흐름

나이트와치는 WebDriver API를 이용해서 브라우저의 자동화 테스트를 하게 됩니다.
모든 테스트는 Javascript 환경에서 실행 가능하고 CSS 또는 Xpath 셀렉터, BDD(Behavior-Driven Development)[^4]-style assertion 등을 제공합니다.

깃플 서비스에서는 워크스페이스와 사용자 채팅앱 모두에서 실제 동작을 테스트하고 그 결과를 저장합니다. 추가로 나이트와치 테스트를 화면을 비디오로 저장해서 오류가 발생할 때 재현되는 동영상을 바로 확인할 수 있도록 설정해서 사용하고 있습니다. nightwatch-video-recorder

마치면서...

프론트엔드에서 적용하고 있는 기술에 대해서 전반적인 내용을 소개했는데 상세한 기술 적용에 대해서는 앞으로 추가해 가도록 하겠습니다.

[^1]: Single page application : wikipedia
[^3]: Flexbox Guide
[^4]: BBD(Behavior-driven development) : wikipedia

터플 백엔드 기술스택

깃플 기술스택 전체

Gitple은 SaaS(Software as a Service) 형태의 전형적인 클라우드 애플리케이션 입니다. 개발팀은 두번째의 경험이라 이번에는 더욱 정교하게 기술스택을 쌓아 나가고 있습니다.

깃플 서비스의 백엔드 기술스택을 전반적으로 설명해 보겠습니다. 각각의 기술에 대한 상세 내용은 앞으로 블로그 포스팅 할 예정입니다.

백엔드: 도커기반 마이크로서비스 아키텍처

위에서 부터 차례로 설명합니다.
깃플 서비스의 백엔드는 단위기능을 수행하는 마이크로서비스들로 구성됩니다. 마이크로서비스들은 부하분산과 장애조치failover를 위해 여러 노드에 걸쳐 수평적확장될 수 있습니다.

마이크로서비스는 버전관리되는 도커이미지로 제작되어 여러개 노드에 배포됩니다. 마이크로서비스는 도커docker 컨테이너로 수행됩니다. 모든 백엔드의 서비스는 도커로 관리되고 있습니다.

저장장치와 컴퓨팅을 제공하는 노드들은 클라우드 인프라(IaaS)에서 수행됩니다. 오픈스택기반 프라이빗 클라우드 및 아마존 웹서비스(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를 지원하는 다른 도구로 해결 가능했습니다.

RegistratorSkydns : 서비스 디스커버리

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를 제공합니다.

데이터 저장

MongoDB : NoSQL 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 등의 용도로 활용합니다.

이상 백엔드의 기술스택을 살펴보았습니다. 프론트엔드 기술스택에 대해서는 다음편을 기대해 주세요~