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


Archive»


 

'vagrant'에 해당되는 글 2

  1. 2013.10.24 Vagrant를 이용한 개발환경 관리(간단한 VM관리) (1)
  2. 2013.10.22 Docker 소개 (7)
 

Vagrant를 이용한 개발환경 관리(간단한 VM관리)

ALM | 2013.10.24 00:48 | Posted by 조대협

Vagrant

시작하기

Vagrant는 한마디로 이야기 하면, “간소화된, VM 관리 서비스이다”. 이미 Virtual Machine 환경은 보편화 되서 사용되고 있고, VMWare Oracle Virtual Box등을 이용하면 PC에서도 손쉽게 VM 환경을 구축할 수 있다. 그러나 문제점은, Virtual Box와 같은 Hypervisor가 있다고 해도, VM을 생성하는 것 자체가 번거로운 작업이라는 것이다.

 Hypervisor에서 논리적인 가상 하드웨어 머신을 생성하고 가상머신에 OS를 설치하고, 일일이 설정을 해줘야 한다. 이런 반복적인 작업을 조금더 손쉽게 자동화 할 수 없을까? 하는 아이디어에서 시작한 것이 Vagrant이다.

먼저 이해를 돕기 위해서 예제를 실행해보자.

Vagrant VM 관리도구 이기 때문에, 먼저 Hypervisor 부터 인스톨을 해야 한다.

https://www.virtualbox.org/ 에서 Virtual Box를 다운로드 받아서 설치하자.

다음으로 http://www.vagrantup.com/ 에서 vagrant를 받아서 인스톨한다. 이제 준비가 끝났다.

아래와 같이 vagrant init precise32 http://files.vagrantup.com/precise32.box 를 실행하면, Ubuntu Linux VM의 실행하기 위한 설정들을 자동으로 가지고 온다. 그리고 vagrant up 명령어를 실행하면 해당 설정에 따른 VM 을 자동으로 다운받아서 설치하고 Virtual Box를 통해서 해당 VM을 기동 시킨다. Putty를 이용하여 SSH localhost:2222 번으로 접속 (id:vagrant, passwd:vagrant)를 입력하면, 생성된 VM에 로그인할 수 있다. 또는 간단하게 “vagrant ssh”라고 실행하면, 현재 생성된 VM에 자동으로 SSH로 연결된다.



Vagrant 없이 Virtual Box에서 직접 Ubuntu VM을 설치하려면 VM을 만들고, Ubuntu OS를 설치해야 한다. 그러나 Vagrant가 있으면 이렇게 간단하게 두줄의 명령어로 VM을 만들고 실행시킬 수 있다.

Box 개념 이해하기

앞에서 vagrant init 명령을 실행할때, preceise32.box라는 파일을 지정하였다. box 파일은 VM을 만들기 위한 기본 OS 이미지를 포함한 VM 설정(CPU,메모리 사이즈등)에 대한 기본 템플릿이다. (사이즈가 보통 수백 메가가 나간다.)

http://www.vagrantbox.es/ 에 보면 공개된 box 파일들이 있다. Ubuntu, Debian 등 다양한 Linux OS 버전의 VM 들에 대한 box 파일들이 있다.

Vagrant file

Vagrant init을 하면, 해당 디렉토리에 “Vagrantfile” 이라는 이름으로 생성되는 파일인데, Box VM 생성을 위한 기본 템플릿이라면, Vagrant file은 생성될 VM에 대한 세부 설정을 정의한다. VM을 생성할때, 어떤 box 파일을 사용할 것인지, VM에 대한 하드웨어 설정 예를 들어 CPU,메모리 사이즈,네트워크, 네트워크 포트포워딩 설정등을 여기서 재정의 할 수 있다.

아래는 Oracle Virtual Box실행시 preceise32 box 이미지를

http://files.vagrantup.com/precise32.box 에서 읽어와서, CPU 2, 512M를 가진 “Terry_vargrant0”이라는 VM을 생성하는 Vagrantfile이다. 아래와 같이 파일을 생성한후에, vagrant up 명령을 수행시키면 설정한 정보 대로 VM이 생성된다.

