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


Archive»


 

'terraform'에 해당되는 글 2

  1. 2018.01.31 CI/CD 레퍼런스 아키텍쳐 (1)
  2. 2018.01.11 VM 이미지 생성을 위한 오픈소스 Packer
 


CI/CD 레퍼런스 아키텍쳐


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


Continuous Deployment를  구현하기 위해서는 여러가지 프레임웍을 조합할 수 있다. 배포를 위한 Chef,Puppet과 같은 Configuration management tools, 그리고 네트워크, VM등을 코드로 설정하기 위한 Terraform 과 같은 Infrastructure as a code, VM 이미지를 만들기 위한 Packer 등 다양한 솔루션 조합이 가능한데, 이 글에서는 이러한 솔루션을 조합하여 어떻게 Continuous Deployment 파이프라인을 구현할 수 있는지에 대해서 설명하고, 구체적인 솔루션 제안을 통하여 레퍼런스 아키텍쳐를 제안하고자 한다.

1. Terraform + Ansible 기반의 Continuous Delivery

가장 기본적인 조합으로는 Terraform 을 이용해서 코드로 정의된 설정을 이용하여 인프라를 설정한 후에,

VM에, Ansible을 이용하여 애플리케이션 서버등의 소프트웨어를 설치한 후,  애플리케이션 코드를 배포하는 방식이다.

아래 그림은 Terraform으로 먼저 VM 인스턴스 그룹을 만든 후에, Load Balancer에 연결하고, CloudSQL (DB)인스턴스를 배포하는 구조이다.




이후에, 각 VM에 대한 설치는 Ansible을 이용하는 구조이다 Ansible은 Jenkins와 같은 CD 툴에 의해서 코드 변경등이 있으면 호출되서 자동화 될 수 있다.


이러한 구조는 전통적인 Continuous Delivery 기반의 애플리케이션 배포 자동화 구조이다.


2. Packer를 추가한 Foundation Image 사용방식

앞의 구조에서 VM은 애플리케이션 서버를 코드 배포 단계에서 배포할 수 도 있지만 애플리케이션 코드 이외에는 변경이 없기 때문에, Terraform으로 인프라를 배포할때, Packer와 Ansible을 이용하여, 애플리케이션이 설치되어 있는 이미지를 만들어놓고, 이를 이용해서 배포할 수 있다. (이미지를 만드는 과정을 베이킹 = 굽는다. 라고 한다.)

아래 그림을 보면, Terraform에서, Packer를 호출하고, Packer가 VM 이미지를 만드는데, 이 과정에서 Ansible을 이용하여, 애플리케이션 서버를 설치하도록 설정하는 구조를 가지고 있다.



위의 구조에서는 node.js server 애플리케이션 서버를 사용했지만, 실제 인프라를 구축할때는 redis나 웹서버등 다양한 애플리케이션의 설치가 필요하기 때문에, 이 구조를 사용하면 전체 인프라 구축을 코드로 정의하여 자동화를 할 수 있다.

3. Spinnaker를 이용한 Continuous Deployment 구조

코드만 배포하고 업데이트 할 경우, 서버의 패치 적용등의 자동화가 어렵기 때문에, 매번 배포시 마다, VM 설정에서 부터 OS 설치와 패치 그리고 애플리케이션 설치와 코드 배포까지 일원화하여 VM 단위로 배포할 수 있는데, 이를 Continuous Deployment 라고 한다.


솔루션 구성은 2번의 구조와 유사하나, Terraform으로는 VM과 로드밸런서를 제외한 다른 인프라를 설정하고 Spinnaker를 이용하여, 로드밸런서와 VM을 이용한 배포를 실행한다.


Spinnaker로 배포할 수 있는 범위는 방화벽, 로드밸런서, VM 과 같이 워크로드를 받는 부분인데, Spinnaker는 Packer와 Ansible과 협업하여, VM에 모든 스택을 설치하고, 이를 VM 단위로 배포할 수 있도록 해준다. 복잡한 네트워크 설정이나, CloudSQL과 같은 클라우드 전용 서비스는 Spinnaker로 설정이 불가능하기 때문에, 먼저 Terraform으로 기본 인프라를 설정하고, VM관련된 부분만을 Spinnaker를 사용한다.

이렇게 VM전체를 배포하는 전략을 피닉스 서버 아키텍쳐라고 한다. 피닉스 서버 패턴은 http://bcho.tistory.com/1224?category=502863 글을 참고하기 바란다.


Spinnaker를 이용한 배포 전략

Spinnker를 이용하면, VM 기반의 배포뿐 아니라, 다양한 배포 전략을 수행할 있다.



그림 https://sdtimes.com/cloud/google-open-source-platform-spinnaker-1-0/


Blue/Green deployment

블루 그린 배포 전략은 새버전의 서버그룹을 모두 배포 완료한 후에, 로드밸런서에서 트래픽을 구버전에서 새버전으로 일시에 바꾸는 방식이다.

Rolling deployment

