블로그 이미지
평범하게 살고 싶은 월급쟁이 기술적인 토론 환영합니다.같이 이야기 하고 싶으시면 부담 말고 연락주세요:이메일-bwcho75골뱅이지메일 닷컴. 조대협


Archive»


 
 


Spinnaker #2 - 설치


조대협 (http://bcho.tistory.com)


설치


설치 문서는 https://www.spinnaker.io/setup/  를 참고하면 된다.

설치 가이드를 보면 Quick Install 가이드와 수동 인스톨 가이드를 제공하고 있다.



퀵 인스톨 가이드는 대규모 운영용으로는 어렵고 하나의 인스턴스에, 모든 마이크로 서비스가 인스톨 되는 모델로, 소규모 운영이나 또는 데모용으로 손쉽게 사용이 가능하다. 수동으로 인스톨 하는 방법은 다소 까다롭기 때문에, Quick Install 부터 진행하는 것을 권장한다.


Quick Install 페이지에 들어가면, 각 클라우드와 쿠버네티스 클러스터에 설치 하는 방법이 가이드 되어 있다.


구글 클라우드에 Spinnaker 설치

구글 클라우드에 Spinnaker를 설치하려면,간단하게  Google Cloud Launcher를 이용하면 손쉽게 설치가 가능하다.

설치에 앞서서, Spinnaker는 Google Cloud API를 이용하여, 인스턴스 생성과 스토리지등을 접근하기 때문에, 구글 클라우드 프로젝트에서 해당 API들을 활성화 해줘야 한다. (매우 중요) 활성화 해야하는 API는 아래와 같다.


다음은 Spinnaker를 설치해보자.

Cloud Launcher 페이지에서 Spinnaker를 선택한 후



“Launch on compute engine” 을 선택하면, 4 CPU/20GB VM에 Spinnaker가 설치된다.

아래와 같이 인스턴스 이름을 입력하고, Zone을 선택하면 된다.만약에 필요하다면 VM의 Machine Type을 좀 큰 인스턴스로 해서 운영환경에 적용해도 된다.




만약에 Kubernetes Cluster를 연동해서 사용하고자 한다면, https://www.spinnaker.io/guides/tutorials/codelabs/gcp-kubernetes-source-to-prod/#enable-apis 설치 가이드를 참고하기 바란다.

실행

Spinnaker 를 디폴트로 설치하고 나면 별도의 ID 인증 기능이 설정되어 있지 않기 때문에, 접속 포트가 인터넷으로 열려 있지 않고 local host 로만 접속을 허용한다.

그래서 SSH 터널링을 통해서 로컬 PC의 Local port 9000번과 8084번 포트를 Spinnaker VM의 포트와 맵핑을 시키도록 한다.

9000번은 웹사이트 8084번은 웹사이트가 호출하는 gate 컴포넌트이다.

SSH 터널링은 gcloud compute ssh명령을 이용하면 된다.

사용 방법은 다음과 같다.

gcloud compute ssh --project={구글 클라우드 프로젝트명} --zone={Spinnaker 인스턴스가 배포된 존 이름} {인스턴스명} -- -L 9000:localhost:9000  -L 8084:localhost:8084


다음은 terrycho-sandbox라는 프로젝트 명을 가지고 spinnaker-demo 라는 인스턴스를 asia-northeast-1c에 배포해놓고 접속한 예이다.


gcloud compute ssh --project=terrycho-sandbox --zone=asia-northeast1-c spinnaker-demo -- -L 9000:localhost:9000  -L 8084:localhost:8084


명령을 실행한 후에, 브라우져에서 localhost:9000 번으로 접속하면 Spinnaker 콘솔을 볼 수 있다.



Spinnaker #1 - 소개


Spinnaker

Spinnaker 는 넷플릭스에서 개발하여 오픈 소스화한 멀티 클라우드를 지원하는 Continuous Delivery Platform 이다. 구글 클라우드, 아마존, 마이크로소프트등 대부분의 메이져 클라우드를 지원하며, Kubernetes 나, OpenStack 과 같은 오픈소스 기반의 클라우드 또는 컨테이너 플랫폼을 동시에 지원한다.

시나리오

Spinnaker 의 특징은 멀티 클라우드 지원성뿐만 아니라, 오케스트레이션 파이프라인 구조를 지원한다 특징인데,  배포 단계는 여러개의 스텝이 복합적으로 수행되는 단계이기 때문에, 복잡한 워크 플로우에 대한


관리가 필요하다.

하나의 배포 시나리오를 통해서 오케스트레이션 파이프라인에 대해서 이해해보도록 하자

  • 코드를 받아서 빌드를 하고,

  • 빌드된 코드를 VM에 배포하여 이미지로 만든 후에, 해당 이미지를 테스트한다.

  • 테스트가 끝나면, Red/Black 배포를 위해서 새버전이 배포된 클러스터를 생성한 후에

  • 새 클러스터에 대한 테스트를 끝내고

  • 새 클러스터가 문제가 없으면 트래픽을 새 클러스터로 라우팅한다.

  • 다음으로는 구버전 클러스터를 없앤다.

각 단계에서 다음 단계로 넘어가기 위해서는 선행 조건이 필요하다. 예를 들어 이미지가 빌드가 제대로 되었는지 안되었는지, 새 클러스터가 제대로 배포가 되었는지 안되었는지에 대한 선/후행 조건의 확인 들이 필요하다.

Spinnaker에서는 이러한 오케스트레이션 파이프라인을 “파이프라인”이라는 개념으로 구현하였다. 파이프라인 흐름에 대한 예를 보면 다음과 같다.


위의 파이프라인은 이미지를 찾아서 Red/Black 배포를 위해서 Production에 새로운 이미지를 배포하고, Smoke 테스트를 진행한 후에, 구 버전을 Scale down 시키고, 소스를 태깅 한다. 이때 구 버전을 Destory 하기 전에, Manual Approval (사람이 메뉴얼로 승인) 을 받고 Destory 하는 흐름으로 되어 있다.


또한  각 단계별로 하위 테스크가 있는 경우가 있다. 예를 들어 새로운 클러스터를 배포하기 위해서는 클라우드 내에 클러스터 그룹을 만들고, 그 안에 VM들을 배포한 후에, VM 배포가 완료되면 앞에 로드 밸런서를 붙이고, Health check를 설정해야 한다. 그리고 설정이 제대로 되었는지 체크를 한다음에 다음 단계로 넘어간다.


이러한 개념을 Spinnaker에서는 Stage / Steps/ Tasks/ Operation 이라는 개념으로 하위 태스크를 구현하였다. 개념을 보면 다음과 같다.



파이프라인 컴포넌트

파이프라인은 워크 플로우 형태로 구성이 가능하다. 아래 그림은 파이프라인을 정의하는 화면의 예시이다.


<그림. 파이프라인 예제>

출처 http://www.tothenew.com/blog/introduction-to-spinnaker-global-continuous-delivery/


파이프라인에서 스테이지별로 수행할 수 있는 테스크를 선택할 수 있다.  샘플로 몇가지 스테이지를 보면 다음과 같다.

  • Bake : VM 이미지를 생성한다.

  • Deploy : VM 이미지 (또는 컨테이너)를 클러스터에 배포한다.

  • Check Preconditions : 다음 단계로 넘어가기전에 조건을 체크한다. 클러스터의 사이즈 (EX. 얼마나 많은 VM이 생성되서 준비가 되었는지)

  • Jenkins : Jenkins Job 을 실행한다.

  • Manual Judgement : 사용자로 부터 입력을 받아서 파이프라인 실행 여부를 결정한다

  • Enable/Disable Server Group : 이미 생성된 Server Group을 Enable 또는  Disable 시킨다

  • Pipeline : 다른 파이프라인을 수행한다.

  • WebHook : HTTP 로 다른 시스템을 호출한다. 통상적으로 HTTP REST API를 호출하는 형


개념 구조


Spinnaker는 리소스를 관리하기 위해서, 리소스에 대한 계층구조를 정의하고 있다.



<그림. Spinnaker의 자료 구조 >

출처 : ttp://www.tothenew.com/blog/introduction-to-spinnaker-global-continuous-delivery/



가장 최상위에는 Project, 다음은 Application 을 가지고 있고, Application 마다 Cluster Service를 가지고 있고, 각 Cluster Service는 Server Group으로 구성된다. 하나하나 개념을 보자면,


Server Group 은, 동일한 서버(같은 VM과 애플리케이션)로 이루어진 서버군이다. Apache 웹서버 그룹이나 이미지 업로드 서버 그룹식으로 그룹을 잡을 수 도 있고, 이미지 서버 그룹 Version 1, 이미지 서버 그룹 Version 2 등으로 버전별로 잡는등 유연하게 서버군집의 구조를 정의할 수 있다.

이러한 서버 그룹은 Cluster 라는 단위로 묶일 수 있다.


아래 예제 그림을 통해서 개념을 좀더 상세하게 살펴보자


위의 그림은 이미지 서비스(Image service)를 제공하는 서비스를 Cluster로 정의한것이다.

위의 구조는 Image Service를 Service Group으로 정의했는데, v1,v2,v3 버전을 가지고 있고 각 버전이 Service Group으로 정의된다 (이런 이유는 멀티 버전을 이용한 카날리 테스트나 Red/Black 배포를 이용하기 위해서 여러 버전을 함께 운용하는 경우가 생긴다.)

그리고, 리전별로 별도의 Image Service를 각각 배포하는 모델이다.

리전과 멀티 클라우드의 개념은 Spinnaker 문서에 나온 자료 구조 이외에, 중요한 자료 구조인데, 리소스를 정의할때 클라우드 계정을 선택함으로써 클라우드를 선택할 수 있고, 서비스의 종류에 따라 리전을 선택하는 경우가 있는데 이 경우 리전별로 리소스를 분류해서 보여준다.


Cluster는 Application 내에서 생성될때 , Service Group을 생성시 입력하는  {Account}-{stack}-{Detail} 을 식별자로하여 Cluster를 식별한다. 같은 식별자를 가진 Service Group을 하나의 Cluster로 묶는다.

아래는 Service Group을 생성하는 화면으로 Account, Stack, Detail을 입력하는 메뉴가 있는 것을 확인할 수 있다.



아래 그림은 myapplication 이라는 이름을 갖는 Application 내에, 각각 MY-GOOGLE-ACCOUNT라는 account를 이용하여, myapplication-nodestack-cluster1과, myapplication-nodestack-cluster2 두개의 클러스터를 생성한 예제이다.





또는 자주 쓰는 구성 방식중 하나는 Red/Black (또는 Blue/Green  이라고도 함) 형태를 위해서 하나의 클러스터에 구버전과 새버전 서버 그룹을 각각 정의해놓고 구성하는 방법이 있다.


Application은 Cluster의 집합이고, Project는 Application의 집합이다.

개발하고 배포하고자 하는 시스템의 구조에 따라서 Project, Application, Cluster를 어떻게 정의할지를 고민하는 것이 중요하다.


예를 들어 하나의 서비스가 여러개의 애플리케이션으로 구성되어 있는 경우, 예를 들어 페이스북 처럼, 페이스북 앱, 웹 그리고 앱 기반 페북 메신져가 있는 경우에는 페이스북이라는 프로젝트 아래, 페이스북 앱 백앤드, 웹 백앤드, 앱 백앤드로 Application을 정의할 수 있고,각각의 Application에는 마이크로 서비스 아키텍쳐 (MSA) 방식으로 각각서 서비스를 Cluster로 정의할 수 있다.

아키텍쳐

마지막으로 Spinnaker의 내부 아키텍쳐를 살펴보도록 하자.

Spinnaker는 MSA (마이크로 서비스 아키텍쳐) 구조로 구성이 되어 있으며, 아래 그림과 같이 약 9 개의 컴포넌트로 구성이 되어 있다.



각 컴포넌트에 대해서 알아보도록 하자


  • Deck : Deck 컴포넌트는 UI 컴포넌트로, Spinnaker의 UI 웹사이트 컴포넌트이다.

  • Gate : Spinnaker는 MSA 구조로, 모든 기능을 API 로 Expose 한다, Gate는 API Gateway로, Spinnaker의 기능을 API로 Expose 하는 역할을 한다.

  • Igor : Spinnaker는 Jenkins CI 툴과 연동이 되는데, Jenkins에서 작업이 끝나면, Spinnaker Pipeline을 Invoke 하는데, 이를 위해서 Jenkins의 작업 상태를 Polling을 통해서 체크한다. Jenkins의 작업을 Polling으로 체크 하는 컴포넌트가 Igor이다.

  • Echo : 외부 통신을 위한 Event Bus로, 장애가 발생하거나 특정 이벤트가 발생했을때, SMS, Email 등으로 notification을 보내기 위한 Connector라고 생각하면 된다

  • Rosco : Rosco는 Bakering 컴포넌트로, Spinnaker는 VM또는 Docker 이미지 형태로 배포하는 구조를 지원하는데, 이를 위해서 VM이나 도커 이미지를 베이커링(굽는) 단계가 필요하다. Spinnaker는 Packer를 기반으로 하여 VM이나 도커 이미지를 베이커링 할 수 있는 기능을 가지고 있으며, Rosco가 이 기능을 담당 한다.

  • Rush : Rush는 Spinnaker에서 사용되는 스크립트를 실행하는 스크립트 엔진이다.

  • Front50 : Front 50은 파이프라인이나 기타 메타 정보를 저장하는 스토리지 컴포넌트이다.

  • Orca : Oraca는 이 모든 컴포넌트를 오케스트레이션하여, 파이프라인을 관리해주는 역할을 한다.

  • CloudDriver : 마지막으로 Cloud Driver는 여러 클라우드 플랫폼에 명령을 내리기 위한 아답터 역할을 한다.




Packer와 Ansible을 이용하여, node.js 이미지 생성하기


조대협 (http://bcho.tistory.com)


앞서 글에서 패커를 이용한 이미지 생성 및, 이미지 타입(http://bcho.tistory.com/1226) 에 대해서 알아보았다. 이번 글에서는 node.js 가 깔려있는 파운데이션 타입의 구글 클라우드 VM이미지를 패커와 앤서블을 이용해서 구현해 보도록 한다. 이 글을 이해하기 위해서는 http://bcho.tistory.com/1225 에 대한 이해가 필요하다.


구성은 다음과 같다. 패커를 이용하여, Debian OS 기반의 이미지를 만든 후에, 패커의 Provisioner를 이용하여 Ansible을 설치하고, 이 설치된 Ansible을 이용하여 node.js등을 설치하는 playbook 을 실행하는 순서로 node.js용 이미지를 만든다.  



패커 스크립트는 다음과 같다.

builder 부분은 예전과 같다.(http://bcho.tistory.com/1225) Debian 이미지를 기반으로 VM을 생성한다.

VM 생성후에, 소프트웨어 설치등을 정의하는 부분은 provisioner 라는 부분에 정의되는데, 두 타입의 Provisioner가 사용되었다. 첫번째는 shell 타입이고 두번째는 ansible-local 형태의 provisioner이다.


{

 "variables":{

   "project_id":"terrycho-sandbox",

   "prefix":"debian-9-nodejs"

 },

 "builders":[

  {

   "type":"googlecompute",

   "account_file":"/Users/terrycho/keys/terrycho-sandbox-projectowner.json",

   "project_id":"{{user `project_id`}}",

   "source_image":"debian-9-stretch-v20180105",

   "zone":"us-central1-a",

   "ssh_username":"ubuntu",

   "image_name":"{{user `prefix`}}-{{timestamp}}",

   "machine_type":"n1-standard-4"

  }

 ],

 "provisioners":[

   {

     "type":"shell",

     "execute_command":"echo 'install ansible' | {{ .Vars }} sudo -E -S sh '{{ .Path }}'",

     "inline":[

               "sleep 30",

               "apt-add-repository ppa:rquillo/ansible",

               "/usr/bin/apt-get update",

               "/usr/bin/apt-get -y install ansible"

               ]

   },

   {

      "type":"ansible-local",

      "playbook_file":"./nodejs_playbook.yml"

   }


 ]


}


첫번째 provisioner에서는 ansible을 apt-get으로 설치하기 위해서 sudo 권한으로 apt-get update를 실행하여, 리파지토리 정보를 업데이트 한후에, apt-get -y install ansible을 이용하여, ansible을 설치한다.


두번째 provisioner는 ansible-local provisioner로, 앞단계에서 설치된 ansible을 로컬에서 실행하여, playbook을 실행해주는 코드이다.

ansible은 Configuration management & Deployment 도구로, 나중에 기회가 되면 다른글을 이용해서 소개하도록 한다.

이 코드에서 호출된 nodejs_playbook.yml 파일의 내용은 다음과 같다.

- hosts: all

 tasks:

       - name : create user node

         become : true

         user :

             name: nodejs

             state : present

       - name : update apt-get install

         shell : curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -

       - name : install node.js LTS

         become : true

         #become_user: nodejs

         apt : pkg=nodejs state=installed update_cache=true


hosts:all로, ansible에 등록된 모든 호스트에 대해서 스크립트를 실행하도록 한다. 여기서는 별도의 호스트를 등록하지 않았고, ansible-local 타입으로 실행하였기 때문에, 이 호스트 (localhost)에만 스크립트가 실행된다.

크게 3단계로 실행이 되는데, 첫번째가 nodejs라는 사용자를 만드는 단계로, user 라는 모듈을 사용하여 nodejs라는 사용자를 생성하였다. 이 사용자 계정은 향후 애플리케이션이 배포되었을때, nodejs를 실행할 계정으로 사용된다. 사용자 계정을 만들기 위해서는 root 계정을 획득해야하기 때문에, become: true로 하여 sudo 로 명령을 실행하도록 하였다.

두번째는 node.js를 인스톨하기 위해서 설치전 사전 스크립트를 실행하는 부분이다. apt-get install을 디폴트 상태에서 실행하게 되면 node.js 4.x 버전이 인스톨된다. 최신  8.X 버전을 인스톨하기 위해서, 스크립트를 실행한다. 앤서블 모듈중에서 shell 모듈을 이용하여 쉘 명령어를 실행하였다.

세번째 마지막은 apt 모듈을 이용하여, node.js를 인스톨하도록 한다.


스크립트 작업이 끝났으면, 이미지를 생성해보자

%packer build node.json


으로 실행을 하면 이미지가 생성된다. 생성된 이미지는 구글 클라우드 콘솔의 GCE (Google Compute Engine)의 Images 메뉴에서 확인이 가능하다.

다음과 같이 debian-9-nodejs-*로 새로운 이미지가 생성된것을 확인할 수 있다.



생성된 이미지가 제대로 되었는지를 확인하기 위해서, 이 이미지로 VM을 생성해서 nodejs 버전을 확인해보면 다음과 같이 8.9.4 가 인스톨 되었음을 확인할 수 있다.

또한 nodejs로 된 계정이 생성되었는지를 확인하기 위해서 /etc/passwd 내에 사용자 정보가 생성되었는지를 확인해보면 아래와 같이 nodejs 이름으로 계정이 생성되었음을 확인할 수 있다.



참고 : https://blog.codeship.com/packer-ansible/



피닉스 패턴의 VM 이미지 타입


조대협 (http://bcho.tistory.com)


피닉스 서버 패턴을 이용해서 이미지를 만들때, 그러면 이미지에 어디까지 패키징이 되어야할지 결정할 필요가 있다. 정답은 없지만 몇가지 정형화된 패턴을 찾을 수 는 있다


OS Image

가상화 환경이나 클라우드를 사용하면 디폴트로 사용하는 패턴으로 이미지가 OS 단위로 되어 있는 패턴이다. 우분투 이미지, 윈도우 이미지와 같이 OS 단위로 이미지가 되어 있다.




피닉스 패턴을 사용할 경우 애플리케이션 배포시, 이미지를 이용해서 VM 을 생성하고 VM 이 기동될때, Configuration management 도구를 이용하여 소프트웨어 스택 (미들웨어, 라이브러리등)과 애플리케이션 코드를 배포하는 방식이다.

Foundation Image

Foundation Image는 이미지를 OS단위가 아니라 서비스 플랫폼, 예를 들어 Ruby on rails 환경, PHP환경과 같은 환경 별로 관리하는 방법이다.



일종의 PaaS와 같은 개념의 이미지로 생각되는데, 가장 적절한 절충안이 아닌가 싶다.


Immutable Image

마지막으로는 Immutable Image (불변) 이미지인데, 이 이미지 타입은 배포마다 매번 새롭게 이미지를 만드는 패턴이다.


항상 OS 부터 애플리케이션 까지 전체 스택이 같이 이미지화 되어 배포되기 때문에, 최신 업데이트를 유지하기가 좋지만, 빌드 시간이 많이 걸리고 관리해야 하는 이미지 양이 많아진다.

이 패턴으로 갈거면 도커를 쓰는게 오히려 정답이 아닐까 싶다.


 OS 이미지 패턴의 경우 VM이 올라오면서 소프트웨어들이 설치되고 애플리케이션이 설치되는 모델인데, 소프트웨어 특히 npm이나 pip들을 이용해서 라이브러리를 설치할때 외부 저장소를 이용하는 경우, 외부 저장소가 장애가 날 경우 소프트웨어 설치가 안되기 때문에 외부 시스템 장애에 대한 의존성을 가지고 있고 설치 시간이 길기 때문에 그다지 좋은 패턴으로는 판단이 안되고, immutable 패턴은 위에서도 언급했듯이 빌드 시간이 길고, 여러 이미지를 관리해야하기 때문에 그다지 권장하고 싶지 않지만, 전체를 매번 묶어서 배포함으로써 일관성 유지가 가능한 장점이 있기 때문에 만약에 해야 한다면 도커를 이용해서 구현하는 것이 어떨까 한다. Foundation Image 패턴이 가장적절한 패턴으로 판단되는데, 다음글에서는 Packer를 이용하여, Foundation Image 타입을 만드는 방법을 알아보도록 하겠다.


Packer


조대협 (http://bcho.tistory.com)


Packer (https://www.packer.io/) 는 HashiCorp에서 개발한 가상 머신 이미지를 만들어주는 오픈소스이다.

예를 들어서, 아마존 클라우드 AMI이미지나, 구글 클라우드 이미지를 스크립트를 이용하여 생성이 가능하다.

하나의 스크립트를 이용하여, 구글 클라우드, VMWare, 아마존 클라우드 등 여러 클라우드 환경 (가상화 환경)과 컨테이너 엔진용 이미지를 생성할 수 있다.


Chef,Puppet,Ansible과 같은 Configuration management 툴과 혼동이 될 수 있지만, Packer는 OS 이미지를 만들어주는 역할을 하고, Configuration management 툴들은 이렇게 만들어진 이미지 위에 소프트웨어를 설치하고, 이를 설정하는 상호 보완적인 역할을 하게 된다.

특히 피닉스 서버 패턴에서 VM 이미지를 생성하는데 매우 유용하게 사용될 수 있다. 피닉스 서버 패턴은 http://bcho.tistory.com/1224 를 참고하기 바란다.

템플릿

전체 컨셉은 VM의 설정을 JSON 파일에 정의해놓고, packer 툴을 이용하여 이미지를 생성하는 방식이다.

VM의 설정을 정의한 파일을 템플릿 파일이라고 하는데, 다음과 같은 구조를 가지고 있다.


  • Variable : 변수를 정의하는 섹션으로, 동적으로 변경될 수 있는 클라우드 프로젝트명, 리전명등을 정의하는 부분이다. 메인 템플릿내에 섹션으로 정의할 수 도 있고, 또는 환경 변수나 별도의 변수만 지정한 파일 또는 CLI 옵션으로도 변수값을 전달할 수 있다.

  • Builder : 가장 핵심이 되는 부분으로 OS 버전등 VM 설정에 대한 부분을 정의한다.

  • Provisioner : 이미지에서 OS 설정이 끝난후에, 소프트웨어 스택을 설치하는 부분을 정의한다. 앞에서도 언급하였지만 Packer는 다양한 가상환경에 대한 이미지 생성에 최적화 되어 있지 소프트웨어 설치를 용도로 하지 않기 때문에, Provisioner에서는 다른 configuration management 툴과의 연계를 통해서 소프트웨어를 설치하도록 지원한다. 간단한 쉘을 이용하는것에서 부터, ansible,chef,puppet,salt stack등 다양한 configuration management 도구를 지원하도록 되어 있다. https://www.packer.io/docs/provisioners/index.html
    이 과정에서 OS 설치 후, 소프트웨어 스택 설치 뿐만 아니라, 패치 및 기타 OS 설정 작업을 진행할 수 있다.

  • Post-Processor : Builder와 Provisioner에 의한 이미지 생성이 끝나면 다음으로 실행되는 명령이다.

간단한 예제

이해를 돕기 위해서 직접 간단한 이미지를 만들어보도록 하자.

예제는 맥북에서 packer를 사용하여 구글 클라우드 이미지를 만드는 예제이다. 구글 클라우드의 간단한 사용법은 http://bcho.tistory.com/1107 문서를 참고하기 바란다.

설치 하기

설치는 매우 간단하다. packer는 커맨드 라인 형태의 툴이기 때문에, https://www.packer.io/downloads.html 에서 다운로드 받은후에, 압축을 푼후, PATH에 추가해서 사용하면 된다.


환경 준비

구글 클라우드 API 활성화

packer의 이미지 생성은 구글 클라우드에 접속하여 VM을 만들어서 이미지를 생성하고 이를 구글 클라우드에 등록하는 방식이기 때문에, 구글 클라우드의 관련 API들을 호출해야 한다.

그래서 이 API를 외부에서 호출이 가능하도록 Enable 해줘야 하는데, 아래와 같이 구글 클라우드 메뉴에서 APIs & Services 항목에 들어가면 필요한 API들을 활성화 할 수 있다.



필요한 API는

  • Google Cloud Billing API

  • Google Compute Engine API

를 Enable(활성화) 해줘야 한다

Service Account 파일 생성

packer가 구글 클라우드 API를 사용하기 위해서는 API를 호출하기 위한 인증과 권한 인가가 필요하다. 구글 클라우드는 여러가지 방법을 제공하는데, 여기서 사용할 방법은 service account 를 이용하는 방법이다. 콘솔에서 service account를 생성하고, 이 계정에 여러가지 권한을 부여할 수 있는데, 이렇게 생성된 service account에 대한 인증 정보는 파일로 생성이 된다. 이 예제에서는 이 파일의 경로를 지정하여 service account의 권한을 이용하여 이미지를 생성하도록 하였다.

Service account 파일을 생성하는 자세한 방법은 http://bcho.tistory.com/1166 를 참고하기 바란다.

예제 코드

준비가 끝났으면 이제 실제로 간단한 이미지를 만들어보자. 아래는 gce.json 파일로, n1-standard-4 사이즈 VM에 debian-9 OS로 된 이미지를 구글 클라우드에 만드는 예제이다.


{

 "variables":{

   "project_id":"terrycho-sandbox",

   "prefix":"terrycho-packer"

 },

 "builders":[

  {

   "type":"googlecompute",

   "account_file":"/Users/terrycho/keys/terrycho-sandbox-projectowner.json",

   "project_id":"{{user `project_id`}}",

   "source_image":"debian-9-stretch-v20180105",

   "zone":"us-central1-a",

   "ssh_username":"ubuntu",

   "image_name":"{{user `prefix`}}-{{timestamp}}",

   "machine_type":"n1-standard-4"

  }

 ]

}

이 예제가 제대로 작동하기 위해서는 variables의 project_id를 본인것으로 변경해야 하고,  account_file 부분에 본인이 생성하여 다운로드 받은 service account 파일의 경로를 지정해야 한다.


설정 파일의 내용을 상세하게 알아보도록 하자.

  • account_file : 구글 클라우드 API 에 접근하기 위한 Service account 파일 경로

  • project_id : 이미지 생성에 사용할 구글 클라우드 프로젝트 ID를 지정한다. 여기서는 프로젝트 이름을 terrycho-sandbox로 지정하였다.

  • source_image : 이미지를 생성할때 베이스 이미지를 선택한다. 베이스 이미지는 구글 클라우드에 등록된 이미지를 기준으로 하는데, 이미지 목록은 google cloud CLI 명령인 gcloud  명령을 이용하면 된다.
    %gcloud  compute images list
    명령을 이용하면 현재 가용한 이미지 목록을 볼 수 있고, 거기서 필요한 이미지 이름을 사용하면 된다. 여기서는 debian-9 이미지를 사용하였다.

  • image_name : 생성될 이미지 명. 구글 클라우드 GCE에 이 이름으로 이미지가 등록된다.

  • zone : 이미지를 만드는 방식이 실제 구글 클라우드에서 VM 인스턴스를 만들었다가 이를 기반으로해서 이미지를 추출하는 방식이기 때문에, 이미지를 추출하기 위한 이 VM을 어느 zone에서 기동 시킬지를 지정한다.

예제 실행


파일 작성이 끝난후 아래와 같이 프롬프트 상에서 packer build 명령을 이용하면 이미지 생성이 시작된다.

%packer build gce.json


아래는 명령어를 실행한 결과이다. 로그를 보면 구글 클라우드내에서 설정에 따라서 VM을 만들었다가 이미지를 추출하고, VM을 지우는 과정을 확인할 수 있다.



이 과정이 끝나고 구글 클라우드 콘솔에서 Compute Engine > Image 메뉴를 들어가보면 아래 그림과 같이 terrycho-packer-.... 라는 이름으로 이미지가 생성되어 등록된것을 확인할 수 있다.



이 이미지를 이용하여, 새로운 VM을 만들면 된다. 



피닉스 서버

조대협 (http://bcho.tistory.com)


근래에 들어서 인프라 스트럭쳐를 소프트웨어로 정의하는 Infrastructure As a Code (줄여서 IaC라고 부름)를 관심있게 보고 있는데, CI/CD의 단순 연장선상의 하나의 툴링정도로 생각했는데, 생각보다 상당히 넓은 생태계라서 좀더 깊게 보고 있다.

IaC는 일반적인 툴이나 단순한 프로세스가 아니라 하나의 사상이기 때문에 이를 제대로 이해하기 위해서는 툴링 관점의 접근 보다는 사상과 배경에 대해서 제대로 이해할 필요가 있다.

IaC 개념을 이해하는데 도움이 되는 개념으로 Snowflakes Server (스노우플레이크 서버)와 Phoenix Server(피닉스 서버) 두 가지 개념에 대해서 알아볼 필요가 있다.

Snowflakes Server (스노우 플레이크 서버)

예전에 일반적으로 서버를 운영하는 방법은 서버를 설치한 후 OS를 인스톨한 후에, 필요한 소프트웨어와 애플리케이션을 설치하여 운영하는 형태였다. 여기에 문제가 생긴 경우 패치를 하거나 정기적인 보안 패치 튜닝들을 해당 서버에 지속적으로 적용하고, 애플리케이션은 CI/CD 등의 툴을 이용하여 배포하는 구조를 가지고 있었다.


이렇게 한번 설치한 서버에 계속해서 설정을 변경하고 패치를 적용하는 등의 업데이트를 지속적으로 적용하여 운영하는 서버를 스노우 플레이크 서버 (눈송이 서버)라고 하는데, 이렇게 설정된 서버는 다시 똑같이 설정하기가 매우 어렵다. 모든 설정과정이 문서화가 잘되어 있으면 모르겠지만 대부분 문서화가 꼼꼼한 경우도 드물뿐더러,  담당자가 바뀌거나 관리 조직이 바뀌는 경우에는 그 이력이 제대로 유지되는 경우가 없다. 그래서 장비를 업그레이드 하거나 OS를 새로 인스톨해서 같은 환경을 꾸미고자 할때 예전 환경과 동일한 환경을 구성하기가 어렵고 그래서, 누락된 설정이나 패치등에 의해서 장애가 발생하는 경우가 많다.

이렇게 한번 설정을 하고 다시 설정이 불가능한, “마치 눈처럼 녹아버리는" 서버의 형태를 스노우 플레이크 서버라고 한다.


재 구성의 문제뿐 아니라, 이런 스노우 플레이크 서버는 구성 편차를 유발하기도 하는데, 여러대의 웹서버를 운영하고 있는 조직에서, 문제가 있어서 특정 서버를 패치한 경우, 다른 동일한 웹서버를 모두 패치 하지 않는 이상 구성이 달라진다.  이는 또 운영상의 문제를 일으킬 수 있다.

Phoenix Server (피닉스 서버)

그래서 나온 서버 패턴이 피닉스 서버 패턴인데, 피닉스(불사조)는 불멸로도 알려져있지만 정확히는 불속에서 다시 태어나는 re-born (재탄생)의 개념을 가지고 있다. 이 재탄생의 개념을 서버 설정 방식에 적용한 패턴이 피닉스 서버 패턴이다.

새로운 소프트웨어를 인스톨하거나 설정을 변경할때 기존 서버에 변경 작업을 더 하는 것이 아니라, 처음 OS 설치에서 부터, 소프트웨어 인스톨, 설정 변경까지를 다시 반복하는 것이다.

예를 들어 우분투 16, 톰캣 7.0 버전으로 운영되고 있는 서버가 있을때, 이 서버에 로그 수집 모듈은 fluentd를 설치하는 케이스가 있다고 가정하자.


스노우플레이크 서버 패턴의 경우에는 이미 운영되고 있는 서버에 새롭게 fluentd를 일일이 설치하거나 자동화가 되어 있는 경우에는 ansible 이나 chef등의 configuration management 도구를 이용하여 fluentd를 설치하게 된다.


피닉스 서버 패턴의 경우에는 새 VM을 다시 만들고, 우분투 16 OS를 설치하고, 톰캣 7.0을 설치하고 fluentd를 설치한 다음. 이 VM으로 기존 VM 을 교체한다.


매번 전체 설치를 반복한다면 매우 많은 시간이 들텐데, 어떻하냐? 물론 매번 이렇게 새롭게  모든 스택을 설치하지 않는다. 어느정도 공통 스택은 가상머신의 베이스 이미지 (VM Base Image)로 만들어놓고, 이 이미지를 이용하여 VM을 생성한 후에, 차이가 나는 부분만 설정을 하는 구조를 설정하는 구조를 사용하게 되고 이 과정은 스크립트 코드를 이용해서 자동화하기 때문에, 그렇게 많은 시간이 소요되지 않는다.

피닉스 서버 패턴에서는 매번 전체를 스크립트를 이용해서 설치하기 때문에, 다음과 같은 장점을 가지게 된다.


  • 스크립트에 모든 설정 정보가 유지되게 된다.

  • 이 스크립트 코드를, git와 같은 소스 코드 관리 시스템을 이용해서 관리하게 되면, 어떤 부분을 누가 어떻게 수정을 했는지 추적이 가능하게 된다.

피닉스 서버 패턴을 이용한 배포 구조

그러면 이 피닉스 서버 패턴을 이용한 배포 구조를 보도록 하자

앞의 예제와 같이 Ubuntu 16, Tomcat 7이 설치된 VM서버 2대가 서비스되고 있고, 이 서버들은 앞단에 로드밸런서에 연결되어 있다고 생각하자. 이 VM들은 Ubuntu16, Tomcat 7이 설치되어 있는 Base Image로 생성했다고 가정하자.



Fluentd를 설치하기 위해서는 피닉스 서버 패턴 처럼, Fluentd가 설치된 새로운 base image를 생성하고, 이 이미지를 이용하여 새로운 VM들을 만든다. 이 VM들 그룹은 아직 서비스가 되기 전으로, 이 그룹을 Pre-production 그룹이라고 한다.



Pre-production 그룹이 정상적으로 들어왔으면 로드밸런서를 변경하여 기존의 구 버전 VM으로 들어가던 트래픽을 pre-production 그룹으로 옮겨준다.


그리고 마지막으로, 기존의 운영환경을 지워주면 아래와 같이 새 환경으로 서비스 하는 환경만 남게 된다.


이렇게 서버가 구 버전에서 새버전으로 재탄생(re-born)하는 것이 피닉스 서버 패턴이다.


이 패턴의 문제는 VM 이미지를 빌드하기 때문에, 빌드 및 배포 시간이 상대적으로 오래 걸리고, 또한 배포 당시 기존 Production 환경과 Pre-production 환경이 공존하기 때문에, 다소 추가 비용이 소요될 수 있다.


이 피닉스 서버 패턴에서 중요한것은 기존 이미지를 이용하여 변경을 주고, 이를 다시 이미지로 만들어낼 수 있지만, 이렇게 하면 스노우플레이크 서버이지 피닉스 서버가 아니다. 피닉스 서버는 기존 이미지를 재 사용하는게 아니라 처음부터 모든 스택을 새로 설치해야 하기 때문에, 처음부터 모든 스택을 설치하여 이미지를 만들 수 있는 자동화 툴이 필요하다. 다음 글에서는 이미지 생성을 자동화 해주는 HashiCorp의 Packer라는 오픈소스에 대해서 알아보도록 하겠다.