VAGRANTFILE_API_VERSION = "2"

 

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|

  config.vm.box = "precise32"

  config.vm.box_url = "http://files.vagrantup.com/precise32.box"

  # config.vm.network :forwarded_port, guest: 80, host: 8080

  # config.vm.network :private_network, ip: "192.168.33.10"

  # config.vm.network :public_network

  # config.ssh.forward_agent = true

  config.vm.provider "virtualbox" do |vm|

        vm.customize [

               "modifyvm",:id,

               "--memory","512",

               "--name","Terry_vagrant0",

               "--cpus","2",

                       ]

  end

end

 

Vagrant + Provisioning

Vagrant를 이용하면, VM을 쉽게 만들 수 있다. 그런데 개발환경을 구축하자면, OS가 인스톨된 VM 뿐만 아니라, 그위에 웹서버,DB등 미들웨어들을 설치해야 하고, 그리고 거기에 맞는 Configuration을 해야 한다. 물론 미리 VM 이미지에 웹서버등을 설치해놓고, 필요에 따라서 vagrant를 이용해서 해당 VM들을 설치해서 사용해야 하지만 그 경우에는 설정마다 매번 다른 VM이미지를 만들어놔야 하기 때문에 번거롭다. 만약에 OS 만 설치된 VM에다가, 설정에 따라서 소프트웨어와 설정을 하는 부분을 분리한다면?

이런 접근을 지원하는 기능이 Vagrant provisioning이라는 기능이 있다. VM을 기동한 후에, vagrantfile에 정의된 provisioning script를 수행해준다. 다음 예제를 보자. 다음 예제는 VM이 기동된 후에, apt-get 명령을 이용해서 apache2 (웹서버)를 자동으로 설치하는 설정이다.

VAGRANTFILE_API_VERSION = "2"

 

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|

  config.vm.box = "precise32"

  config.vm.box_url = "http://files.vagrantup.com/precise32.box"

config.vm.provision :shell, :inline => "sudo apt-get install -y apache2"

 

end

위의 예제는 VM이 기동될때 마다 shell 명령어를 수행하도록 한것인데, 명령어말고도 shell스크립트를 수행하게 할 수 도 있고, puppet이나 chef와 같은 configuration management 도구를 이용해서, 제품을 설치하게 할 수 도 있다.

한 가지 주의할점은 Vagrantfile provision 부분에 정의된 명령어는 vagrant up, reload, provision 3개의 명령어가 실행될때 마다 매번 실행된다. up에서도 매번 실행되기 때문에, 스크립트내에, 해당 소프트웨어가 미리 설치되었는지 확인한 후에, 설치가 안되어 있을 경우에만 설치하도록 스크립트를 짜는 것이 좋다.

Provisioning에 대한 자세한 방법은 http://docs.vagrantup.com/v2/provisioning/index.html 를 참고하면 된다.

Vagrant를 이용한 개발 환경 구축

그러면 Vagrant를 이용해서 개발환경을 어떻게 구축할 수 있는지 살펴보도록 하자



크게 그림과 같이 2개의 repository가 필요하다. Box image repository에는 기본 이미지가 인스톨된 box image들을 저장해놓는다.

그리고 svn이나 git와 같은 VCS 툴에 vagrantfile을 저장해놓는다. (아니면 간단하게 웹서버에 저장해놔도 된다.) Vagrantfile에는 box 파일들을 저장해놓은 repository pointing 하도록 하고, 필요에 따라서

1.  Ubuntu + Apache

2.  Ubuntu + MySQL

3.  Ubuntu + Tomcat

와 같이 다양한 설정을 만들어 놓고, 필요에 따라서 Vagrantfile이 받은 후에, 간단하게 “vagrant up” 명령어만 수행하면 간단하게 개발환경에 필요한 VM을 만들어낼 수 있다.

지금까지 간략하게 Vagrant에 개념과 사용법에 대해서 알아보았다.Vagrant는 그외에도, Vagrant는 단일 VM 뿐만 아니라 multi vm을 단일 vagrantfile에서 설정이 가능하고, Oracle Virtual Box뿐만 아니라,VMWare Amazon EC2 클라우드 까지 지원한다. 간단하게는 개발환경에서 부터,응용하면, QA,스테이징,운영환경 배포용으로도 활용할 수 있다.

자세한 내용들은 http://docs.vagrantup.com/ 를 참고하기 바란다

Docker란 무엇인가?

개념 잡기

