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


Archive»


 
 


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을 만들면 된다.