오픈소스배포툴 (propvision tool) 이며환경설정툴 (configuration management tool) 이고 remote 서버에접근후명령실행툴 (ad hoc task execution) 은 puppet, chef, ansible, salt 가유명하다. 여

Similar documents
<313033C8A35FB0F8C7D05FC6AEB7BBB5E55F E74BFCD5F416E C65C0BB5FC0CCBFEBC7D15FB0B3B9DF5FC8AFB0E65FB1B8C3E05F F E687770>

< E74BFCD20416E C65C0BB20C0CCBFEBC7D120B0B3B9DF20C8AFB0E620B1B8C3E C6EDC1FD29322E687770>

opennaru

를 이용한 발 환 Ansible과 Vagrant 개 경구 김 ( 용환 축 #1 이 글은 양이 많은 관계로 다음 주소의 글에 게재된 내용으로 축소되었다. 오타가 많고 정리가 안되었으나, 배경지식을 많이 할애한 관계로 공개

opennaru

Microsoft Word - ntasFrameBuilderInstallGuide2.5.doc

untitled

PowerPoint 프레젠테이션

1. 안드로이드개발환경설정 안드로이드개발을위해선툴체인을비롯한다양한소프트웨어패키지가필요합니다 툴체인 (Cross-Compiler) 설치 안드로이드 2.2 프로요부터는소스에기본툴체인이 prebuilt 라는이름으로포함되어있지만, 리눅스 나부트로더 (U-boot)

1. efolder 시스템구성 A. DB B. apache - mod-perl - PHP C. SphinxSearch ( 검색서비스 ) D. File Storage 2. efolder 설치순서 A. DB (MySQL) B. efolder Service - efolder

PowerPoint Presentation

<31332DB9E9C6AEB7A2C7D8C5B72D3131C0E528BACEB7CF292E687770>

github_introduction.key

ORANGE FOR ORACLE V4.0 INSTALLATION GUIDE (Online Upgrade) ORANGE CONFIGURATION ADMIN O

28 THE ASIAN JOURNAL OF TEX [2] ko.tex [5]

Remote UI Guide

Eclipse 와 Firefox 를이용한 Javascript 개발 발표자 : 문경대 11 년 10 월 26 일수요일

PowerPoint 프레젠테이션

소프트웨어설치 1. 소프트웨어설치및제거 ( 소스코드 ) 소스코드컴파일을이용한 S/W 설치 1. 소스코드다운로드 - 예 ) httpd tar.gz - 압축해제 : #tar xzvf httpd tar.gz - INSTALL 또는 README파일참조

8 장데이터베이스 8.1 기본개념 - 데이터베이스 : 데이터를조직적으로구조화한집합 (cf. 엑셀파일 ) - 테이블 : 데이터의기록형식 (cf. 엑셀시트의첫줄 ) - 필드 : 같은종류의데이터 (cf. 엑셀시트의각칸 ) - 레코드 : 데이터내용 (cf. 엑셀시트의한줄 )

LXR 설치 및 사용법.doc

Microsoft PowerPoint - chap01-C언어개요.pptx

슬라이드 1

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

을풀면된다. 2. JDK 설치 JDK 는 Sun Developer Network 의 Java( 혹은 에서 Download > JavaSE 에서 JDK 6 Update xx 를선택하면설치파일을

DE1-SoC Board

Secure Programming Lecture1 : Introduction

Solaris Express Developer Edition

소개 TeraStation 을 구입해 주셔서 감사합니다! 이 사용 설명서는 TeraStation 구성 정보를 제공합니다. 제품은 계속 업데이트되므로, 이 설명서의 이미지 및 텍스트는 사용자가 보유 중인 TeraStation 에 표시 된 이미지 및 텍스트와 약간 다를 수

PowerPoint 프레젠테이션

Copyright 2012, Oracle and/or its affiliates. All rights reserved.,.,,,,,,,,,,,,.,...,. U.S. GOVERNMENT END USERS. Oracle programs, including any oper

본문서는 초급자들을 대상으로 최대한 쉽게 작성하였습니다. 본문서에서는 설치방법만 기술했으며 자세한 설정방법은 검색을 통하시기 바랍니다. 1. 설치개요 워드프레스는 블로그 형태의 홈페이지를 빠르게 만들수 있게 해 주는 프로그램입니다. 다양한 기능을 하는 플러그인과 디자인

본교재는수업용으로제작된게시물입니다. 영리목적으로사용할경우저작권법제 30 조항에의거법적처벌을받을수있습니다. [ 실습 ] 스위치장비초기화 1. NVRAM 에저장되어있는 'startup-config' 파일이있다면, 삭제를실시한다. SWx>enable SWx#erase sta

6주차.key

/chroot/lib/ /chroot/etc/

PowerPoint 프레젠테이션

슬라이드 1

<C0CCBCBCBFB52DC1A4B4EBBFF82DBCAEBBE7B3EDB9AE2D D382E687770>

ETL_project_best_practice1.ppt

chapter1,2.doc

PowerPoint 프레젠테이션

[Brochure] KOR_TunA

OnTuneV3_Agent_Install

Copyright 2012, Oracle and/or its affiliates. All rights reserved.,,,,,,,,,,,,,.,..., U.S. GOVERNMENT END USERS. Oracle programs, including any operat

슬라이드 1

Microsoft PowerPoint Android-SDK설치.HelloAndroid(1.0h).pptx

Windows 8에서 BioStar 1 설치하기

SQL Developer Connect to TimesTen 유니원아이앤씨 DB 기술지원팀 2010 년 07 월 28 일 문서정보 프로젝트명 SQL Developer Connect to TimesTen 서브시스템명 버전 1.0 문서명 작성일 작성자

기존에 Windchill Program 이 설치된 Home Directory 를 선택해준다. 프로그램설치후설치내역을확인해보면 Adobe Acrobat 6.0 Support 내역을확인할수 있다.

1. What is AX1 AX1 Program은 WIZnet 사의 Hardwired TCP/IP Chip인 iinchip 들의성능평가및 Test를위해제작된 Windows 기반의 PC Program이다. AX1은 Internet을통해 iinchip Evaluation

1. Windows 설치 (Client 설치 ) 원하는위치에다운받은발송클라이언트압축파일을해제합니다. Step 2. /conf/config.xml 파일수정 conf 폴더에서 config.xml 파일을텍스트에디터를이용하여 Open 합니다. config.xml 파일에서, 아

Mobile Service > IAP > Android SDK [ ] IAP SDK TOAST SDK. IAP SDK. Android Studio IDE Android SDK Version (API Level 10). Name Reference V

Spring Boot

MySQL-Ch10

01Àå

Microsoft PowerPoint SDK설치.HelloAndroid(1.5h).pptx

Spring Boot/JDBC JdbcTemplate/CRUD 예제

Microsoft Word - CPL-TR OM2M.doc

ODS-FM1

Microsoft PowerPoint - Smart CRM v4.0_TM 소개_ pptx

Portal_9iAS.ppt [읽기 전용]

Microsoft PowerPoint - 10Àå.ppt

단계

untitled

Sun Java System Messaging Server 63 64

슬라이드 1

Apache Ivy

CD-RW_Advanced.PDF

4S 1차년도 평가 발표자료

Copyright 2004 Sun Microsystems, Inc Network Circle, Santa Clara, CA U.S.A..,,. Sun. Sun. Berkeley BSD. UNIX X/Open Company, Ltd.. Sun, Su

K7VT2_QIG_v3

Assign an IP Address and Access the Video Stream - Installation Guide


서현수

PowerPoint 프레젠테이션

iii. Design Tab 을 Click 하여 WindowBuilder 가자동으로생성한 GUI 프로그래밍환경을확인한다.

Sena Technologies, Inc. HelloDevice Super 1.1.0


목차 BUG offline replicator 에서유효하지않은로그를읽을경우비정상종료할수있다... 3 BUG 각 partition 이서로다른 tablespace 를가지고, column type 이 CLOB 이며, 해당 table 을 truncate

휠세미나3 ver0.4

Snort Install Manual Ad2m VMware libnet tar.gz DebianOS libpcap tar.gz Putty snort tar.gz WinSCP snort rules 1. 첫번째로네트워크설정 1) ifconf

PowerPoint 프레젠테이션

APOGEE Insight_KR_Base_3P11

Tcl의 문법

Microsoft PowerPoint - Chapter_03-1_DevEnv.pptx

리눅스설치가이드 3. 3Rabbitz Book 을리눅스에서설치하기위한절차는다음과같습니다. 설치에대한예시는우분투서버 기준으로진행됩니다. 1. Java Development Kit (JDK) 또는 Java Runtime Environment (JRE) 를설치합니다. 2.