Docker Linux 기반의 Container RunTime 오픈소스이다. 처음 개념을 잡기가 조금 어려운데, Virtual Machine과 상당히 유사한 기능을 가지면서, Virtual Machine보다 훨씬 가벼운 형태로 배포가 가능하다. 정확한 이해를 돕기 위해서, VM Docker Container의 차이를 살펴보자.

아래는 VM 에 대한 컨셉이다. Host OS가 깔리고, 그 위에 Hypervisor (VMWare,KVM,Xen etc)가 깔린 후에, 그위에, Virtual Machine이 만들어진다. Virtual Machine은 일종의 x86 하드웨어를 가상화 한 것이라고 보면된다. 그래서 VM위에 다양한 종류의 Linux, Windows등의 OS를 설치할 수 있다.



DockerContainer 컨셉은 비슷하지만 약간 다르다. Docker VM 처럼 Docker Engine Host위에서 수행된다. 그리고, Container Linux 기반의 OS만 수행이 가능하다.

Docker VM처럼 Hardware를 가상화 해주는 것이 아니라, Guest OS (Container) Isolation해준다.무슨 말인가 하면, Container OS는 기본적으로 Linux OS만 지원하는데, Container 자체에는 Kernel등의 OS 이미지가 들어가 있지 않다. Kernel Host OS를 그대로 사용하되, Host OS Container OS의 다른 부분만 Container 내에 같이 Packing된다. 예를 들어 Host OS Ubuntu version X이고, Container OS CentOS version Y라고 했을때, Container에는 CentOS version Y full image가 들어가 있는 것이 아니라, Ubuntu version X CentOS version Y의 차이가 되는 부분만 패키징이 된다. Container 내에서 명령어를 수행하면 실제로는 Host OS에서 그 명령어가 수행된다. Host OS Process 공간을 공유한다.



실제로 Container에서 App을 수행하고 ps –ef 를 이용하여 process를 보면, “lxc”라는 이름으로 해당 App이 수행됨을 확인할 수 있다. 아래는 docker를 이용해서 container에서 bash 를 수행했을때는 ps 정보이다. lxc 프로세스로 bash 명령어가 수행되었음을 확인할 수 있다.

root      4641   954  0 15:07 pts/1    00:00:00 lxc-start -n 161c56b9284ffbad0477bd04875c4277be976e2032f3ffa35395950ea05f9bd6 -f /var/lib/docker/containers/161c56b9284ffbad0477bd04875c4277be976e2032f3ffa35395950ea05f9bd6/config.lxc -- /.dockerinit -g 172.17.42.1 -e TERM=xterm -e HOME=/ -e PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin -e container=lxc -e HOSTNAME=161c56b9284f -- /bin/bash

LXC (LinuX Container), 자세한 정보는 http://linuxcontainers.org/ 에서 얻을 수 있다.

lxc container를 실행시켜주는 runtime으로, 앞에서 설명한것과 같이 VM과 비슷한 기능을 제공하지만, 실제 수행에 있어서, guest os (container)를 마치 VM처럼 isolate해서 수행해주는 기능을 제공한다.

이와 같이 Docker LXC라는 Linux에 특화된 feature를 사용하기 때문에, 제약 사항을 가지고 있는데, 현재까지 Docker Ubuntu 12.04 이상(Host OS)에서만 사용이 가능하다.

Performance에 대해서는 당연히 Host OS에서 직접 application 을 돌리는 것보다 performance 감소가 있는데, 아래 표와 같이 performance 감소가 매우 적은 것을 볼 수 있다.



출처: http://www.slideshare.net/modestjude/dockerat-deview-2013

Repository 연계

다음으로 Docker의 특징중의 하나는 repository 연계이다.Container Image를 중앙의 Repository에 저장했다가, 다른 환경에서 가져다가 사용할 수 있다. 마치 git와 같은 VCS (Version Control System)과 같은 개념인데, 이를 통해서 Application들을 Container로 패키징해서 다른 환경으로 쉽게 옮길 수 있다는 이야기다.



예를 들어 local pc에서 mysql, apache, tomcat등을 각 컨테이너에 넣어서 개발을 한 후에, 테스트 환경등으로 옮길때, Container repository에 저장했다가 테스트환경에서 pulling(당겨서) 똑같은 테스트환경을 꾸밀 수 있다는 것이다. Container에는 모든 application과 설치 파일, 환경 설정 정보 등이 들어 있기 때문에, 손쉽게 패키징 및 설치가 가능하다는 장점을 가지고 있다.

