본문 바로가기

Sorry Architecture

Terraform

테라폼(Terraform, https://www.terraform.io)은 클라우드(Cloud) 인프라스트럭처(Infrastructure)를 소스 코드로 관리할 수 있도록 하시코프(HashiCorp)에서 만든 도구이며, 이러한 개념을 인프라스트럭처 애즈 코드(Infrastructure as Code, IaC)라고 부른다.[각주:1] 테라폼이라는 단어는 지구와 비슷한 행성을 사람이 살 수 있는 환경으로 만든다는 뜻을 가지고 있는데, 하시코프 창업자가 새로운 IaC 프로젝트의 이름을 고민하던 중 인프라스트럭처를 구축한다는 점이 비슷하다고 생각해서 이름을 지었다고 한다. [각주:2]

보통 인프라스트럭처라고 부르는 것에는 부하 분산기(Load Balancer), 데이터베이스(Database), 방화벽(Security Firewall), 저장소(Storage), 도메인 시스템(DNS) 등이 포함된다. 서비스(Application/Service)를 구동하기 위한 기반시설 같은 것이다. IDC 또는 On-premises 환경에서는 전문가들이 직접 설치를 해주었고 고도의 기술과 많은 시간이 필요했다. 그런데 클라우드 환경에서는 이러한 인프라스트럭처들을 모두 API로 관리할 수 있게 되었고, 이 것을 고도화하여 스트립트나 코드(Script/Code)로 인프라스트럭처를 다룰 수 있도록 발전했다. 클라우드 포메이션이나 테라폼은 그렇게 탄생했다. 테라폼을 이용하면 클라우드 제공업체(Cloud Provider)[각주:3]가 제공하는 여러 인프라스트럭처를 편리하게 생성, 삭제, 변경할 수 있다.

Terraform Lifecycle

Terraform Life-cycle

  1. Setup backend
  2. Edit terraform files
  3. Initialize (terraform init)
  4. Plan (terraform plan)
  5. Apply (terraform apply)
  6. List (terraform state list)
  7. Destroy (terraform destroy)


Terraform Workflow

  1. Edit terraform files
  2. Plan
  3. Review report from plan
  4. Apply (Build Infrastructure)
  5. Review terraform state
  6. If you need, repeat whole cycle from STEP 1


Example

다음은 GCP(Google Cloud Platform)에서 VPC(Virtual Private Cloud)를 만드는 예제를 보여준다. VPC 모듈(Terraform Module) 안에서 VPC와 퍼블릭,프라이빗 서브 네트워크(Public/Private Subnetwork)를 만든다. 바로 아래는 모듈을 사용하는 쪽이고 그 아래는 모듈을 정의한 부분이다.


terraform {
  required_version = ">= 0.11"
}

provider "google" {
  region      = "us-central1"
  project     = "${var.your_proj}"
  credentials = "${file("key.json")}"
}

module "vpc" {
  source          = "${var.module_url}"
  vpc_name        = "test_vpc_gcp"
  regions         = "list("us-central1", "asia-south1")"
  private_subnets = "list("10.255.233.0/24", "10.255.243.0/24")"
  public_subnets  = "list("10.255.123.0/24", "10.255.124.0/24")"
}

 

VPC 모듈에서는 한 개의 VPC를 만들고 그 안에 여러 개의 서브넷을 구성하도록 설계했다. 각 서브넷은 크게 퍼블릭 프라이빗으로 나누었다. 그리고 각 서브넷은 리전(Region) 마다 한 개씩 만들도록 했다. 다시 말해서 각 리전마다 퍼블릭 서브넷 한 개 프라이빗 서브넷 한 개를 만드는 것이다. Google의 자원을 정의할 때 퍼블릭 서브넷의 개수와 리전의 개수가 같지 않으면 아무것도 만들 지 않도록 조건을 설정했다. 아래 예제에서 count 변수의 값을 계산하는 부분을 보면 자세한 조건을 알 수 있다. 다시 말해서, 입력값으로 받은 리전과 서브넷의 수가 같지 않으면 자원의 총 합은 0이 되므로 아무 서브넷도 만들지 않는다.


locals {
  private_subnets_count = "${length(var.private_subnets)}"
  public_subnets_count  = "${length(var.public_subnets)}"
  regions_count         = "${length(var.regions)}"
}

resource "google_compute_network" "vpc" {
  name                    = "${var.vpc_name}"
  description             = "${var.vpc_desc}"
  auto_create_subnetworks = "${var.automode}"
}

resource "google_compute_subnetwork" "private" {
  count         = "${local.private_subnets_count != local.regions_count ? 0 : local.regions_count}"
  name          = "${format("%s-private-%s", var.vpc_name, element(var.regions, count.index))}"
  network       = "${google_compute_network.vpc.self_link}"
  region        = "${element(var.regions, count.index)}"
  ip_cidr_range = "${element(var.private_subnets, count.index)}"
}

resource "google_compute_subnetwork" "public" {
  count         = "${local.public_subnets_count != local.regions_count ? 0 : local.regions_count}"
  name          = "${format("%s-public-%s", var.vpc_name, element(var.regions, count.index))}"
  network       = "${google_compute_network.vpc.self_link}"
  region        = "${element(var.regions, count.index)}"
  ip_cidr_range = "${element(var.public_subnets, count.index)}"
}

 

테라폼 파일(File)을 만들었으면 그 안에서 어떤 자원을 만들 수 있는 지 먼저 점검해 볼 수 있다.

$ terraform plan

 

실행 계획을 확인하면 테라폼으로 만들거나 변경하거나 삭제할 자원을 볼 수 있다. 대부분은 실행계획 그대로 실제 자원을 만들거나 변경하는데, 가끔은 실패하는 경우가 있다. 실행 계획은 테라폼 파일이 동작할 상황을 가정해서 보여주는 것으로 실제 프로바이더(Provider)에 적용한 결과를 보여주지 않기 때문이다. 그래서 실행계획에서는 잘 만들어질 것 같던 자원이라도 테라폼 어플라이(Apply) 명령으로 실제 반영하려고 할 때 각 프로파이더의 제약사항에 따라 자원생성에 실패하기도 한다. 실행 계획을 확인했으면, 'terraform apply' 명령을 실행해서 설계한 자원을 만들거나 변경할 수 있다.

$ terraform apply

 

테라폼을 자주 사용하다보면 자연스럽게 모듈(Module)을 사용하게 된다.[각주:4] 위의 예제처럼 반복적으로 사용할 수 있는 부분들을 모듈로 만들어 두고 여러 곳에서 공통으로 활용하기 좋기 때문이다. 모듈은 직접 만들어서 사용해도 좋고 다른 사람이 만들어 놓은 것을 가져다 사용해도 좋다.

테라폼을 이용해서 자원을 관리하다보면 만들어 놓은 자원을 삭제 해야할 경우가 있다. 이 때는 'terraform destroy' 명령을 활용하면 되는데, 명령을 이용하면 같은 공간의 모든 자원을 한 번에 다 삭제할 수도 있고 특정 자원만 골라서 삭제할 수도 있다. 특히 특정 자원만 골라서 삭제하는 기능은 종종 유용하다. 모듈을 조합해서 하나의 커다란 자원을 만들었는데, 그 중 일부만 변경하거나 제거하고 싶을 경우 이 기능을 활용하면 편하다.

$ terraform destroy -target module.testlb -target module.servergroup
Enter Value: yes
 
module.testlb.aws_lb.lb: Destroying... (ID: arn:aws:elasticloadbalancing:us-east-1:...r/net/testlb-test-ue1/0b6655e59805dc44)
module.testlb.aws_lb.lb: Still destroying... (ID: arn:aws:elasticloadbalancing:us-east-1:...r/net/testlb-test-ue1/0b6655e59805dc44, 10s elapsed)
module.testlb.aws_lb.lb: Still destroying... (ID: arn:aws:elasticloadbalancing:us-east-1:...r/net/testlb-test-ue1/0b6655e59805dc44, 20s elapsed)
module.testlb.aws_lb.lb: Destruction complete after 22s
module.testlb.aws_security_group.lb: Destroying... (ID: sg-e5e2e391)
module.testlb.aws_security_group.lb: Destruction complete after 1s
 
Destroy complete! Resources: 5 destroyed.

 

만약 지정한 자원만 삭제하는 기능을 사용하지 않고 특정 자원만 없애고 싶다면, 테라폼 파일에서 해당 자원을 주석 처리하고 'apply' 명령을 실행하여 삭제할 수 있다. 그렇게 하면 현재 프로바이더에 만들어진 자원과 테라폼 파일에 정의한 자원목록을 비교하게 되고 테라폼 파일에 없는 자원은 삭제하기 때문이다.


 

  1. IaC(Infrastructure as Code)를 이야기한다면 대부분 테라폼을 떠올릴 정도로 대표적이다. 하지만 테라폼 이전부터 AWS(Amazon Web Services)에서는 자신들의 자원(Resources)들을 관리하기 위하여 AWS 클라우드 포메이션(CloudFormation)이라는 비슷한 서비스를 제공했다. [본문으로]
  2. 지형(Terrain)과 변환(Transform)이라는 단어를 이미 알고 있다면 테라폼이라는 단어가 어떤 것을 가리키는 지 더 쉽게 유추할 수 있을 것이다. [본문으로]
  3. 대표적으로 AWS(Amazon Web Services), GCP(Google Cloud Platform)가 있다. [본문으로]
  4. Jikji Code [본문으로]

'Sorry Architecture' 카테고리의 다른 글

Security as Code  (0) 2019.03.03
Polymorphism  (0) 2019.02.21
Immutable Infrastructure  (0) 2019.02.21
CI/CD Pipeline  (0) 2019.02.21
Circuit Breaker  (0) 2019.02.21