Vagrant 와 Ansible 을이용한개발환경구축 Part 1 : Vagrant 의이해 2014.8.12.[ 제 102 호 ] Ⅰ. 가상머신이용배경 Ⅱ. Vagrant 의소개와설치
SW 공학트렌드 동향분석 Webzine Ⅰ. 가상머신이용배경 일반적인서버개발환경은 < 그림 1> 처럼 DB 는 IDC 내의서버를활용하고, 웹서버는로컬환경을이용하는단순한웹서버개발환경을사용하고있었다. 따라서개발자가테스트하는동안테스터는개발버전을테스트할수없고개발서버로배포될때까지기다려야했다. 그림 1_ 일반적인웹서버의개발방식 이방법은두가지이슈가있다. 첫번째, DB 를초기화해다시셋팅하고 DAO 유닛테스트를통해서 CI (Continuous Integration) 를진행하는과정을할수없다. 그이유는 DB 는모든이들이함께쓰는장비이기때문이다. 그래서이부분은진행을할수없다. DB 데이터를모든개발자가공유할수는있지만, 모든테스트를다진행할수없는형태이다. 그림 2_ 가상머신내에웹서버와 Database 를설치한환경 두번째, 테스터는개발되고있는버전이완료되었다는테스트시작을알려주기전까 지는기다려야한다. 애자일개발방법으로진행할때, 2 주단위로구현하고테스트하는 일정이존재하면개발자가개발서버에따로배포해줄때까지기다리는것말고는마땅 01 2014 August (No.102)
공학트렌드 히할수있는방법이없다. 이런불편함을제거하기위해서 < 그림 2> 와같이하나의가상머신으로통일화할수있다. 웹서버와 Database를함께설치하면하나의개발서버를구축할수있고, 이구축된가상머신은개발자와테스터간에공유될수있을것이다. 또한설정을통해서웹서버에접속할포트역시하나의포트로통일시킬수있고, 필요하다면로컬 PC 에서충돌하지않을포트를지정하여서비스할수있다. 이런방법은다음의장점들을제공한다. 첫째, CI 철학에맞게가상머신에서 DB 초기화를진행할수있다. 따라서 DAO 테스트를완벽하게진행할수있다. ( 물론, staging 환경에맞게 production 레벨에서는테스트코드가동작되지못하게진행해야한다.) 둘째, 테스터는가상머신만받을수있으면언제든지테스트를진행할수있다. 테스터가개발자로부터어느버전을테스트할지미리알고있는상태라면, 해당소스의버전을다운로드해테스트를병행으로진행하면서스크럼팀의빠른스피드의개발을진행시킬수있도록도와준다. 셋째, 개발자 - 테스터뿐아니라, 연동이필요한다른개발자에게도움을줄수있다. 즉, 일종의개발환경킷을제공하는효과를가질수있다. < 그림 3> 또는 < 그림 4> 와같이가상머신위에 API 테스트 Layer(API 테스트베드 ) 를두어웹서버의환경을두어 Acceptance Test 환경을만들수있다. 이런사례는 Facebook 이나 Twitter 의개발자센터와같은비슷한모델로구현이가능하다. 넷째, 사무실 IP 에서 IDC 로의연결이방화벽으로막혀있는환경에서유용하다. 전자금융거래법 ( 일명전금법 ) 이적용되거나, 개인정보를가지고테스트해야하는상황에서는 < 그림 1> 과같은방식은더이상개발이불가능해진다. 즉, 로컬개발환경에서 Production 이아닌개발단계라할지라도 IDC 의서버나 DB 에연결하는방식이어려워진다. 보안이더욱대두되는상황이기때문이다. 다섯째, 로컬환경에서소프트웨어테스트를위해새로설치하고삭제하는것이번거로울수있다. 예를들어새로출시된 JDK8 위에서동작하는 WAS 를테스트하기위해서 JDK8 을설치했다가테스트하고다시삭제해야하는경우가있는데, 가상머신을이용해서이런번거로움을해결할수있다. 02
SW 공학트렌드 동향분석 Webzine 그림 3_ 가상머신위에 API Test Layer 를위치한개발환경 Practical 한개발자환경은 < 그림 3> 에서조금더진화한 < 그림 4> 의모습이다. 개발자환경기반위에다양한유틸리티를포함한그림이될것이다. 일반유틸리티부터개발자나테스터를위한소스배포툴, 재시작스크립트, DB 쪽스크립트를포함한그림이될것이다. 그림 4_ 그림 10에서형상관리툴과필요한 Utility 가포함된개발환경 가상머신이존재하는것은간단한작업을하는웹서버를테스트하기위함보다는여러개의웹서버와 DB 또는 Nosql 이존재하는다양한스토리지가존재하는테스트환경을테스트하는경우가더많다. 이를위해서는가상머신내에서는다양한시스템을설치하고테스트할수있는환경을 < 그림 5> 와같이구성할수있을것이다. 03 2014 August (No.102)
공학트렌드 그림 5_ 연동가능한개발환경과 API Test Layer 가포함된가상머신 이렇게만들가상머신은 Vagrant 로테스트환경구현이가능하다. 그리고배포는 shell script, puppet, chef, ansible 과같은자동화툴로가상머신을만들수있는배포기능 을추가할수있다. 유지보수가가능한가상머신을계속만들수있다. Ⅱ. Vagrant 의소개와설치 2.1 Vagrant 소개 Vagrant 는가상머신관리도구이다. 즉, 가상머신플랫폼 (Hypervisor) 이먼저설치되어야하고그가상머신플랫폼을관리하는 CLI 로관리하는도구가 Vagrant 이다. Vagrant 를쓰는이유는자동화가편하다는점때문이다. 즉, virtual box 를실행시키기위한설정과설치, 시작 / 중지 / 종료등이런작업을일일이해야하는작업을 Vagrant 를이용하면 CLI(command line interface) 기반에서할수있다. 즉, < 그림 6> 의예처럼 Mac OS 에서 Windows 7이나 Ubuntu 리눅스를실행시키려면 Oracle VM Virtual Box 에서이미지를다운로드해서이미지의설정을정하고시작 / 중지 / 종료버튼을눌러야한다. 이과정은사람이수동으로작업해야한다. 그러나 Vagrant 는이를 CLI 상에서쉽게해결할수있다. 예를들어시작은 vagrant up, 종료는 vagrant halt 이다. 자세한설명은뒤에서하도록한다. 04
SW 공학트렌드 동향분석 Webzine 그림 6_Oracle VM Virtual Box 화면 Vagrant 는가상서버를구현하는좋은툴로서, 지금까지얘기한모든것이가능하도록지원한다. 우선간단하게소개하자면다음과같다. 라이선스 : MIT License 개발언어 : Ruby 메인개발자 : Mitchell Hashimoto http://mitchellh.com/ 홈페이지 : http://www.vagrantup.com/ 사용할수있는이미지목록 : http://www.vagrantbox.es/ 버전 1.6.3 (2014.7.7 현재 ) 1.0.0 (2012.3.7) 문서 : http://docs.vagrantup.com/v2/ 2.2 Vagrant 설치 Virtualbox download url(https://www.virtualbox.org/wiki/downloads) 에접속해서가장먼저가상머신플랫폼 (Hypervisor) 인 Oracle 의 Virtual Box 를설치한다. Oracle Virtual Box 는 GPL License 이기때문에사용하는데는별다른이슈가없다. 저자는 Mac OS X 사용자이므로 OS X hosts 용을다운로드했다 1). 다음은 Vagrant 설치를진행한다. http://www.vagr antup.com/ 에접속해서하단좌측 Download 버튼을클릭한다. Vagrant download 화면 (http: 1) 본필자는 MAC OS X 를사용하므로 MAC OS X 기준으로설명하도록하겠다. 05 2014 August (No.102)
공학트렌드 //www.vagrantup.com/downloads.html) 에서 Vagrant 를운영체제에맞게설치한다. 설치한이후에는 Vagrant 의버전을확인한다. $ vagrant v Vagrant 1.6.3 2.3 Vagrant 실행 2.3.1 가상머신이미지다운로드및 vagrant init ( 초기화 ) 먼저프로젝트디렉토리를생성하고생성한디렉토리로접근한다. $ mkdir idp testbox $ cd idp testbox Vagrant 이미지를다운로드해서 local 에저장한다. 아래예는 precise(ubuntu 12.04) 64 비트버전을다운로드한예시이다. precise64 는 Vagrant 안에서사용되는이름또는 별칭이다. OS 가설치된가상머신이미지를 box 로생각하면된다. $ vagrant box add precise64 http://files.vagrantup.com/precise64.box 참고로저장된 vagrant 가상머신이미지는 Mac 의경우 ~/.vagrant.d/boxes 디렉토리 에저장된다. ~/.vagrant 디렉토리에는가상머신에대한메타정보가포함되어있다. vagrant init 명령어를사용하여 box 를초기화한다. 그래서 vagrant 메타파일인 Vagrantfile 을생성하도록한다. $ vagrant init $ ls Vagrantfile Vagrantfile 파일을 ansible 로 provision 할수있도록수정한다. 관련없는내용과주석 을제외해서 Vagrantfile 파일을아래와같이수정한다. # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do config config.vm.box = "precise64" config.vm.box_url = "http://files.vagrantup.com/precise64.box" config.vm.hostname = "web" config.vm.network "private_network", ip: "192.168.1.50" config.vm.network :forwarded_port, guest: 9966, host: 8888 config.vm.provision "ansible" do ansible ansible.playbook = "playbook.yml" 06
SW 공학트렌드 동향분석 Webzine config.vm.box 에 precise64 로선택하고 config.vm.box_url 을이미지를다운로드할수있 는 url 로지정했다. 가상머신의 host 이름을 web 이라지칭했다. config.vm.network 프로 퍼티를이용해 private_network ip 를사용하도록했다. 그리고가상서버에서 9966 포트로 띄운서버를 Host 서버에서 8888 포트로포트포워딩방식을사용한다. 예를들어가상 서버에서는 http://192.168.1.50:9966/view 라는주소를가진웹주소를호스트서버에서는 http://127.0.0.1:8888/view 라는주소로접근할수있음을의미한다. config.vm.provision 은가상서버로어떤툴로 provision( 배포 ) 할것인지를지정하는것이 다. config.vm.provision ansible 의의미는 Ansible 을이용해서하겠다는의미를가진다. ansible.playbook = playbook.yml 은 ansible provisioning 메타파일로 playbook.yml 파일을 사용하겠다는의미를가진다. ansible 에서사용하는스크립트를 playbook 이라고하며 yml 파일은 yaml 이라는표준스펙을지킨다. 자세한얘기는다음장에서설명할예정 이다. 예제로 playbook.yml 을다음과같이저장한다. 간단하게설명하면 vagrant 계정으 로 ls -al /home 결과를화면에출력하라는샘플정보이다. hosts: all user: vagrant tasks: name : test action: command ls al /home register: vagrant debug: var=vagrant.stdout_lines 2.3.2 vagrant up 그림 7_ 평상시 Virtual Box 상태 < 그림 7> 과같이평소가상머신의상태는 전원꺼짐 으로되어있다. 사용자가 vagrant up 명령을이용하면 < 그림 8> 과같이가상머신의상태는 실행중 으로바뀐다. 07 2014 August (No.102)
공학트렌드 그림 8_vagrant up 명령이후가상머신의 status 가 실행중 " 으로변경된화면 vagrant up 명령을내린다. $ vagrant up 상황에따라서는 provision 하지않은가상머신시작을하고싶을때는 --no-provision 을명령어뒤에붙여사용한다. provision 되지않은상태임을확인할수있다. $ vagrant up no provision 2.3.3 vagrant susp 가상머신을잠깐중지하려면 vagrant susp 명령을실행한다. < 그림 9> 와같이가상머신의상태가 저장됨 " 으로바뀐다. $ vagrant susp 그림 9_vagrant susp 명령이후가상머신의 status 가 저장됨 " 으로변경 08
SW 공학트렌드 동향분석 Webzine 2.3.4 vagrant resume 중지된가상머신을다시재개하려면 vagrant resume 을실행하면된다. < 그림 8> 과같은 실행중 인화면으로변경된다. $ vagrant resume 2.3.5 vagrant provision 위에서언급했던 playbook.yml 을기반으로 provisioning 을한다. vagrant provioning 명 령을하면다음과같이가상머신서버로들어가 ls -al /home 결과를화면에출력한다. $ vagrant provision ==> default: Running provisioner: ansible... PLAY [all] ******************************************************************** GATHERING FACTS *************************************************************** ok: [default] TASK: [test] ****************************************************************** changed: [default] TASK: [debug var=vagrant.stdout_lines] **************************************** ok: [default] => { "vagrant.stdout_lines": [ "total 12", "drwxr xr x 3 root root 4096 Sep 14 2012.", "drwxr xr x 25 root root 4096 Jun 27 06:00..", "drwxr xr x 7 vagrant vagrant 4096 Jun 30 05:50 vagrant" ] } PLAY RECAP ******************************************************************** default : ok=3 changed=1 unreachable=0 failed=0 만약 provision 을 ansible 이아닌 shell 기반으로수정한다. Vagrantfile 을아래예제의 볼드체로표시한부분 ( 가상머신에서 test.sh 을실행 ) 하는부분으로수정한다. $ cat Vagrantfile # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do config config.vm.box = "precise64" config.vm.box_url = "http://files.vagrantup.com/precise64.box" #config.vm.network :public_network config.vm.hostname = "web" config.vm.network "private_network", ip: "192.168.1.50" config.vm.network :forwarded_port, guest: 9966, host: 8888 config.vm.provision :shell, :path => "test.sh" 09 2014 August (No.102)
공학트렌드 test.sh 파일은간단히 /home 디렉토리출력하는것이다. $ cat test.sh #!/bin/sh ls al /home 그결과는 ansible 로이용했던것과결과가같다. shell 결과 ansible 결과를비교해볼 때고급스러운개념이있다는것을확인할수있다. $ vagrant provision ==> default: Running provisioner: shell... default: Running: /var/folders/nx/lkzmd37d6fj3sg9kg5flt3yr0000gp/t/vagrant shell20140710 58428 mkmu26.sh ==> default: stdin: is not a tty ==> default: total 12 ==> default: drwxr xr x 3 root root 4096 Sep 14 2012. ==> default: drwxr xr x 25 root root 4096 Jun 27 06:00.. ==> default: drwxr xr x 7 vagrant vagrant 4096 Jun 30 05:50 vagrant 2.3.6 vagrant status 가상머신 status 정보를보려면 vagrant status 명령을사용한다. 아래와같이영어로 실행중을의미하는 running 이출력되는것을볼수있다. $ vagrant status Current machine states: default running (virtualbox) 2.3.7 vagrant ssh vagrant ssh 를이용하여가상머신서버로접근이가능한지테스트한다. ssh 로가상 서버로접근한다. 위에서 config.vm.hostname 으로지정된호스트명 web 을확인할수있 으며, 기본계정은 vagrant 이다. $ vagrant ssh vagrant@web:~$ ssh 포트가열려있으니 ssh 연결하는방법은당연히존재한다. RSA 알고리즘의 ssh key 인 id_rsa( 개인키 ), id_rsa.pub 키를 $HOME/.ssh 에생성하도록한다. $ ssh keygen t rsa host 의 ssh 키를가상서버에복사한다. vagrant 설정에서지정한 config.vm.network private_network ip 로지정한 ip 를입력한다. $ ssh copy id vagrant@192.168.1.50 이후 ssh 연결시정상적으로접근한것으로나온다. 10
SW 공학트렌드 동향분석 Webzine $ ssh vagrant@192.168.1.50 vagrant@web:~$ 2.3.8 vagrant halt vagrant halt 명령을내려가상머신을종료한다. < 그림 7> 의상태로복귀하게된다. $ vagrant halt 2.3.9 vagrant package vagrant package 를통해서패키징하여다른개발자에게전달할수있다. $ vagrant package $ ls package.box package.box 가상머신을 virtual box 가상머신리스트에서삭제를할수있다. < 그림 10> 과같이 vagrant up 을해서 vagrant-test_default_1401100903183_2186 이란이 름을가진가상머신을실행했다. 그림 10_vagrant up 으로가상머신이 실행중 인화면 2.3.10 vagrant destroy 이때 vagrant destroy 명령을내리면다시한번 destroy 를확인한다. y를입력하고엔터를입력한다. $ vagrant destroy < 그림 11> 과같이 virtual box 가상머신리스트화면을보면 vagrant-test_default_14011 11 2014 August (No.102)
공학트렌드 00903183_2186 이름을가진가상머신은삭제되었다. 그림 11_ 실행중이었던가상머신이삭제된화면 2.3.11 vagrant reload Vagrantfile 수정이후반영을하려면 vagrant reload 명령을실행하면설정파일을읽고반영한다. 가상머신도종료했다가다시실행한다. $ vagrant reload 2.3.12 가상서버이름지정하기 Vagrantfile 에지금까지 name 을주지않았다. 아래와같이 config.vm.box 와 config.vm.box_url 만 지정하면 < 그림 12> 와같이 디렉토리명 _testing_1405275482326_94624 의명을가지게된다. Vagrant.configure(VAGRANTFILE_API_VERSION) do config config.vm.box = "precise64" config.vm.box_url = "http://files.vagrantup.com/precise64.box"... 그림 12_ 이름을따로주지않았을때나오는가상서버디폴트이름 12
SW 공학트렌드 동향분석 Webzine virtual box 의화면에서이름을직접수정하지않고 Vagrantfile 의내용을수정하여이름을변 경할수있다. 아래예제는 < 그림 13> 의디폴트가상서버이름을 web 으로바꾸는예제이다. Vagrant.configure(VAGRANTFILE_API_VERSION) do config config.vm.box = "precise64" config.vm.box_url = "http://files.vagrantup.com/precise64.box" config.vm.provider :virtualbox do vb vb.name = "web".. 그림 13_ 예제실행후가상서버의디폴트이름이 web 으로변경됨 2.3.13 여러가상서버 (Multiple VM) 을통제하기 다른디렉토리를하나생성한후, Vagrantfile 파일을아래와같이수정한다. 가상머 신 2 대를동시에실행 / 종료또는하나만실행이가능하다. $ cat Vagrantfile # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do config config.vm.box = "precise64" config.vm.box_url = "http://files.vagrantup.com/precise64.box" config.vm.provision :shell, :path => "test.sh" config.vm.define :web do web_config web_config.vm.box = "web" web_config.vm.define "foohost" do foohost web_config.vm.hostname = "web" web_config.vm.network "private_network", ip: "192.168.1.50" web_config.vm.provider :virtualbox do vb vb.name = "web" 13 2014 August (No.102)
공학트렌드 config.vm.define :mysql do mysql_config mysql_config.vm.box = "mysql" mysql_config.vm.define "foohost" do foohost mysql_config.vm.hostname = "mysql" mysql_config.vm.network "private_network", ip: "192.168.1.51" mysql_config.vm.provider :virtualbox do vb vb.name = "mysql" config.vm.box_url 으로정의한 "http://files.vagrantup.com/precise64.box" vagrant 이미지 를다운로드해 web 과 mysql 이라는이름으로각각 virtual box 이미지의이름을변경한 다. 가상머신이름 (config.vm.define) 과프로바이더 (config.vm.provider) 의이름을정의할 수있다. 프로바이더 (config.vm.provider) 를잘활용하면 cpu 나 memory 설정을구체적으 로지정할수있다. config.vm.provider "virtualbox" do v v.memory = 1024 v.cpus = 2 vagrant up 명령을실행하면 web 과 mysql 이라는이름의가상서버를아래와같이실행 한다. < 그림 14> 와같이두개의가상머신이실행중인것을확인할수있다. $ vagrant up 그림 14_ 가상머신 2 개를동시에실행시킨이후화면 만약각가상머신별로실행을따로하려면 vagrant up web 또는 vagrant up mysql 을 사용한다. 참고로 json 파일로여러개의가상머신을생성할수있다. 아래블로그글 14
SW 공학트렌드 동향분석 Webzine 을참고하면힌트를얻을수있을것이다. http://programmaticponderings.wordpress.com/2 014/02/27/multi-vm-creation-using-vagrant-and-json/ 지금까지가상머신을활용한배경을이야기했고, vagrant 에대한설치, 소개를모두 마쳤다. Part 2 에서는 Ansible 을활용한방식을상세히살펴보도록하겠다. 참고자료 1. https://docs.vagrantup.com 2. https://www.virtualbox.org 3. http://stackoverflow.com/questions/17845637/vagrant-default-name 15 2014 August (No.102)