롤링 배포는, 새버전의 서버를 만들어가면서 트래픽을 구버전 서버에서 새버전으로 점차적으로 옮겨가는 방식이다. 예를 들어 구서버가 10대가 있을때, 새 서버 1대가 배포되면, 구서버 9대와 새서버 1대로 부하를 옮기고, 새서버 2대가 배포되면 구서버:새서버에 8:2 비율로 부하를 주면서 7:3,6:4,5:5,.... 이런식으로 부하를 옮겨가며 전체 부하를 새 서버로 옮기는 방식이다.


블루 그린 배포 전략은 서버 대수의 2배수의 서버가 필요한 반면, 롤링 배포 방식은 같은 서버의 수 (위의 예의 경우 10대만 있으면 됨)를 가지고 배포를 할 수 있기 때문에 서버 자원이 한정되어 있는 경우에 유리하게 사용할 수 있다.

Canary deployment

카날리 배포를 설명하기 전에 카날리 테스트에 대한 용어를 이해할 필요가 있다.

카날리 테스트는 옛날에 광부들이 광산에서 유독가스가 나오는 것을 알아내기 위해서 가스에 민감한 카나리아를 광산안에서 키웠다고 한다. 카나리아가 죽으면 유독가스가 나온것으로 판단하고 조치를 취했다고 하는데, 이 개념을 개발에서 사용하는것이 카날리 테스트 방식이다.

예를 들어 사용자가 1000명이 접속해 있을때, 일부 사용자에게만 새 버전을 사용하도록 하고, 문제가 없으면 전체 사용자가 새 버전을 사용하도록 하는 방식인데, 안드로이드 앱 배포의 경우에도 10%의 사용자에게만 새 버전을 배포해보고 문제가 없으면 100%에 배포하는 것과 같은 시나리오로 사용된다.


이 개념을 배포에 적용한것이 카날리 배포 방식인데, 일부 서버에만 새 버전을 배포하여 운영한 후에, 문제가 없는 것이 확인되면 전체 서버에 새 버전을 배포하는 방식이다.

Docker를 이용한 배포 효율화

이러한 VM 기반의 Continuous deployment 구조는 피닉스 서버 패턴을 기반으로 하여, 모든 업데이트 추적이 가능하다는 장점을 가지고 있지만, 매번 VM을 베이킹해야 하기 때문에 시간이 많이 걸리고, VM 이미지는 사이즈가 커서 스토리지를 많이 사용한다는 단점이 있다.

이러한 배포 구조와 잘 맞는 것이 Docker (Docker 개념 http://bcho.tistory.com/805 ) 인데, Docker는 컨테이너 기반으로 경량화가 되어 있기 때문에, 이미지 베이킹 시간이 상대적으로 짧고, 이미지 사이즈가 작아서 저장이 용이하며, 이미지를 저장하기 위한 리파지토리와 같은 개념이 잘되어 있다.


Spinnaker의 경우 이런 Docker 기반의 피닉스 서버 패턴 기반의 배포를 지원하는데, 특히 Kubernetes 클러스터를 매우 잘 지원하기 때문에, 오히려 VM 기반의 배포 보다는 Docker + Kubernetes 배포 구조를 선택하는 것이 좋다.


이 경우 인프라 배포에 있어서는 애플리케이션을 서비스하는 VM워크로드는 도커를 사용하되, Redis, RDBMS와 같은 미들웨어 솔루션은 재 배포가 거의 발생하지 않기 때문에, VM에 배포하여 사용하는 것이 성능적으로 더 유리하기 때문에, 도커와 VM 을 하이브리드 구조로 배포하는 방식을 권장한다.


클라우드 전용 배포 솔루션  VS 오픈소스 (Terraform)

앞에서 설명한 아키텍쳐에서 사용한 솔루션은 모두 오픈 소스 기반이다. 클라우드 벤더의 경우에는 구글은 Deployment Manager와, 아마존은 CloudFormation을 이용하여, 코드 기반의 배포 (Terraform과 동일)를 지원하는데, 그렇다면, 클라우드에서 제공하는 전용 솔루션을 쓰는 것이 좋은가? 아니면 오픈소스나 벤더에 종속적이지 않은 솔루션을 사용하는 것이 좋은가

오픈소스의 배포툴의 경우에는 요즘 트랜드가 다른 영역으로 확장을 해가는 추세가 있기 때문에, 코드 기반의 인프라 배포 이외에도 애플리케이션 코드 배포등 점점 더 넓은 영역을 커버할 수 있는 장점이 있고, 오픈 소스 생태계내에서 다른 제품들와 연동이 쉬운점이 있다. 그리고 특정 클라우드 벤더나 인프라에 종속성이 없기 때문에 조금 더 유연하게 사용이 가능하지만, 클라우드 벤더에서 제공되는 새로운 서비스나 기능 변화를 지원하는 것에는 상대적으로 클라우드 벤더에서 제공하는 도구보다 느리다. 예를 들어 구글 클라우드에서 새로운 서비스가 나왔을때, 테라폼에서 이 기능을 지원하는데 까지는 시간이 걸린다는 것이다.


양쪽다 좋은 선택지가 될 수 있기 때문에, 현재 환경에 맞는 솔루션을 선택하는 것을 권장한다.



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