Terraform with Azure

Eugene·2024년 6월 24일

Terraform이란?

테라폼(Terraform)은 인프라를 코드로 관리하는 도구입니다(Infra as Code, IaC). 쉽게 말해, 서버, 데이터베이스, 네트워크 등의 인프라 리소스를 프로그래밍 코드로 정의하고 관리할 수 있도록 해줍니다. 이를 통해 인프라를 더 쉽게 배포하고 관리할 수 있습니다.

주요 특징

  1. 인프라를 코드로 작성:
    • 테라폼은 HCL(HashiCorp Configuration Language)이라는 간단한 언어를 사용해 인프라를 코드로 정의합니다.
    • 예를 들어, 서버를 만들고, 네트워크를 구성하고, 데이터베이스를 설정하는 것을 코드로 작성할 수 있습니다.
  2. 다양한 클라우드 제공자 지원:
    • AWS, GCP, Azure와 같은 다양한 클라우드 제공자뿐만 아니라, VMware, OpenStack 같은 온프레미스 환경도 지원합니다.
    • 이를 통해 여러 클라우드 간의 인프라를 일관되게 관리할 수 있습니다.
  3. 변경 사항 추적 및 자동화:
    • 테라폼은 현재 인프라 상태와 원하는 인프라 상태를 비교하여 필요한 변경 사항을 자동으로 적용합니다.
    • 이 과정에서 어떤 변경이 이루어질지 미리 볼 수 있는 기능(plan 명령어)을 제공합니다.
  4. 모듈화:
    • 테라폼은 모듈이라는 개념을 통해 코드 재사용성을 높입니다.
    • 자주 사용하는 인프라 구성 요소를 모듈로 만들어 여러 프로젝트에서 재사용할 수 있습니다.

설치

brew tap hashicorp/tap
brew install hashicorp/tap/terraform

prerequisite: azure cli가 설치되어 있어야 합니다.

Files

main.tf

테라폼 로직 코드를 작성하는 메인 파일입니다. 테라폼에서는 다른 파일들을 import 없이 참조할 수 있습니다.

  • 참조 예시
    module "network_peering" {
      source                     = "./modules/network_association/network_peering"
      common_resource_group_name = var.common_resource_group_name
      subscription_id            = var.subscription_id
      common_subscription_id     = local.common_subscription_id
      resource_group_name        = module.resource_group.resource_group_name
    }
    

variables.tf

main.tf에서 사용되는 변수를 저장합니다.

outputs.ts

main.tf를 실행한 결과를 출력합니다. 여기서 출력한 값을 다른 모듈에서 참조할 수 있습니다.

terraform.tfvars

테라폼 환경변수를 저장합니다(.env 파일과 흡사). 보안상 민감한 정보를 저장하기 때문에 .gitignore에 추가합니다. 여기에 정의된 변수는 variables.tf에 똑같은 변수명으로 정의되어 있어야 하며 자동으로 참조됩니다.

terraform.tfstate

테라폼에 의해 생성된 리소스들이 어떻게 정의되어 있는지 상태를 저장, 관리합니다. apply 명령어에 의해 자동으로 생성되지만, import 명령어로 상태를 업데이트 할 수도 있습니다.

  • 명령어 예시
    # 테라폼 상태파일에 리소스 추가
    terraform import azurerm_key_vault_access_policy.client <resource_id>
    
    # 해당 리소스 상태 확인
    terraform state show azurerm_mysql_flexible_server.example_mysql
    
    # 상태파일에 등록된 리소스 나열
    terraform state list
    

Custom Files

locals.tf

main.tf에서 사용할 커스텀 변수를 저장합니다.

providers.tf

프로바이더를 저장합니다.

Blocks

terraform

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "3.107.0"
    }
  }
}

사용할 프로바이더의 버전을 설정할 수 있습니다.

provider

provider "azurerm" {
  features {}
}

사용할 프로바이더를 선언합니다.
main.tf에서 동시에 두개 이상의 구독을 제어하는 경우엔 다음과 같이 두개의 프로바이더에 구독id와 alias를 지정합니다.

provider "azurerm" {
  features {}
  alias           = "source" # alias 속성을 사용하면 resource 마다 provider를 지정해야함.
  subscription_id = var.subscription_id
}

provider "azurerm" {
  features {}
  alias           = "common" # alias 속성을 사용하면 resource 마다 provider를 지정해야함.
  subscription_id = var.common_subscription_id
}

프로바이더에 alias를 정의하면 main.tf 에서 리소스를 생성/참조할 때 반드시 어느 프로바이더를 사용할지 설정해야 합니다.

resource

resource "azurerm_virtual_network_peering" "SourceToCommon" {
  provider                     = azurerm.source # 어떤 프로바이더를 사용할지 설정합니다.
  name                         = "peerSourceToCommon"
  resource_group_name          = data.azurerm_resource_group.dev.name
  virtual_network_name         = var.vnet_name # data.azurerm_virtual_network.source_vnet.name
  remote_virtual_network_id    = data.azurerm_virtual_network.common_vnet.id
  allow_virtual_network_access = true
  allow_forwarded_traffic      = true
}

