ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Terraform과 모듈 - 로컬
    Iac(Infrastructure as Code) 2023. 3. 25. 17:31

     

    들어가기 전에

    이전 Terraform과 모듈 포스팅에서 모듈이 무엇인지와 모범사례를 알아보았다.

    이 글에서는 모범사례 중 하나인 로컬 모듈을 사용하여 코드를 구성하고 캡슐화하는 실습을 진행해보려한다.

     

    선행 조건

    • Azure 계정
    • Azure CLI
    • Terraform CLI

     

    모듈 구조

    Terraform은 module 블록의 source 인수에서 참조되는 모든 로컬 디렉토리를 모듈로 취급한다.

    모듈의 일반적인 파일 구조는 다음과 같다.

     

     

    단일 .tf 파일로 모듈을 만들거나 원하는 다른 파일 구조를 사용할 수 있다.

    각 파일은 다음과 같은 용도로 사용된다.

    • LICENSE
      : 모듈이 배포되는 라이센스가 포함된다. LICENSE 파일을 통해 모듈을 사용하는 사람들에게 해당 모듈을 사용할 수 있는 조건을 알릴 수 있다. Terraform 자체는 이 파일을 사용하지 않는다.
    • README.md
      : 마크다운 형식으로 모듈 사용 방법을 설명하는 문서가 포함된다. Terraform은 이 파일을 사용하지 않지만 Terraform Registry 및 GitHub와 같은 서비스 페이지를 방문하는 사람들에게 이 파일의 내용을 안내한다.
    • main.tf
      : 모듈에 대한 기본 구성 세트가 포함된다. 다른 구성 파일을 만들고 구성할 수 있지만 프로젝트에 가장 적합하다.
    • variables.tf
      : 모듈에 대한 변수 정의가 포함된다. 다른 사람이 나의 모듈을 사용할 때, 변수는 module 블록에서 인수로 구성된다. 모든 Terraform 값을 정의해야 하므로 기본 값이 지정되지 않은 모든 변수는 필수 인수가 된다. 기본 값이 있는 변수는 모듈 인수로 제공되어 기본 값을 재정의할 수 있다.
    • outputs.tf
      : 모듈에 대한 출력 정의가 포함된다. 모듈을 사용하는 구성에서 사용할 수 있어 모듈에서 정의한 인프라 부분 정보를 구성의 다른 부분으로 전달하는 데 자주 사용된다.

     

    ❗ 추가로 알아야 할 몇 가지 다른 파일이 있으며 모듈의 일부로 배포하지 않도록 주의해야 한다.

     

    • terraform.tfstateterraform.tfstate.backup
      : 이 파일에는 Terraform 상태가 포함되고 Terraform이 구성과 프로비저닝된 인프라 사이의 관계를 추적하는 방법이다.
    • .terraform/
      : 이 디렉토리에는 인프라를 프로비저닝하는 데 사용되는 모듈과 플러그인이 포함된다. 여기에 속한 파일들은 .tf 파일에 정의된 인프라 구성이 아니라 인프라를 프로비저닝할 때 Terraform의 특정 인스턴스에만 적용된다.
    • *.tfvars
      : 모듈 입력 변수는 인수를 통해 설정되기 때문에 독립 실행형 Terraform 구성으로 사용하지 않는 한 내가 작성한 구성의 module 블록에 *.tfvars 파일을 배포할 필요가 없다.

     

    위에서 언급한 3가지 파일에는 암호나 액세스 키와 같은 비밀 정보가 포함되는 경우가 많아 Git 과 같은 버전 제어 시스템에서 파일을 무시하도록 .gitignore 파일을 구성 해야한다.

     

    모듈 만들기

    아래는 내가 만들어 놓은 모듈이다.

     

    module 구조
    루트 구성

     

    Hashicorp에서 제공하는 모듈화 하는 방법을 확인하려면 여기를 확인하자.

    하지만, 이론적인 내용과 함께 간단한 예시로는 내가 원하는 모듈화를 완수하기는 한계가 있다.

    항상 느끼는거지만 이런 상황에서는 간단한 예시를 빠르게 돌려서 거시적으로 흐름을 경험하고 파악하는게 중요하다.

     

    처음부터 본인이 원하는 이상향을 만들기보다는 간단한 예시를 실행해서 큰 흐름을 보는 실습을 하면 좋을 것 같다.

     

    공식 홈페이지와 함께 참고한 사이트는 아래와 같다.

     

    위 자료들을 참고하여 나만의 Terraform 모듈 작업흐름을 나열해보았다.

    • 자식 모듈의 main.tf 변수 입력값은 variables.tf의 type과 description만 만들고 실제 값은 루트 구성의 main.tf의 입력변수로 추가한다.
    • 루트 구성의 변수 값을 설정하는 방법에는 .tfvars 파일 또는 명령줄 및 루트 구성파일에 직접 값을 작성해 전달하는 방법이 있다.
    • 첫번째는 .tfvars 파일로 정의하는 방법은 아래와 같다.
    # main.tf
    name = var.example_id
    
    # variables.tf
    variable "example_id" {
        description = "Id of the example."
    }
    
    # terraform.tfvars
    example_id = AAAbet234AAWRV

     

    흐름은 main.tf에서 선언한 변수 값을 variables.tf에서 찾고 값이 정의되지 않았다면 terraform.tfvars 파일에서 탐색을 진행한다.

     

    Terraform 공식 홈페이지는 terraform.tfvars 파일에는 민감한 데이터를 정의하라고 안내한다.

     

    • 두번째는 루트 구성 파일에 직접 값을 작성하는 것이다.
    # main.tf
    name = "example_name"

     

    직접 main.tf 파일에 작성하는 것이라 직관적이다. 하지만, 리소스의 다양한 값을 선언하고 싶을 때 main.tf를 직접 수정해야 한다.

     

    • 세번째는 CLI 명령줄로 작성하는 것이다.

     

     

    위에서 보듯 terraform apply 를 실행할 때 루트 구성의 variables.tf의 정의된 내용을 가져와 출력해주는 것이다.

    이렇게 진행했을 때 작성된 루트 구성 코드는 아래와 같다.

     

    module "storage_account" {
        source = "./modules/st-module-0322"
    
        storage_account_name = "<storage_account_name>"
        resource_group_name = data.azurerm_resource_group.rg_prod.name
        resource_group_location = data.azurerm_resource_group.rg_prod.location
    }
    
    module "storage_account_container" {
        source = "./modules/stc-module-0323"
    
        storage_account_container_name = "<storage_account_name>"
        storage_account_name = module.storage_account.storage_account_name
    }
    
    module "virtual_network_spoke" {
        source = "./modules/vnet-module-0322"
    
        resource_group_name = data.azurerm_resource_group.rg_prod.name
        location = data.azurerm_resource_group.rg_prod.location
    
        virtual_network_name = "Spoke"
        vnet_address_space = ["10.11.0.0/16"]
    
        tags = "Spoke0324"
    }

     

    루트 구성에서 자식 모듈을 연결하는 흐름을 다시 정리하자면,

    루트 구성에서 작성된 속성값은 module 블록에서 variables.tf 파일의 정의된 것과 연결되어 사용된다.

     

    여기서 말하는 루트 구성은 모듈 바깥의 존재하는 실제 terraform 명령을 수행하여 init, plan, apply, destory를 진행하는 위치이다. 자식 모듈은 루트 구성에서 가져와 사용하는 모듈 자체이다.

     

    원격 상태 파일에 있는 참조 값 사용하기

     

    위에서 보듯 A 컴퓨터에서 만든 상태 파일을 B 컴퓨터에서 사용하는 흐름이다.

    팀원들과 협업할 때 꼭 사용해야 하는 흐름이니 제대로 알고 사용하자.

     

    위 그림에서 보듯 A 컴퓨터에서 값을 B 컴퓨터에서 사용하려면 반드시 output 블록을 작성해야 한다.

    output 블록을 사용하면 terraform.tfstate 파일에 아래와 같이 작성된다.

     

    A 컴퓨터 terraform 상태 파일

     

    위 그림은 A 컴퓨터에서 만든 terraform.tfstate 파일이다.

    B 컴퓨터에서 어떻게 값을 사용할 수 있을까?

     

    # A 컴퓨터에서 만든 terraform.tfstate 파일을 불러온다.
    data "terraform_remote_state" "demo0324" {
      backend = "azurerm"
      config = {
        storage_account_name = "stdemo0324"
        container_name       = "stc-demo0324"
        key                  = "demo0324.terraform.tfstate"
    
        access_key = "${var.remote_access_key}"
      }
    }
    
    # A 컴퓨터에서 가져온 값을 B 컴퓨터에서 사용하기
    module "peering_spoke" {
        source = "./modules/peer-module-0322"
    
        resource_group_name = data.azurerm_resource_group.rg_prod.name
    
        virtual_network_origin_name = module.virtual_network_spoke.name
        virtual_network_edge_name = "${data.terraform_remote_state.demo0324.outputs.virtual_network_name}"
    
        remote_virtual_network_edge_id = "${data.terraform_remote_state.demo0324.outputs.virtual_network_id}"
    }

     

    terraform.tfstate 는 JSON 형태로 값을 저장하기 때문에 data 소스를 사용해 상태파일이 저장된 스토리지를 연결한다.

    스토리지는 private 형태라 서비스 주체, AAD 토큰, access key 등 접근하는 방법이 다양하다.

    여기서는 access key로 접근한다. access key는 민감한 데이터이기 때문에 terraform.tfvars 에 선언해두었다.

    key 값의 선언된 내용이 terraform 상태 파일 이름이다.

    상태 파일의 outputs 블록의 정의된 값을 data.terraform_remote_state.demo0324.outputs.virtual_network_name 이렇게 참조해주면 A 컴퓨터에서 만든 리소스 값을 B 컴퓨터에서 사용할 수 있는 팀원간의 공유된 리소스를 사용하게 되는 것이다.

     

    글을 마치면서

    이렇게 로컬에 구성한 모듈을 사용하는 여행을 진행해보았다.

    하면서 느낀점은 AWS 와 Terraform 관련 자료는 많은데 Azure 와 Terraform 관련 자료는 많이 없다는 것이다.

     

    하지만, 세부적인 명령 구조와 리소스 및 속성 명이 변경되었을 뿐 큰 흐름에서는 똑같다는 것을 알 수 있었다.

    GCP는 검토를 못해봐서 확신할 수 없지만 AWS, Azure가 그러하듯 GCP도 큰 흐름은 같을 것이다.

     

    수 많은 시행착오를 겪었지만 가장 핵심이되는 흐름만 정리를 해보았다. 중요한건 꺽이지 않는 마음을 가지고 꾸준히 나아가는 것만이 완수할 수 있는 길이 될 것이다.

    'Iac(Infrastructure as Code)' 카테고리의 다른 글

    Terraform과 모듈  (0) 2023.03.22
Designed by Tistory.