여기서 고려해야할점은 Docker는 아쉽게도 아직까지 개발중이고, 정식 릴리즈 버전이 아니다. 그래서, 아직까지는 production(운영환경)에 배포를 권장하고 있지 않다. 단 개발환경에서는 모든 개발자가 동일한 개발환경을 사용할 수 있게 할 수 있고, 또한 VM 보다 가볍기 때문에, 개발환경을 세팅하는데 적절하다고 볼 수 있다.

Base Image vs Dockerfile

Docker Container Image packing하기 위해서, Docker Base Image Docker file이라는 두가지 컨셉을 이용한다. 쉽게 설명하면, Base Image는 기본적인 인스톨 이미지, Docker file은 기본적인 인스톨 이미지와 그 위에 추가로 설치되는 스크립트를 정의한다.

예를 들어 Base Image Ubuntu OS 이미지라면, Docker FileUbuntu OS + Apache, MySQL을 인스톨하는 스크립트라고 보면 된다. 일반적으로 Docker Base Image는 기본 OS 인스톨 이미지라고 보면 된다. 만약에 직접 Base Image를 만들고 싶으면  http://docs.docker.io/en/latest/use/baseimages/ 를 참고하면 된다. docker에서는 미리 prebuilt in image들을 제공하는데, https://index.docker.io/ 를 보면 public repository를 통해서 제공되는 이미지들을 확인할 수 있다. 아직까지는 Ubuntu 많이 공식적으로 제공되고, 일반 contributor들이 배포한 centos 등의 이미지들을 검색할 수 있다. (2013.10.22 현재 redhat 등의 이미지는 없다.)

아래는 docker file 샘플이다. (출처 : http://docs.docker.io/en/latest/use/builder/)

# Nginx

#

# VERSION               0.0.1

 

FROM      ubuntu

MAINTAINER Guillaume J. Charmes <guillaume@dotcloud.com>

 

# make sure the package repository is up to date

RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list

RUN apt-get update

 

RUN apt-get install -y inotify-tools nginx apache2 openssh-server

위의 이미지는 Ubuntu OS 베이스 이미지에 apt-get을 이용해서, inotify-tools nginx apache2 openssh-serverf 를 인스톨하는 스크립트이다.

Docker 실행해보기

그럼 간단하게 docker를 테스트해보자, 윈도우즈 환경을 가정한다. 앞서 말한바와 같이 Docker Unbuntu 위에서만 작동한다. (참고 : http://docs.docker.io/en/latest/installation/windows/)

그래서, 윈도우즈 위에서 Ubuntu VM을 설치한후, Ubuntu VM에서 Docker를 실행할 것이다. 이를 위해서 VM을 수행하기 위한 환경을 설치한다.

l  Hypervisor Virtual Box를 설치한다. https://www.virtualbox.org 

l  VM을 실행하기 위한 vagrant를 설치한다. http://www.vagrantup.com 

l  Docker 코드를 다운받기 위해서 git 클라이언트를 설치한다. http://git-scm.com/downloads 

여기까지 설치했으면, docker를 실행하기 위한 준비가 되었다.

다음 명령어를 수행해서, docker 코드를 git hub에서 다운로드 받은 후에, vagrant를 이용해서 Ubuntu host os를 구동한다.

git clone https://github.com/dotcloud/docker.git

cd docker

vagrant up

Virtual Box를 확인해보면, Docker Host OS가 될 Ubuntu OS가 기동되었음을 확인할 수 있다.



그러면, 기동된 Ubuntu OS SSH를 이용해서 log in을 해보자. Putty를 이용해서 127.0.0.1:2222 포트로, SSH를 통해서 로그인한다. (기본 id,passwd vagrant/vagrant 이다.)

이제 Docker를 이용해서, public repository에서 “busybox”라는 Ubuntu OS Container로 설치하고, Container에서 “echo hello world” 명령어를 수행해보자

sudo su

docker run busybox echo hello world

Docker public repository에서 busybox image를 다운로드 받아서 설치하고, 아래와 같이 명령어를 수행했음을 확인할 수 있다.



※ 참고 : 현재 docker에 설치된 이미지 리스트 docker images, 설치된 이미지를 삭제할려면 docker rmi {image id}. {image id} docker images에서 hexa로 나온 id를 사용하면 된다.