resource "azurerm_virtual_network_peering" "CommonToSource" {
  provider                     = azurerm.common
  name                         = "peerCommonToSource"
  resource_group_name          = data.azurerm_resource_group.common_rg.name
  virtual_network_name         = data.azurerm_virtual_network.common_vnet.name
  remote_virtual_network_id    = var.vnet_id # data.azurerm_virtual_network.source_vnet.id
  allow_virtual_network_access = true
  allow_forwarded_traffic      = true
}

리소스를 생성합니다. 변경사항이 없는 경우, 리소스는 재생성되지 않습니다. 그러나 변경사항이 있는 경우, 데이터베이스와 같은 리소스는 삭제 후 재생성될 수 있으므로, 프로퍼티 변경 시 재생성 여부를 확인하고 수정해야 합니다. 재생성이 실수로 이루어지는 것을 방지하기 위해, lifecycle의 prevent_destroy 옵션을 추가할 수 있습니다. 테라폼 Argument Reference에 "Changing this forces a new resource to be created."라는 설명이 있을 경우, 해당 프로퍼티 변경 시 리소스가 재생성됩니다.

resource "azurerm_mysql_flexible_server" "example_mysql" {
  provider               = azurerm.source
  name                   = var.mysql_name
  location               = var.location
  resource_group_name    = var.resource_group_name
  administrator_login    = var.mysql_admin_username
  administrator_password = var.mysql_admin_password
  sku_name               = var.mysql_flexible_server_sku_name
  version                = "8.0.21"
  zone                   = 3

## prevent_destroy가 참이면 재생성 방지
  lifecycle {
    prevent_destroy = true
  }
}

data

이미 생성되어 있는 리소스를 참조합니다. 참조한 리소스는 data객체에 저장됩니다.

data "azurerm_resource_group" "common_rg" {
  provider = azurerm.common
  name     = var.common_resource_group_name
}

resource "azurerm_virtual_network_peering" "SourceToCommon" {
  provider                     = azurerm.source # 어떤 프로바이더를 사용할지 설정합니다.
  name                         = "peerSourceToCommon"
  ## 참조 data 사용
  resource_group_name          = data.azurerm_resource_group.dev.name
  virtual_network_name         = var.vnet_name
  remote_virtual_network_id    = data.azurerm_virtual_network.common_vnet.id
  allow_virtual_network_access = true
  allow_forwarded_traffic      = true
}

module

module "network_peering" {
  source                     = "./modules/network_association/network_peering"
  common_resource_group_name = var.common_resource_group_name
  subscription_id            = var.subscription_id
  common_subscription_id     = var.common_subscription_id
  resource_group_name        = module.resource_group.resource_group_name
  vnet_name                  = module.virtual_network.vnet_name
  vnet_id                    = module.virtual_network.vnet_id # 모듈 연동
}

프로퍼티 값에 module객체로 다른 모듈을 참조하면 (예:vnet_id =module.virtual_network.vnet_id) 참조된 모듈이 먼저 실행됩니다.

variable

변수를 정의합니다. 이는 주로 variables.tf 파일에서 수행합니다. description에는 변수에 대한 설명을 작성하고, type에는 변수의 타입을 명시하며, default에는 기본값을 입력할 수 있습니다. terraform.tfvars 파일에 일치하는 변수가 없을 경우, 기본값이 사용됩니다.

variable "vm_size" {
  description = "The size of the virtual machine"
  type        = string
  default     = "Standard_DS1_v2"
}

Workspace

테라폼에서는 운영 환경에 따라 서로 다른 구성을 적용할 수 있게 workspace 기능을 제공합니다.

workspace는 각 환경의 독립적인 상태 파일을 유지하고, 환경별로 다른 변수 파일을 사용하여 각 환경에 적합한 설정을 적용할 수 있습니다.
workspace를 적용하면 명령어를 다음과 같이 작성합니다.

  • 명령어 예시
# dev workspace 선택
terraform workspace select dev
# dev 환경변수 파일이 envs 디렉토리에 있을 경우.
terraform plan -out=tfplan -var-file=envs/dev.tfvars
  • workspace 관련 명령어
# workspace 목록 확인
terraform workspace list
# 현재 workspace 확인
terraform workspace show
# workspace 생성
terraform workspace new dev
# workspace 삭제
terraform workspace delete dev
# workspace 선택
terraform workspace select dev

Ignore Changes

리소스의 프로퍼티 변경을 막기 위해, lifecycle.ignore_changes 속성을 추가할 수 있습니다.

# 예시
resource "azurerm_mysql_flexible_server" "example_mysql" {
  name                   = var.mysql_name
  location               = var.location
  resource_group_name    = var.resource_group_name
  administrator_login    = var.mysql_admin_username
  administrator_password = var.mysql_admin_password
  sku_name               = var.mysql_flexible_server_sku_name
  version                = "8.0.21"

  lifecycle {
    ignore_changes = [
      # 무시할 속성 목록 추가
    ]
  }
}
profile
서버 개발자

0개의 댓글