- terraform으로 infra를 구성할 때 규모가 점점 커질경우 하나의 파일에 모든 것을 정의 한다면 의도치않게 다른 부분에 영향을 미칠 수 있고 환경별 가은 리소스의 코드가 중복될 수 있다.
- 이 단점을 해결하기 위해서 terraform은 리소스의 코드가 중복되어 쌓일수 있다.
- 모듈은 관련 요소들을 하나로 모아 패키지를 만드는데, 예를 들면 VPC 모듈의 경우 vpc, subnet, gateway 등 리소스를 하나의 패키징을 한다.
- 모듈의 장점으로는 총 3가지로 요약할 수 있다.
- 캡슐화 - 서로 관련이 있는 요소들을 모아 캡슐화하여 의도치 않는 문제를 예방할 수 있다.
- 재사용성 - 모듈을 사용해 리소스를 정의하면 다른 환경에서도 해당하는 리소스를 재사용할 수 있다.
- 일관성 - 매번 새로 작성하게 되면 사용자에 따라 리소스의 옵션이 빠지거나, 같을 수 없기 때문에 모듈을 재 사용 한다면 일관성 가질 수 있다.
- terraform은 재사용하기 위해 mudule를 사용한다.
- 재사용 하기 위해 사용자가 module를 생성하고 변수 입력 값을 제거한다.
- Directory를 mudule로 변경
- staging 환경에서 module을 사용하기 위해서는 source가 존재해야 한다.
- ※ staging 환경 - 운영 환경(Production)과 거의 동일한 환경을 만들어 놓고, 운영환경으로 이전하기 전에, 여러 가지 비 기능적인 부분 (Security, 성능, 장애등)을 검증하는 환경
- staging 경에서의 main.tf 파일은 실제 구성하려는 환경에 대한 정보를 입력해야한다.
- terraform apply를 통해 실행 및 테스트를 진행한다.
module의 기본 구조
- module은 root module과 child module로 나뉘어 진다.
- root module
- terraform command가 실행 되고 있는 module
- 필수 요소인 module
- Root Module은 다른 Module의 기본 진입점
- main.tf에는 Child Module의 Source 위치 또는 Module들의 연결을 정의
- child module
- 다른 module (Root module 포함) 에서 호출하여 사용되는 module
- Resource들을 정의
- 중첩 Module의 경우는 "modules/"의 하위에 위치해야 한다.
- a. Input variables
- 다른 Module로부터 입력받을 입력 값들을 관리
- variables.tf 파일에 저장
- b. Output variables
- 다른 Module에게 반환할 출력 값들을 관리
- output.tf 파일에 저장
- c. Resources
- Infrastructure Object들을 관리
- main.tf 파일에 저장
- d. terraform.tfstate 및 terraform.tfstate.backup
- Terraform 상태를 포함하며, Terraform의 구성과 프로비저닝 된 인프라 간의 관계를 추적할 수 있다.
- e. .terraform
- 인프라를 프로비저닝 하는데 사용되는 모듈과 플러그인이 포함되어 있다.
- .tf 파일에 정의된 인프라 구성이 아닌 Terraform의 특정 인스턴스에 한정된다.
- f. *.tfvars
module 작성 방법
- 작성 방법은 본 프로젝트에서 사용한 terraform code 예시로 사용하겠다.
- tree
. │ main.tf │ terraform.tfvars │ variable.tf │ outputs.tf │ └─modules │ ├─01_vpc │ main.tf │ outputs.tf │ variables.tf │ ├─02_s3 │ main.tf │ outputs.tf │ variables.tf │ ├─03_sg │ main.tf │ outputs.tf │ variables.tf │ ├─04_efs │ main.tf │ outputs.tf │ variables.tf │ ├─05_ec2 │ main.tf │ outputs.tf │ variables.tf │ └─06_auto_scaling main.tf outputs.tf variables.tf
root module
- 아래와 같이 해당하는 부분은 root module에 해당한다.
. │ main.tf │ terraform.tfvars │ variable.tf │ outputs.tf │
- root module의 기본 구성은 다음과 같다.
module "vpc" { source = "./modules/01_vpc" }
- source에는 모듈로 쓰기위해 child module에 리소스를 정의해둔 폴더의 경로를 적는다.
- provider는 테라폼을 실행할 폴더 root module에 정의한다.
child module
- 아래와 같이 해당하는 부분은 child module에 해당한다
└─modules │ ├─01_vpc │ main.tf │ outputs.tf │ variables.tf │ ├─02_s3 │ main.tf │ outputs.tf │ variables.tf │ ├─03_sg │ main.tf │ outputs.tf │ variables.tf │ ├─04_efs │ main.tf │ outputs.tf │ variables.tf │ ├─05_ec2 │ main.tf │ outputs.tf │ variables.tf │ └─06_auto_scaling main.tf outputs.tf variables.tf
- child module의 기본 구성은 다음과 같다.
resource "aws_vpc" "vpc" { cidr_block = var.vpc_cidr enable_dns_hostnames = true tags = { "Name" = "vpc" } }
- 모듈은 폴더 단위로 구성한다.
- modules 폴더 내에 있는 01_vpc, 02_s3, 03_sg의 구성 파일들이 각각 하나의 모듈이 되는 것이다.
변수 정의하는 방식
입력 받을 변수의 경우는 root, child 두 곳 모두에 변수를 정의해 주어야 한다.
기본 예시는 다음과 같다.
root module의 main.tf
provider "aws" { region = var.region } module "vpc" { source = "./modules/01_vpc" vpc_cidr = var.vpc_cidr }
root module의 variables.tf
variable "region" { desciption = "region를 입력하세요(ex)ap-northeast-2" } variable "vpc_cidr" { description = "vpc cidr block : x.x.x.x/x를 입력하세요" }
- root module의 변수를 입력 받는다.
child module의 main.tf
resource "aws_vpc" "vpc" { cidr_block = var.vpc_cidr enable_dns_hostnames = true tags = { "Name" = "vpc" } }
child module의 variables.tf
variable "vpc_cidr" { }
- 입력받은 변수를 module의 변수로 입력하고 - 입력된 변수를 통해 resource를 생성한다.
변수를 입력 받지 않고 root module의 variables.tf에 직접 지정해주는 방법도 있다.
하지만 재사용성을 극대화하기 위하여 앞으로 상황마다 값을 바꾸어 처리하기 위해서는 변수를 입력 받는 것이 좋다.