C# Programming Guide - Types

BEef 사용법.pages

Apache2 + Tomcat 5 + JK2 를 사용한 로드밸런싱과 세션 복제 클러스터링 사이트 구축

Web Scraper in 30 Minutes 강철

H3050(aap)

Sena Device Server Serial/IP TM Version

PowerPoint 프레젠테이션

Polly_with_Serverless_HOL_hyouk

YUM(Yellowdog Updater,Modified) : RPM 패키지가저장된서버 ( 저장소 ) 로부터원하는패키지를자동으로설치한다. : YUM 도구는 RPM 의패키지의존성문제를해결

AGENDA 모바일 산업의 환경변화 모바일 클라우드 서비스의 등장 모바일 클라우드 서비스 융합사례

Cloud Friendly System Architecture

게시판 스팸 실시간 차단 시스템

자동화 툴 검토 보고서

Chapter 1

Transcription:

를 이용한 발 환 Ansible과 Vagrant 개 경구 김 (http://knight76.tistory.com) 용환 축 #2 이 글은 양이 많은 관계로 다음 주소의 글에 게재된 내용으로 축소되었다. 오타가 많고 정리가 안되었으나, 배경지식을 많이 할애한 관계로 공개한다. ( http://knight76.tistory.com/entry/%ec%86%8c%ed%94%84%ed%8a%b8%ec%9b%a8%ec %96%B4 %EA%B3%B5%ED%95%99%EC%84%BC%ED%84%B0 %EA%B8%B0%EA%B3% A0 Vagrant%EC%99%80 Ansible%EC%9D%84 %EC%9D%B4%EC%9A%A9%ED%95%9C %EA%B0%9C%EB%B0%9C %ED%99%98%EA%B2%BD ) 순서 Part 2 1. 경 2. ansible 개 2.1. ansible 2.2. ansible 개 2.3. ansible 3. ansible yaml과 playbook 개 3.1. yaml 개 3.2. jinja2 개 3.3. playbook 개 3.4. 개 4.. vagrant/ansible 4.1. 가 4.2. 가 /WAS/DB 4.3. 개 경 5. 결 배 부록 소 및 설치 선택 이유 소 설치 의 소 소 소 소 명령어 소 테스트 시나리오 상 서버 준비 상 서버에 소프트웨어 설치 실제 발 환 론 소 1. puppet 개 2. chef 개 3. docker 개 소 소 을 이용한 개발 환경 구축 예제 Vagrant/Ansible 1. 배경 에서 Oracle Virtual Box와 Vagrant를 설치했고 간단한 provision(배포) 를 설명했다. Part 1

오픈소스배포툴 (propvision tool) 이며환경설정툴 (configuration management tool) 이고 remote 서버에접근후명령실행툴 (ad hoc task execution) 은 puppet, chef, ansible, salt 가유명하다. 여기에서는 salt 를제외한나머지 puppet, chef 를언급하고주제인 ansible 을설명할예정이다. puppet 과 chef, ansible, salt 는오픈소스시스템설정관리소프트웨어 ( 도구 ) 로서, 각각고유한설정명세언어를이용하여환경설정파일또는스크립트를배포할수있는툴이다. 효율적인개발환경및서버관리를지원하여서버환경의인프라를최적화할수있다. 저자는국내의한포털업체서 1000 대가넘는서버에오픈소스 web/was/app 을설치하고, 환경설정파일, 스크립트, 유틸리티를배포하는작업을맡아서진행했다. 이를바탕으로 Web/WAS/APP 배포서버를개발했었다. 당시에는쓸만한유틸리티가전무한상태이기때문에직접만들어서사용했다. 이렇게만든 provision 툴을이용하여 Infra Engineer 로부터서버를받자마자바로설치와배포를완료시켜 web/was 서버를실행할수있도록했다. Concurrent 한환경으로개발하여수십대의서버를순식간에설치하여서비스가되도록하였다. 최적화된인프라를지탱하는솔루션으로 in house 용으로개발하여사용하였다. 그러나이런툴이없는 IT 회사나조직에서는 provision 을하지못하고열악한방식으로구현하였다. 서버에접속해서소스를다운받고컴파일한후서버재시작하는구조로진행했다. 그리고 web 또는 was 환경설정파일은 ftp 로복사하는형태로진행했다. 그리고이렇게한대의서버를구축하고난후, 해당서버의로그를제외한바이너리와설정파일, 스크립트들을모두한번에복사해서다른서버로파일복사하는경우가있다. 만약서버셋팅이 20 대라면 20 대에일일이접속하여설치 / 설정을진행하다보니, 시간이많이소비되었다. 한국뿐아니라전세계적으로아직까지도이렇게작업하고있는현실이다. 참고로아마존 AWS 서비스에서도초기버전에는 provision 툴이없었다. 그러나 Cloud Formation(http://aws.amazon.com/ko/cloudformation/) 이라는툴을공개하여 provision 이쉽게되도록지원하고있다.

< 그림 1> AWS CloudFormation 툴 ( 출처 : http://aws.amazon.com/ko/cloudformation/) 최근전세계적으로 Devops 개발자들의노력으로말미암아오픈소스라이브러리에서오픈소소툴로승화되고있다. In house 용플랫폼으로쓰던제품들이일부오픈소스및상용화하면서 provision 툴에대한마인드가변화되었다. Devops 에대한소개 제임스어쿼트 (James Urquhart) 는클라우드에서돌아가는요즘애플리케이션에여전히회복력과내구성이필요하며, 모니터링이필요하고, 크게변하는부하에대응할필요가있음을설명하면서이를확실히했다. 그러나그는예전에는 IT/ 기반체계운영에서제공된이런기능들이이제는애플리케이션의일부가되어야하며, 특히 " 서비스로서의플랫폼 (Platform as a service)" 환경이되어야한다고

언급했다. 운영은사라지지않으며, 개발의일부가된다. 빅데이터, 웹성능최적화, 애플리케이션미들웨어, 어마어마하게분산된환경에서의내구성을이해하고있는최고의개발자따위를마음에그리기보다, 개발팀에있는운영전문가가필요하다. 기반체계는사라지는것이아니며, 코드로옮겨간다. 그리고기반체계, 시스템관리자및기업의 IT 부서를담당한사람들은발전해서그들의기반체계를유지할수있는코드를작성할수있다. 고립되기보다는, 애플리케이션을만든개발자와협동하고협력할필요가있다. 이런움직임이비공식적으로알려진 " 개발운영 (DevOps)" 이다. 출처 : http://www.hanbit.co.kr/network/view.html?bi_id=1831 현재까지오픈소스 Provision 툴로는 Puppet, Chef 가가장유명하고많은개발자들이쓰고있었다. 그러나최근에는 Salt 나 Ansible 이라는툴이떠오르고있는상황이다. Debian 운영체제안에서이 4 개오픈소스툴의다운로드수를 < 그림 2> 에서확인할수있다. puppet 이가장많이사용하고있으며, 그뒤로 chef, salt, ansible 의순서를보여주고있다. ( 출처 : http://redmonk.com/sogrady/2013/12/06/configuration management 2013/) < 그림 2> Debian 에서의 puppet, chef, salt, ansible 설치횟수 ( 출처 : http://redmonk.com/)

< 그림 3> Debian 에서의 puppet 을제외한 chef, salt, ansible 설치횟수 ( 출처 : http://redmonk.com/) 한편해커뉴스커뮤니티에서언급되고있는수로따지면현재 ansible 이 puppet 이나 chef, salt 보다더높은인기를누리고있음을 < 그림 4> 에서확인할수있다. < 그림 4> 해커뉴스커뮤니티에서주목하고있는 ansible

Github 프로젝트에서 git 저장소에대한관심을 star 마킹을하여체크할수있는데, < 그림 5> 와같이네개의오픈소스 provision 툴중에서는 ansible 이가장인기가많은상태이다. < 그림 5> puppet, chef, ansible, salt GitHub 저장소에서의 star 마킹횟수 또한 GitHub 은 public git 저장소를자기계정의 git 저장소로복사 (fork) 할수있는기능을제공하는데, ansible 이 < 그림 6> 과같이비교표본중가장많은 fork 숫자를포함하고있다.

< 그림 6> puppet, chef, ansible, salt GitHub 저장소에서의 fork 횟수 puppet 과 chef 라는유명한툴이있음에도불구하고 ansible 은빠르게 Devops 개발자들에게최근에많은호감을가지고점점인기가높아지고있다. 구글트렌드에따르면, < 그림 7> 과같이 2013 년초부터급격히 ansible 에대한관심이생긴것을확인할수있다. < 그림 7> 구글트렌드결과 ( 출처 : http://www.google.com/trends) 많은개발자들이 slashdot.org 에서다양한의견을펼친것이있다. 아래링크를살펴보면재미있을것이다. http://tech.slashdot.org/story/13/11/22/0239230/review puppet vs chef vs ansible vs salt 2. ansible 의소개와설치 2.1 ansible 선택이유 저자는 agent 기반과 rsh/ssh 기반으로 provision 방식을개발 / 활용하니, 상황에따라맞는형태가있음을알게되었다. agent 기반이확장성이나추후대규모 provision 를할경우매우효과적인측면이있다. 또한 agent 를 provision 뿐아니라다양한방식으로활용이되는장점이있다. 대신 provision 서버와통신하는부분이고도화된다. 따라서빠르고간단한 provision 을할수없다. 반면, rsh/ssh provision 방식은빠른 provision 이가능하다. 그러나수천대의서버를통제하려면 rsh/ssh 기반은한계가있다. 저자는주관적으로 puppet 과 chef 와 ansible 의비교해보았다. 일부내용은주관적이며, 관련자료는 Part 2 문서의부록을참고한다. 이름 개발언어 정의 agent 인스톨여부 통신방법 공유리파지토리 학습시간 시스템복잡성 github 활동성

puppet ruby DSL ( 독자 ) chef ruby DSL (ruby기반 ) 필요 http ssl 존재중중중 필요 STOMP / rest ansible python yaml 불필요 ssh/jso n 존재상상중 존재하지않음 하하상 가장많이사용하고있는 puppet 이나 chef 대신 ansible 을선택하게된배경은다음의조건이었다. salt 라는 provision 툴도선택가능성안에있지만, ansible 이좀더 community 활동성이좋아서이를선택했다. Mac/Linux 환경를지원해야한다. ( 윈도우환경은지원하지않아도됨 ) Agent 기반이아니고 ssh 기반이어야한다. ( 추후상용환경에서사용할때 Agent 기반이면방화벽이슈, agent 데몬관리라는불편한점이존재한다.) 쉽게사용할수있어야한다. Learning curve 가높지않아야한다. DSL 대신최대한 Standard 을사용해야한다. 테스트환경 (vagrant) 에서사용할수있어야하고서버배포환경에서도사용할수있어야한다. 설정내용은읽기쉬워야한다. 유지보수가편해야하며인수인계가쉽고가능해야한다. 자동배포환경이쉬워야한다. 병렬실행이되어야한다. 앞으로많이개발가능성이높은오픈소스 (github 활동성 ) 여야한다. 멱등성 (idempotence) 이보장되어야한다. * 멱등성 (idempotence) 이란? 연산을여러번적용하더라도결과가달라지지않는성질을멱등성 (idempotence) 이라한다. puppet, chef, ansible 등은모두이런특성을가지고있다. 쉽게말하면, rest api 의경우 get, head,put, delete 메소드는멱등성을가지고있다. 그러나 post 는상태를변하시키기때문에멱등성이없다. 서버의어떤변화를주지않기때문이다. * ansible 툴에서의멱등성이란? 여러번 ansible 툴을사용하더라도동일한결과값을나올수있도록제공되는형태여야한다. 즉매번다른결과가나오거나에러가나온다면비멱등성 (non idempotent) 하다고할수있다. ansible 툴의거의대부분의모듈은멱등성을제공한다. 또한멱등성을제공하기위해서는조건절을제공하고있다. 예를들자면, 처음 ansible 스크립트를실행후다시실행을했다. 상황에따라서는파일이 append 가될수있다. 그러나멱등성의원칙은언제나실행은해도결과가동일하게나온다. 또한파일 / 디렉토리를생성또는삭제하는 create:, remove: 같은 ansible 모듈을실행할때 when: 조건절을이용할수있다. 상태가변경되면 changed_when: 또는 failed_when: 을사용할수있다.

대부분의 ansible 모듈이멱등성 (idempotence) 를보장한다라는의미는상태 (status) 를파악할수있다는의미를가진다. 원래제공한 ansible 모듈은대부분멱등성를제공하나개발자 / 시스템운영자가만든 ansible 스크립트는멱등성를제공하지못할수있다. 따라서멱등성이깨지지않도록주의해야한다. 2.2 ansible 소개 ansible 이라는회사 (ansible inc) 가 ansible 이라는오픈소스 (https://github.com/ansible/ansible) 를기반으로 ansible tower(http://www.ansible.com/home) 를판매하고있다. ansible 오픈소스는무료이나 ansible tower 는유료이다. 여기서얘기하는내용은오픈소스버전이며, ansible tower 는유료이므로이글의작성범위에서벗어나기때문에언급하지않는다. ansible tower 는 ansible 을쉽게사용할수있는 UI 버전과 LDAP 을지원하고있다. ansible provision 툴은현재 Atlassian, Twitter, VeriSign, EA, Evernote, Nasa, Gopro, rackspace, juniper, mapr 등해외유명업체에서사용중이다.

< 그림 8> ansible 홈페이지 ( 출처 : http://www.ansible.com) ansible 은 application 과시스템을쉽게배포할수있도록하는간단한 IT 자동화플랫폼이다. application 을배포, 업데이트할때마다매번서버에접속해서들어가서스크립트를실행하지않아도자동화된형태의언어로 agent 없는리모트환경에 ssh 를이용하여접근하여작업할수있다. 현재 ansible 은오픈소스 (GNU GENERAL PUBLIC 라이선스 ) 이며, < 그림 9> 과같이 https://github.com/ansible/ansible 에서소스를제공하고있다. 특히 793 명의 contributer 가있는것은가장활발히움직이고있음을의미한다. puppet 이나 chef 에서비해서많은개발자들이참여하고있다. 현재 Github 프로젝트중 Python top 10 프로젝트중하나이다.

< 그림 9> ansible github 페이지 (https://github.com/ansible/ansible) 현재 (2014.7.23) 버전은 1.5.3 이며조만간에 1.6.0 이출시될예정이다. ansible 은 ssh( 디폴트 ) 로리모트서버로연결후, ansible module ( 이하 ansible 모듈 ) 이라불리는작은프로그램을전송하여실행한다. 실행이완료후에는해당 ansible 모듈은은삭제한다. ssh 로연결만된다면어떤서버에도접근하여라이브러리모듈을저장할수있다. ansible 모듈은 JSON 으로리턴만하면사용할수있기때문에 ruby, bash, ptyhon 등어떤언어에서라도사용될수있다. 그리고플러그인을제공하여확장이가능하고 callback, python api, 추가기능을구현할수있는큰특징들이있다. 최근에이런 plugin 이확장되면서좋은기능이추가되고있다. ansible 은 YAML 이라는아주간단한포맷의언어를사용하고있다. 쉬운영문을기반으로한 YAML 을이용하여자동화 job 을기술할수있도록한다. YAML 에대한설명은다음장에서진행한다. ansible 은 YAML 기반으로된 playbook 이라는설정파일을자동화된 job 을정의한다. 설치부터복사까지모든작업은이 playbook 에서정의할수있다. 그리고 inventory 라는파일을이용하여서버설정을할수있다.

< 그림 10> ansible 아키텍처 ( 출처 : http://terry.im/wiki/terry/ansible.html) 2.3 ansible 설치 ansible 은 agent 가필요없기때문에서버에만설치하면된다. 서버를 ansible 에서는 control machine 이라부른다. 설치방법은소스, python, yum, apt, freebsd, mac osx 에서쉽게설치할수있다. http://docs.ansible.com/intro_installation.html#installing the control machine 저자는 Mac OSX 사용자이므로 homebrew 를이용하여 ansible 을설치했다. $ brew update $ brew install ansible OS X Mavericks 버전에서는 pip 설치시에는컴파일러이슈가발생할수있다. 이를해결하기위해서는아래와같이사용하여 ansible 을설치한다. $ sudo CFLAGS= Qunused arguments CPPFLAGS= Qunused arguments pip install ansible

만약, 그래도 clang: error: unknown argument: ' mno fused madd' [ Wunused command line argument hard error in future] 이라는에러문구가표시하며해결이되지않는다면다음을실행하여 ansible 을설치한다. XCode 5.1.1. 부터는 unknown argument 는컴파일에러가나도록바뀐듯하다. $ ARCHFLAGS= Wno error=unused command line argument hard error in future pip install ansible 참고로 ansible 를 windows 내설치을공식적으로지원하지는않지만, 개인블로그가 cygwin 을활용하여 windows 에서도 ansible 을사용할수있도록가이드를작성한것이있으니참고한다. https://servercheck.in/blog/running ansible within windows 다음은 ansible 의리모트호스트 (remote host), managed node 는특별히할것은없다. ansible 서버에서해당 node 로 ssh 연결이쉽게될수있도록해당 node 에서 ssh 인증키를생성하고인증키를 ansible 서버에서갖고있도록하면된다. 그리고 node 에서는 python 2.4 이상의버전이설치되어있으면된다. 만약 2.4 버전미만의 python 버전이설치되어있으면, 2.4 이상으로업그레이드를하거나 python simplejson 을반드시설치해야한다. $ pip install simplejson simplejson 으로눈치챘겠지만 json 형태로데이터가전달된다. 에러또는디버그시에 json 형태로결과를리턴받는다. 아래예제는저자의생각없는 copy & paste 를통해서발생한에러정보를 json 으로보여주고있는것을보여주고있다. TASK: [mysql start mysql] *************************************************** failed: [192.168.1.50] => {"failed": true, "item": ""} msg: service not found: tomcat TASK: [mysql shell /usr/bin/mysql u root password= e "CREATE DATABASE IF NOT EXISTS hello; USE hello; CREATE TABLE person (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50));"] *** failed: [192.168.1.50] => {"changed": true, "cmd": "/usr/bin/mysql u root password= e \"CREATE DATABASE IF NOT EXISTS hello; USE hello; CREATE TABLE person (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50));\" ", "delta": "0:00:00.007686", "end": "2014 07 28 06:58:35.883732", "item": "", "rc": 1, "start": "2014 07 28 06:58:35.876046"} stderr: ERROR 1050 (42S01) at line 1: Table 'person' already exists

3. ansible 의 yaml 과 playbook 소개 3.1 yaml 소개 위키 (http://ko.wikipedia.org/wiki/yaml) 에따르면, yaml 은 xml, c, python, perl 에서정의된 email 양식에서개념을얻어만들어진 사람이쉽게읽을수있는 ' 데이터직렬화양식이다. yaml 이라는이름은 YAML ain t Markup Language (YAML 은마크업언어가아니다.) 라는재귀적인이름에서유래되었으나, Yet Another Markup Language ( 또다른마크업언어 ) 이현재공식적인약자이다. yaml 은마크업보다는데이터중심, 즉 serialization format 이라는의미를강조하고있다. 발음은 야믈 ' 이라발음한다. 마치 camel 과음율을맞추는의도를가지고있다. 공식싸이트는 http://yaml.org/ 이다.

< 그림 11> yaml 공식싸이트 http://yaml.org

은 2001년에 1.0 (http://www.yaml.org/spec/history/2001 05 26.html)이 퍼블리싱되었다. 년에는 1.2(http://yaml.org/spec/1.2/spec.html#id2759572)가 퍼블리싱 되었는데. 이 때 json간의 관계를 설명이 되어 있다. 1.2의 변경은 yaml을 json과의 호환을 위해서이다. json과 yaml은 사람이 읽기 편한 데이터 교환 포맷을 목표로하고 있다. json은 간결함과 범용성에 초점을 둔다면, yaml은 json의 장점을 포함하고 임의의 고유 데이터 구조에 대한 직렬화(serialization)을 지원한다. yaml 2009 은 모든 데이터를 리스트, 해쉬, 스칼라 데이터의 조합으로 적절히 표현할 수 있다. 문법이 상대적으로 쉽고 가독성이 좋다. 주요 특징은 다음과 같다. yaml 문자열은 UTF 8 또는 UTF 16과 같이 출력 가능한 유니코드 문자집합을 이용한다. 공백 문자를 이용한 들여쓰기로 구조체를 구분한다. 그러나 탭문자를 들여쓰기에 사용하지 않는다. 리스트 요소는 여러 줄에 쓸 때에는 하이픈( )으로 시작하는 한 줄에 하나의 요소를 표현하며, 한 줄에 모아 쓸 때에는 대괄호([])를 이용하며 쉼표로 각 요소를 구분한다. 해쉬는 콜론 기호를 이용해서 키:값의 형태로 한 줄에 하나를 표현하거나, 한 줄에 모아 쓸 때에는 중괄호({})를 이용하며 쉼표로 각 요소를 구분한다. 간단한 값(스칼라 값)은 보통 아무 표시를 하지 않으나 따옴표("")나 작은 따옴표()를 이용해 둘러쌀 수 있다. 따옴표 안에서 특수 문자는 C언어 스타일(역슬래쉬키와 함께쓰이는 제어문자 예. \n)로 표시한다. 블록 값은 보존( ) 또는 접기(>)의 선택 지시자로 나눈다. 하나의 스트림에 있는 여러 개의 문서는 하이픈 3개( )로 나누며, 마침표 세개(...)로 스트림의 끝을 나타낸다. 반복되는 노드는 기본적으로 &를 통해 나타내며, * 문자 이후의 내용을 참조한다. 주석은 #으로 표시하며, 한 줄이 끝날 때까지 유효하다. 노드들은 타입과 느낌표로 시작해 URI 주소를 지시하는 태그를 통해 라벨이 붙는다. YAML xml 예제를 yaml으로 변경한 사례를 통해서 yaml을 이해한다. xml 예제는 다음과 같다. <recipe> <title>macaroni and Cheese</title> <description>my favorite comfort food.</description> <author>brian Genisio</author> <timetoprepare>30 Minutes</timeToPrepare> <ingredients>

<ingredient> <name>cheese</name> <quantity>3</quantity> <units>cups</units> </ingredient> <ingredient> <name>macaroni</name> <quantity>16</quantity> <units>oz</units> </ingredient> </ingredients> </recipe> 이를 yaml 로바꾸면다음과같다. 특별한설명을하지않아도 attribute 의 key 와 value 값을콜론 (:) 단위로정의하고 list 에대해서는하이픈 ( ) 으로표시한다. Recipe: Title: Macaroni and Cheese Description: My favorite comfort food. Author: Brian Genisio TimeToPrepare: 30 Minutes Ingredients: Name: Cheese Quantity: 3 Units: cups Name: Macaroni Quantity: 16 Units: oz 그리고, json 예제를 yaml 으로변경한사례를통해서 yaml 을이해한다. json 예제는다음과같다. '[ "apple", { "bar": ["baz", "kwa", 3.0, 5] } ]' 이를 yaml 예제로바꾼다면아래와같다. apple bar: baz kwa

3.0 5 ansible 뿐아니라대부분의소프트웨어에서는 yaml 설정파일의확장자는 yml 로정의해서사용하고있다. 참고로독자에게는생소해보일수있는 yaml 은 travis CI, redmine, google app engine, cassandra, google code prettify 외많은오픈소스및솔루션에서설정파일을정의하는데사용하고있다. 3.2 jinja2 소개 yaml 은정적이다. ansible 에서는이를동적으로표현할수있는무엇인가가필요했다. jinja2 (http://jinja.pocoo.org/docs/) 라는 python 라이브러리를이용해서 yaml 문법의단점을보완했다. 일종의템플릿언어 (java 의 freemarker, rythm) 와같다. ntp server 1.1.1.1 로표현했던것을변수선언부에 ntp_variable = 2.2.2.2 를선언하고설정에는 ntp {{ntp_variable}} 로표현가능하다. jinja2 파일은사실상템플릿엔진을사용해서만들파일이기때문에확장자는.j2 로지정한다. 그래서 ansible 예제에서종종보이는템플릿 (template) 디렉토리밑의파일들이.j2 로되어있는것을볼수있다. 예를들어 mysql 의 client.cnf.j2 파일을아래예제와같이저장할수있다. 만약 utf8 변수가 true 이면 default character set 의값을 utf8 로바꾸라는정보를추가할수있다. [client] {% if utf8 %} # apply utf8 default character set = utf8 {% endif %} 단조로울수있는환경배포가 python 모듈 jinja2 를통해서쉽게배포환경을구성할수있다. 3.3 playbook 소개 playbook 은 ansible 의환경설정, 배포를가능케하는언어이다. 리모트서버에접속하여무엇가를실행시키는정책을기술한다. 사람이쉽게읽을수있는 yaml 문법을채용하여정책을기술한다. playbook 은정책을기술하는데, ansible module 을활용한다. playbook 의기본레벨은환경설정이나배포에유용하게사용할수있다. 좀더고급단계에서는특정서버에무엇인가를전달하거나, 로드밸런서나모니터링하는복잡한환경에서사용할수있다.

각 playbook 은하나또는하나이상의 play 를둔다. play 의목적은여러호스트들에잘정의된 role 과 task 를매핑하는역할을한다. < 그림 12> 는 playbook 의구성요소를간단하게설명하고있다. < 그림 12> ansible model ( 출처 : http://www.jedelman.com/home/ansible for networking) role 은 file 들을 include 하거나하나로합칠수있는 (combile) 아이디어를기반으로만들어졌다. 재사용가능한추상화를가능케한다. task 는 ansible 모듈의호출을의미한다. role 의개념을예제를통해서설명한다. tasks/foo.yml 이라는 task 를정의한파일이다. # possibly saved as tasks/foo.yml name: placeholder foo command: /bin/foo name: placeholder bar command: /bin/bar playbook 안에 task 를정의한 tasks/foo.yml 을 include 하는것이가능하다. tasks:

include: tasks/foo.yml 다음은 playbook 안에는아래와같은형태로개발하는데. include 를활용하여복잡하지않도록할수있다. name: this is a play at the top level of a file hosts: all remote_user: root tasks: name: say hi tags: foo shell: echo "hi..." include: load_balancers.yml include: webservers.yml include: dbservers.yml role 를좀더관리를편하게하기위해사용할수있다. host inventory 파일에정의한서버그룹별로각각나우어 provision 할수있도록할수있다. 예를들어 inventory 파일에서 dbservers 와 webservers 로나눈경우라면 role 의개념을잘이용하여설치정보를디렉토리로나눌수있다. common, dbservers, webservers 이렇게디렉토리를나누어서 db 를설치할때는 common 디렉토리의 yml 파일과 dbservers 의 yml 을읽어설치하게하고 web 서버를설치할때는 common 디렉토리의 yml 파일과 webservers 디렉토리의 yml 을설치하게할수있다. 변수선언은 vars 문안에서정의한다. http_port 는 80 으로초기화한다. hosts: webservers vars: http_port: 80 미리정의된 base_path 변수의값의 app 디렉토리스트링값을 app_path 에저장한다. hosts: app_servers vars: app_path: "{{ base_path }}/app" 그것외에변수의디폴트값을넣는다거나, for 문을동작시킬수있다. {{ some_variable default(5) }} {% for host in groups['app_servers'] %} {{ hostvars[host]['ansible_eth0']['ipv4']['address'] }}

{% endfor %} command 바깥에서변수를받을수있다. $ ansible playbook release.yml extra vars "host=127.0.0.1 user=vagrant" playbook 파일 hosts: '{{ hosts }}' remote_user: '{{ user }}' 그리고조건문을제공한다. when, false_when 등다양한조건문을지원한다. ansible 노드가 Debian 이면운영체제를바로셧다운하라지정한다. tasks: name: "shutdown Debian flavored systems" command: /sbin/shutdown t now when: ansible_os_family == "Debian" 마지막으로루프 (loop) 를제공한다. wheel 그룹으로 testuser1, testuser2 계정을추가하는명령어를루프를통해서진행할수있다. name: add several users user: name={{ item }} state=present groups=wheel with_items: testuser1 testuser2 여러파라미터를두어 group 별로지정을할수있다. name: add several users user: name={{ item.name }} state=present groups={{ item.groups }} with_items: { name: 'testuser1', groups: 'wheel' } { name: 'testuser2', groups: 'root' } 3.3 inventory 소개 inventory 파일은리모트서버에대한 meta 데이터를기술하는파일이다. ansible 에서는 inventory 파일에는 yaml 은적용하지않았다.

기본파일은 /etc/ansible/hosts 을읽게하거나, 따로 inventory 파일을만들고따로옵션을주어동작하게할수있다. 다음은 hosts 파일예제이다. [, ] 안에있는이름이그룹이름이고, 호스트명 (host) 은해당그룹에속한다. webservers 와 dbservers 로나누어서작업을할수있도록그룹핑이되어있다. [webservers] foo.example.com bar.example.com [dbservers] one.example.com two.example.com three.example.com 만약고정 ip 를가지고있고 hosts 파일안에들어가있지않는서버가있다면아래와같이설정파일을만들수있다. 192.168.1.50 ip 를가진서버에 22 번 ssh 포트로 vagrant 계정으로접근할수있도록한다. 이는테스트환경을만들때매우유용하다. 192.168.1.50 ansible_ssh_user=vagrant ansible_ssh_port=22 3.4 명령어소개 ansible playbook 와 ansible 명령어가있다. ansible playbook 명령어는 playbook yaml 파일을실행한다. 아래예제는 /etc/ansible/hosts inventory 파일을사용하지않고따로정의된 hosts inventory 파일을기반으로 playbook 으로정의한 webservers.yml 을실행시키라는명령어이다. $ ansible playbook i hosts webservers.yml 리모트호스트에접근하여특정명령어를실행할수있다. ansible 에서는 ad hoc task 실행이라한다. ansible playbook 이아닌 ansible 명령어를이용해야한다. 아래예제는따로정의된 production inventory 파일에저장된모든호스트에서대해서재부팅을명령하는 $ ansible boston i production m command a '/sbin/reboot' 만약에러가발생하면 verbose 옵션을주어자세한내용을얻을수있다. $ ansible playbook i hosts playbook.yml vvvv PLAY [all] ********************************************************************

GATHERING FACTS *************************************************************** <192.168.1.50> ESTABLISH CONNECTION FOR USER: vagrant <192.168.1.50> REMOTE_MODULE setup <192.168.1.50> EXEC ['ssh', ' C', ' tt', ' vvv', ' o', 'ControlMaster=auto', ' o', 'ControlPersist=60s', ' o', 'ControlPath=/Users/knight/.ansible/cp/ansible ssh %h %p %r', ' o', 'Port=22', ' o', 'KbdInteractiveAuthentication=no', ' o', 'PreferredAuthentications=gssapi with mic,gssapi keyex,hostbased,publickey', ' o', 'PasswordAuthentication=no', ' o', 'User=vagrant', ' o', 'ConnectTimeout=10', '192.168.1.50', "/bin/sh c 'mkdir p $HOME/.ansible/tmp/ansible tmp 1406200040.69 215131276335574 && chmod a+rx $HOME/.ansible/tmp/ansible tmp 1406200040.69 215131276335574 && echo $HOME/.ansible/tmp/ansible tmp 1406200040.69 215131276335574'"] fatal: [192.168.1.50] => SSH encountered an unknown error. The output was:... 4. vagrant/ansible 테스트시나리오 4.1 가상서버준비 virtualbox/vagrant 와 ansible 을간단하게연동하는예제를진행한다. 리눅스버전중하나인 ubuntu 의 12.04 버전이며 64 비트버전인 precise64 를기반으로예제를준비했다. 가상서버 (192.168.1.50) 가실행중인상태에서 Vagrant 파일, hosts 파일, playbook.yml 을추가하였다. 이해도를높이기위해서 vagrant 작업은두번진행한다. 먼저 Vagrant 파일은아래와같이생성한다. $ mkdir p idp testbox $ cd idp testbox $ 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.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"

end end hosts 파일은다음과설정한다. 192.168.1.50 ansible_ssh_user=vagrant ansible_ssh_port=22 playbook.yml 파일은다음과같다. /user/local 디렉토리리스트를하고 ansible 로그결과를로그로찍도록한다. $ cat playbook.yml hosts: all user: vagrant tasks: name : test action: command ls al /usr/local register: vagrant debug: var=vagrant.stdout_lines vagrant up 명령을실행하면. provision 까지진행하면성공하는결과화면이보인다. < 그림 13> 과같이 virtualbox 리스트화면을확인할수있다. $ vagrant up Bringing machine 'default' up with 'virtualbox' provider... ==> default: Importing base box 'precise64'... ==> default: Matching MAC address for NAT networking... ==> default: Setting the name of the VM: idp testbox_default_1406257067416_3765 ==> default: Clearing any previously set network interfaces... ==> default: Preparing network interfaces based on configuration... default: Adapter 1: nat default: Adapter 2: hostonly ==> default: Forwarding ports... default: 9966 => 8888 (adapter 1) default: 22 => 2222 (adapter 1) ==> default: Booting VM... ==> default: Waiting for machine to boot. This may take a few minutes... default: SSH address: 127.0.0.1:2222 default: SSH username: vagrant default: SSH auth method: private key default: Warning: Connection timeout. Retrying... ==> default: Machine booted and ready! ==> default: Checking for guest additions in VM... default: The guest additions on this VM do not match the installed version of default: VirtualBox! In most cases this is fine, but in rare cases it can default: prevent things such as shared folders from working properly. If you see default: shared folder errors, please make sure the guest additions within the

default: virtual machine match the version of VirtualBox you have installed on default: your host and reload your VM. default: default: Guest Additions Version: 4.2.0 default: VirtualBox Version: 4.3 ==> default: Setting hostname... ==> default: Configuring and enabling network interfaces... ==> default: Mounting shared folders... default: /vagrant => /development/work/idp testbox ==> 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 40", "drwxr xr x 10 root root 4096 Sep 14 2012.", "drwxr xr x 10 root root 4096 Sep 14 2012..", "drwxr xr x 2 root root 4096 Sep 14 2012 bin", "drwxr xr x 2 root root 4096 Sep 14 2012 etc", "drwxr xr x 2 root root 4096 Sep 14 2012 games", "drwxr xr x 2 root root 4096 Sep 14 2012 include", "drwxr xr x 3 root root 4096 Sep 14 2012 lib", "lrwxrwxrwx 1 root root 9 Sep 14 2012 man > share/man", "drwxr xr x 2 root root 4096 Sep 14 2012 sbin", "drwxr xr x 6 root root 4096 Sep 14 2012 share", "drwxr xr x 2 root root 4096 Sep 14 2012 src" ] } PLAY RECAP ******************************************************************** default : ok=3 changed=1 unreachable=0 failed=0

< 그림 13> vagrant up 실행후 virtualbox 화면이제는 web 이라는 virtualbox 의 gui 이름을주도록한다. Vagrant 파일을아래와같이수정한다. config.vm.provider 의이름을 web 으로변경하도록한다. $ 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.hostname = "web" config.vm.network "private_network", ip: "192.168.1.50" config.vm.network :forwarded_port, guest: 9966, host: 3333

end config.vm.provider :virtualbox do vb vb.name = "web" end config.vm.provision "ansible" do ansible ansible.playbook = "playbook.yml" end vagrant reload 명령을내려서다시가상서버를실행한다. < 그림 14> 와같이 virtualbox 에 web 이라는이름을변경했다. vagrant up 하면서 provision 한부분때문에다시진행하지는않는다. $ vagrant reload ==> default: Attempting graceful shutdown of VM... ==> default: Setting the name of the VM: web ==> default: Clearing any previously set forwarded ports... ==> default: Clearing any previously set network interfaces... ==> default: Preparing network interfaces based on configuration... default: Adapter 1: nat default: Adapter 2: hostonly ==> default: Forwarding ports... default: 9966 => 3333 (adapter 1) default: 22 => 2222 (adapter 1) ==> default: Booting VM... ==> default: Waiting for machine to boot. This may take a few minutes... default: SSH address: 127.0.0.1:2222 default: SSH username: vagrant default: SSH auth method: private key ==> default: Machine booted and ready! ==> default: Checking for guest additions in VM... default: The guest additions on this VM do not match the installed version of default: VirtualBox! In most cases this is fine, but in rare cases it can default: prevent things such as shared folders from working properly. If you see default: shared folder errors, please make sure the guest additions within the default: virtual machine match the version of VirtualBox you have installed on default: your host and reload your VM. default: default: Guest Additions Version: 4.2.0 default: VirtualBox Version: 4.3 ==> default: Setting hostname... ==> default: Configuring and enabling network interfaces...

==> default: Mounting shared folders... default: /vagrant => /development/work/idp testbox ==> default: Machine already provisioned. Run `vagrant provision` or use the ` provision` ==> default: to force provisioning. Provisioners marked to run always will still run. < 그림 14> vagrant 설정의 provider 이름을변경하고, vagrant reload 실행한 virtualbox 화면가장먼저 ssh인증서를복사해서로컬장비에서가상서버로접근할수있도록한다. $ ssh copy id vagrant@192.168.1.50 그리고, playbook 을실행하였다. 다음의 provision 결과를얻을수있다. $ ansible playbook i hosts playbook.yml

PLAY [all] ******************************************************************** GATHERING FACTS *************************************************************** ok: [192.168.1.50] TASK: [test] ****************************************************************** changed: [192.168.1.50] TASK: [debug var=vagrant.stdout_lines] **************************************** ok: [192.168.1.50] => { "vagrant.stdout_lines": [ "total 40", "drwxr xr x 10 root root 4096 Sep 14 2012.", "drwxr xr x 10 root root 4096 Sep 14 2012..", "drwxr xr x 2 root root 4096 Sep 14 2012 bin", "drwxr xr x 2 root root 4096 Sep 14 2012 etc", "drwxr xr x 2 root root 4096 Sep 14 2012 games", "drwxr xr x 2 root root 4096 Sep 14 2012 include", "drwxr xr x 3 root root 4096 Sep 14 2012 lib", "lrwxrwxrwx 1 root root 9 Sep 14 2012 man > share/man", "drwxr xr x 2 root root 4096 Sep 14 2012 sbin", "drwxr xr x 6 root root 4096 Sep 14 2012 share", "drwxr xr x 2 root root 4096 Sep 14 2012 src" ] } PLAY RECAP ******************************************************************** 192.168.1.50 : ok=3 changed=1 unreachable=0 failed=0 4.2 가상서버에소프트웨어 /WAS/DB 설치 https://bitbucket.org/gerrytan/jpaminimal (jpaminimal 예제 ) 로공개한소스를가지고테스트를진행한다. ( 자세한소스설명은 http://gerrydevstory.com/2014/03/03/creating a minimal spring mvc jpa hibernate and mysql pro ject/ 을참조한다.) 이예제는 tomcat 위에서동작하는 was 는 JPA/Hibernate 를이용하여 mysql db 를연결하고간단한 web ui 를보여주는웹어플리케이션이다. setup.yml 파일을만들어아래의예제와같이설치할수있다. 모든 host inventory 에정의된 host 파일에 vagrant user 로접근후, sudo 권한으로 git 패키지외 3 종류의소프트웨어를설치하고 mysql 5.5 서버를설치한후 mysql 데몬을시작하도록한다.

hosts: all user: vagrant sudo: True tasks: name: common install apt: pkg={{ item }} state=latest update_cache=yes tags: packages with_items: maven ant zip git name: MySQL install apt: pkg=mysql server 5.5 state=present update_cache=yes tags: mysql name: MySQL start service: name=mysql state=started tags: mysql 설치소프트웨어가많아질수록라인수는점점커지고길어질수있다. 따라서적절히디렉토리를나누고설정파일을분할할필요가있다. ansible 에서정리한 best practice (http://docs.ansible.com/playbooks_best_practices.html) 와 role 모델 (http://docs.ansible.com/playbooks_roles.html) 정보를기반으로구성하였다. < 그림 15> 의디렉토리구조와파일형태를최대한활용했다. 이렇게사용하면분할된 role 으로나뉘다보니복잡성은사라지고유지보수관리가편해지는장점이있다.

< 그림 15> ansible 의 role 관점의디렉토리구조정보 ( 출처 : http://docs.ansible.com/playbooks_roles.html) 저자는 < 그림 16> 과같이디렉토리구조를사용했다.

< 그림 16> playbooks 예제디렉토리구조 설치기본파일은 playbooks 디렉토리밑에 setup.yml 로한다. 아래는 playbooks/setup.yml 파일이다. vagrant user 로 sudo 권한으로 common, java, compile, mysql, tomcat role 순서대로설치하도록한다. hosts: all user: vagrant sudo: True roles: common java compile mysql tomcat

common role 은가상서버에서사용할공통유틸리티를설치하는내용을정의한다. common 디렉토의 main.yml 파일을찾는다. common/vars/main.yml 파일이다. 유틸리티 zip, git, maven, ant 를정의한다. packages: zip git maven ant common/tasks/main.yml 파일에서는 packages.yml 파일을 include 하고 common/vars/main.yml 에서 packages 값을전달한다. include: packages.yml tags=packages common/tasks/packages.yml 파일은 apt get 으로 zip, git, maven, ant 를설치하라고한다. name: install packages apt: pkg={{ item }} state=latest update_cache=yes with_items: packages 다음은 oracle 의 jdk 7 을설치하도록하는 java/tasks/main.yml 파일이다. oracle jdk 를바로다운이쉽지않다. apt get 으로다운받을수있도록준비하고다운받도록한다. ( 이런방법이항상통할수없다. 가장좋은방법은미리 oracle jdk 를다운받은후가상서버로복사하는것일수있다.) name: ensuring add apt repository is installed apt: pkg=python software properties state=latest name: adding webupd8 ppa for java7 installer apt_repository: repo=ppa:webupd8team/java name: updating apt cache apt: update_cache=yes name: installing java7 shell: echo debconf shared/accepted oracle license v1 1 select true debconf set selections && echo debconf shared/accepted oracle license v1 1 seen true debconf set selections &&

apt get y install oracle java7 installer 지금까지공통유틸리티와 oracle java7 설치를완료했다. 이제는소스를 clone 하고컴파일을한다. compile/vars/main.yml 파일이다. jpaminimal 예제의 git url 정보와 clone 되고난후저장할가상서버위치를변수로지정한다. git_clone_url: https://bitbucket.org/gerrytan/jpaminimal.git git_location: /app/git compile/tasks/main.yml 파일로서, 가상서버의 clone 된파일을모두지우고 clone 을진행한후, maven 빌드를진행한후디렉토리 permission 을 vagrant.vagrant 로수정한다. name : delete git cloned directory shell: rm rf {{ git_location }} name : git clone git: repo={{ git_clone_url }} dest={{ git_location }} update=no name : mvn compile command: chdir={{ git_location}} mvn package name: change permission file: path=/app/git owner=vagrant group=vagrant state=directory recurse=yes 다음은 mysql 설치를진행한다. mysql/vars/main.yml 파일이다. utf8 로설정했고 mysqld 설정으로 bind_adress 를지정한다. utf8: true mysqld: bind_address: 127.0.0.1 mysql/tasks/main.yml 파일이다. /usr/bin/mysqld 파일이있으면 mysql 을설치하지않도록했다. 그리고 templates/mysqld.conf.j2 (jinja2 파일 ) 을가성서버에 mysqld.conf 파일로복사하도록하였다. 이렇게하여변수나이벤트시설정파일을동적으로변경시킬수있도록하였다. ( 예, utf8 변수선언 ) was 에서사용할논리 DB 의 table 을매번삭제하고재생성하도록한후 mysqld 데몬을재실행하도록하였다. stat: path=/usr/bin/mysqld

register: mysqld_exist name: mysql 5.5 installation apt: pkg=mysql server 5.5 state=present update_cache=yes when: mysqld_exist.stat.exists == false name: copy conf.d/mysqld.cnf action: template src=mysqld.cnf.j2 dest=/etc/mysql/conf.d/mysqld.cnf notify: restart mysql shell: /usr/bin/mysql u root password= e "DROP TABLE IF EXISTS hello ; CREATE DATABASE IF NOT EXISTS hello; USE hello; CREATE TABLE person (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50));" ignore_errors: True when: mysqld_exist.stat.exists == true name: start mysql service: name=mysql state=restarted enabled=yes sudo: True mysql/template/mysql.conf.j2 파일이다. jinja2 의스크립트가사용되었다. utf8 변수가정의되어있다면언어설정에 utf8 을설정값을저장하도록한다. [mysqld] {% if utf8 %} character set server = utf8 collation server = utf8_unicode_ci {% endif %} mysql/handlers/handlers.yml 파일은 tasks.yml 에서정의한 copy conf.d/mysqld.cnf 이름을가진 task 가완료되면 handler 로 notify 할수있다. mysql 데몬을재시작하도록한다. name: restart mysql action: service name=mysql state=restarted enabled=yes 마지막은 tomcat 설치부분이다. tomcat/vars/main.yml 에는가상서버에 tomcat 이저장할위치를지정한다. tomcat_dir: /app/tomcat

tomcat/tasks/main.yml 파일은톰캣설치에대한정보를언급하고있다. 웹에서다운받아서 tomcat_dir 에저장하도록한후, compile 된 war 파일을 webapps 디렉토리에복사한다. 그리고 tomcat 실행파일 (tomcat initscript.sh) 과 tomcat 설정파일 (server.xml) 을가상서버에잘복사하도록한다. 그리고 service 데몬으로 tomcat 을실행한다. 마지막으로는톰캣이제대로실행되어 8080 포트가 alive 한지 wait 한다. 만약정상이면 play 를종료한다. name: check if tomcat path exists stat: path=/app/src name: if tomcat dir exists stat: path=/app/tomcat name: download Tomcat get_url: url=http://archive.apache.org/dist/tomcat/tomcat 7/v7.0.54/bin/apache tomcat 7.0.54.tar.gz dest=/app/src/apache tomcat 7.0.54.tar.gz name: extract archive tomcat command: chdir=/app /bin/tar xvf /app/src/apache tomcat 7.0.54.tar.gz C /app/ creates=/app/apache tomcat 7.0.54 name: symlink install directory file: src=/app/apache tomcat 7.0.54 path=/app/tomcat state=link name: change ownership of Tomcat installation file: path=/app/tomcat owner=vagrant group=vagrant state=directory recurse=yes name: configure Tomcat server template: src=server.xml dest={{ tomcat_dir }}/conf/ notify: restart tomcat name: copy war to webapps command: cp {{ git_location }}/target/hello 1.0.war {{ tomcat_dir }}/webapps name: install Tomcat init script copy: src=tomcat initscript.sh dest=/etc/init.d/tomcat mode=0755 name: start Tomcat service: name=tomcat state=restarted enabled=yes register: result debug: var=result

name: wait for tomcat to start wait_for: port=8080 tomcat/handlers/handlers.yml 은다음과같다. tomcat task 에서정의한설정파일복사 task 가완료되면아래이벤트가 notify 되어재시작을하도록한다. name: restart tomcat service: name=tomcat state=restarted tomcat/templates/server.xml 은사용자정의된형태로저장한다. 데모에서는특별히바꾼것은없다. 그리고 service 데몬으로쓰기위해서 tomcat/files/tomcat initscript.sh 파일은다음과같다. 이파일은 https://gist.github.com/valotas/1000094 파일을그대로활용했다. tomcat 구동스크립트는 init.d 기준으로하지않으나, tomcat 을 service 명령어를통해서사용할수있는좋은예제라서참고하였다. #!/bin/bash # # chkconfig: 345 99 28 # description: Starts/Stops Apache Tomcat # # Tomcat 7 start/stop/status script # Forked from: https://gist.github.com/valotas/1000094 # @author: Miglen Evlogiev <bash@miglen.com> # # Release updates: # Updated method for gathering pid of the current proccess # Added usage of CATALINA_BASE # Added coloring and additional status # Added check for existence of the tomcat user # #CATALINA_HOME is the location of the bin files of Tomcat export CATALINA_HOME=/app/tomcat #CATALINA_BASE is the location of the configuration files of this instance of Tomcat export CATALINA_BASE=/app/tomcat #TOMCAT_USER is the default user of tomcat export TOMCAT_USER=vagrant #TOMCAT_USAGE is the message if this script is called without any options TOMCAT_USAGE="Usage: $0 {\e[00;32mstart\e[00m \e[00;31mstop\e[00m \e[00;32mstatus\e[00m \e[00;31mrestart\e[00m}"

export JAVA_OPTS=" Dname=tomcat" #SHUTDOWN_WAIT is wait time in seconds for java proccess to stop SHUTDOWN_WAIT=20 tomcat_pid() { echo `ps fe grep $CATALINA_BASE grep v grep tr s " " cut d" " f2` } start() { pid=$(tomcat_pid) if [ n "$pid" ] then echo e "\e[00;31mtomcat is already running (pid: $pid)\e[00m" else # Start tomcat echo e "\e[00;32mstarting tomcat\e[00m" #ulimit n 100000 #umask 007 #/bin/su p s /bin/sh tomcat if [ `user_exists $TOMCAT_USER` = "1" ] then su $TOMCAT_USER c $CATALINA_HOME/bin/startup.sh else sh $CATALINA_HOME/bin/startup.sh fi status fi return 0 } status(){ pid=$(tomcat_pid) if [ n "$pid" ]; then echo e "\e[00;32mtomcat is running with pid: $pid\e[00m" else echo e "\e[00;31mtomcat is not running\e[00m" fi } stop() { pid=$(tomcat_pid) if [ n "$pid" ] then echo e "\e[00;31mstoping Tomcat\e[00m" #/bin/su p s /bin/sh tomcat sh $CATALINA_HOME/bin/shutdown.sh

let kwait=$shutdown_wait count=0; until [ `ps p $pid grep c $pid` = '0' ] [ $count gt $kwait ] do echo n e "\n\e[00;31mwaiting for processes to exit\e[00m"; sleep 1 let count=$count+1; done if [ $count gt $kwait ]; then echo n e "\n\e[00;31mkilling processes which didn't stop after $SHUTDOWN_WAIT seconds\e[00m" kill 9 $pid fi else echo e "\e[00;31mtomcat is not running\e[00m" fi return 0 } user_exists(){ if id u $1 >/dev/null 2>&1; then echo "1" else echo "0" fi } case $1 in start) start ;; stop) stop ;; restart) stop start ;; status) status

;; *) ;; esac exit 0 echo e $TOMCAT_USAGE playbook 결과는로그를확인하면된다. 특별히 fail 난부분이없다. 이제가상서버의 was 서버에접근한다. host inventory 파일에서정한대로이용한다. http://192.168.1.50:8080/hello 1.0/ 을웹으로접속하면 < 그림 17> 화면과같이정상적으로작동하는지확인이가능하다. < 그림 17> jpaminimal 예제의웹 UI jpaminimal 예제는 https://github.com/knight1128/vagrant ansible testbox 를참조하면된다. 4.3 실제개발환경 4.2 의 jpaminimal 예제의경우는워낙간단해서가상환경이필요하지않을수있다. 그러나저자의경우는화이트박스테스트케이스가없는 Legacy 환경에서는반드시필요했다. 일반유틸리티에 java, mysql, tomcat, nodejs 소프트웨어를설치하고 java was 서버한대, java 프로세스 6 대, node js 프로세스 6 대, mysql 1 대를설치도 4.2 에서언급한방식으로쉽게개발환경을구성할수있다. 이개발환경을그대로개발자끼리공유해서환경구성시간을최대한줄일수있었다. ( 설치등등 ) 또한 vagrant/ansible 가상서버테스트환경을바탕으로 API 테스트를진행할수있다. jmeter 나 soapui 를활용할수있다. < 그림 18> 의 jmeter 를구성하여테스트환경을구축할수있다.

< 그림 18> jmeter 개발환경 만약 UI 가있는경우라면, acceptance 테스트또는 funtional 테스트가가능하다. HtmlUnit, Selenium 과같은툴로 UI 를테스트하며명확한테스트를진행할수있을것이다. 그리고, QA 나연동개발이필요한개발자에게는가상서버테스트환경기반의 UI admin 을따로둘수있다. 가상서버로 api 호출과응답을체크하는 admin 서버를만들수있다. 좀더고급스럽게개발한다면 facebook 의개발자센터와같은형태도가능하다. 5. 결론

지금까지 vagrant/ansible 을활용한개발자환경을구성해보았다. 가상머신을통제하는 vagrant 와환경구성툴인 ansible 을이용한다면개발자간, 또는개발자 QA, 개발자 관리자간원활한소통을이어줄수있을것이다. ansible 은 vagrant 뿐아니라 docker 와도연동가능하기때문에다른개발환경을구축할수있다. 그리고 ansible 의고급기능은 production 레벨에서서버배포환경및서버모니터링연동도쓰일수있는훌륭한상용배포툴로사용가능하다. 최근에트렌디하게사용하고있는 Continuous Deployment 를구현할수있다. 그리고 ansible 을 push 방식으로쓰기로하지만, pull 방식으로쓸수있다. 즉상용서버에서 git repository 로 cronjob 으로소스 checkout 을받아서버설정의현행화를할수있다. ansible 은계속발전되고있기때문에앞으로배워두면많은도움이될것이라생각된다. 참고 1. http://redmonk.com/sogrady/2013/12/06/configuration management 2013/ 2. http://en.wikipedia.org 3. http://ko.wikipedia.org

부록 1. puppet 소개 puppet 은 ruby 언어로개발되었고 2005 년 puppet labs(http://puppetlabs.com/) 에서발표하였다. 초기버전은 GPL 라이선스였으나, 2.7.0 버전후에는 Apache 라이선스 2.0 으로변경했다. 대표적적용회사로서 twitter, redhat, salesforce, starbucks, at&t 에서채택되어사용중이다. < 그림 19> 은 puppet 홈페이지이다. < 그림 19> puppet 홈페이지 ( 출처 : http://puppetlabs.com/)

enterprise 버전은유료이나, 오픈소스버전 (https://github.com/puppetlabs/puppet) 은무료로사용할수있다. 제약조건은 < 그림 20> 를참조한다. 중요한관리부분은 puppet 오픈소스부분에서사용가능하다. 그러나지원은받을수없다. < 그림 20> puppet 의상용버전과오픈소스버전차이 ( 출처 :http://puppetlabs.com/puppet/enterprise vs open source) puppet 은 server 와 agent 간의통신체계를근간으로되어있다. 따라서 server, agent 각각설치한다. 그리고통신은 SSL 로통신하도록되어있다. puppet server 에는설정내용을담고있고 puppet agent 를통해서 provision 된다. puppet agent 가설치된서버를 node 라불린다. puppet agent 가 server 로계속주기적으로요청하는클라이언트 서버아키텍처를지원하기때문에 puppet agent 가대량의서버에설치될경우 puppet 서버에부하를발생할수있는단점이있다. 그리고 puppet server 에서특정서버만테스트하려면운영의노하우가필요하다. < 그림 21> 은 puppet 아키텍처를표현한그림이다.

< 그림 21> puppet 아키텍처 ( 출처 : http://www.slashroot.in) 설정파일은독자적인 DSL 기반 (manifest) 을정의하여시스템관리를한다. 그리고다양한 OS 환경에서도추상화된레이어를제공하여단일 manifest 에서실행할수있도록하였다. 따라서리눅스버전마다다른 yum, apt get 같은설치방법을최소화하였다. 리소스의존성을가지게하였고 LDAP 을지원한다. puppet 에대해서궁금한독자는아래싸이트를참조하면된다. http://docs.puppetlabs.com/ http://puppetcookbook.com/ 2. chef 소개 chef 는 puppet 과마찬가지로 ruby 언어로개발되었다. Opscode 사에의해서 2009 년출시되었다. 이후 Chef 라는회사명으로변경되었다. < 그림 22> 은 chef 홈페이지이다. chef 는 facebook, splunk 등과같은쟁쟁한회사에서많이사용하고있다. 최근에는 Amazon 의 aws 서비스에서적용되어 chef 를사용할수있다.

< 그림 22> chef 홈페이지 ( 출처 : http://www.getchef.com/) ruby 언어기반으로 DSL 방식 (recipes, cookbooks) 으로시스템설정을정의한다. ruby 언어를잘아는사람에게는좋은장점이된다. chef 는 cookbook 을정의한다. 즉 cookbook 은요리책으로서형상관리할대상을어떻게요리할지작성한다. cookbook 안에 recipe 가존재하며, recipe 는하나의인프라를관리한다. 이런모델링의내용이 chef 의가장중요한부분이다. 리소스와서버간의연동관계를잘정의되어있는장점이있는반면, 배우는입장에서는학습시간이많이필요하다는단점이있다. 자세한모델링에대한내용은 < 그림 23> 을참조한다.

< 그림 23> chef 사용모델 ( 출처 : http://magazine.rubyist.net/?0035 ChefInDECOLOG) puppet 과마찬가지로 chef 도클라이언트 서버아키텍처기반으로되어있다. < 그림 24> 에서보듯이특이한점은 chef server 를 knife 로통제하는 chef development machine (chef workstation) 이존재한다. chef node 는배포될서버들이다. < 그림 24> chef 간략아키텍처 ( 출처 : http://tasting.solita.fi/chef)

chef 서버는다른시스템과연동을위한 rest api 를제공하고있다. 노드및 cookbook 를각 node 에배포하며통제하는역할을한다. chef indexer 라는시스템이있는데, chef 환경에서검색이필요한작업을책임진다. < 그림 25> 과같은구성아키텍처를통해확인할수있다. 특히 CouchDB 를설치해서 chef 서버와연동하도록해야하며또한 chef indexer 안에는 rabbitmq 가있어이를미리설치해야한다. 통신은 ruby 의 message 연동방식인 STOMP(http://stomp.github.io/) 를사용하도록되어있다. < 그림 25> chef 구성아키텍처 ( 출처 : https://www.ibm.com/developerworks/community/blogs/9e635b49 09e9 4c23 8999 a4d461aeac e2/entry/215?lang=en) puppet 과마찬가지로 chef 는 open source(https://github.com/opscode/chef) 와 enterprise 버전 (http://www.getchef.com/chef/) 으로나뉜다. 기본적인기능은 open source 만으로충분하다. < 그림 26> 는오픈소스버전과상용버전의차이를설명한다.

< 그림 26> chef 의 puppet 의상용버전과오픈소스버전차이 ( 출처 : http://www.getchef.com/chef/) 참고자료는여기서확인한다. http://docs.getchef.com/ https://wiki.opscode.com/display/chef/home 3. docker 소개요즘에는 vagrant 대신가상머신으로 docker 를쓰는경우가있다. docker ( 가상서버는아니지만경량화된컨테이너, 사용자는마치가상서버처럼느낌 ) 에 ansible 를붙여서사용가능하다. < 그림 27> 과같이 docker 는 hypervisor 위에 guest os 가올라간형태의가상머신이아닌 docker enginer 위에 binary container 이다. 따라서가상머신과기능이같고속도가훨신빠르다.

< 그림 27> ( 출처 : https://www.docker.com) 이런장점때문에최근에 docker 가인기를얻고있으며다양한 docker linux image 들이배포되고있다. 최근에빠른관심이보이는부분이이라관심을가져볼만하다. ansible 과 docker 연동사례들이늘고있으니참조하면좋을것같다. 참고자료는다음과같다. http://docs.ansible.com/docker_module.html http://thenewstack.io/are docker users migrating to ansible and away from puppet and chef/ https://github.com/cove/docker ansible