반응형
Terraform 사용법이 표준화 되면서 다른 사람들이 잘 만든 코드나 사내 공통으로 사용되는 코드를 패키징하고 재사용이 가능한 모듈 단위로 관리하는 것이 가능하다. 다수의 모듈로 Repository Structure를 구성해서 사용하는 것이 일반적이다.
Multi Module Repository Structure
root module : 최상위 디렉터리를 의미한다. 아래 예시에서는 `.` 디렉터리가 최상위 디렉터리다.
module : module collection으로 단일 모듈 구성도 가능하고 중첩된 다수의 모듈 collection 구성도 가능하다.
.
├── README.md
├── main.tf
├── variables.tf
├── outputs.tf
├── ...
├── modules/
│ ├── nestedA/
│ │ ├── README.md
│ │ ├── variables.tf
│ │ ├── main.tf
│ │ ├── outputs.tf
│ ├── nestedB/
│ ├── .../
Module 구성
vpc.tf 파일을 network 모듈로 재구성하기 위해 아래 구성으로 폴더 구성을 변경한다. modules/network 디렉터리에는 provider.tf 파일이 없다. 모듈을 구성할 때 Multi Account 구조로 서로 다른 AWS Account를 사용하는 경우가 아니라면 명시적으로 provider.tf 파일을 구성하지 않아도 상위의 provider.tf 파일 정보를 참조한다.
terraform-starter-moduling/
├── main.tf
├── backend.tf
├── versions.tf
├── provider.tf
├── modules/
│ ├── network/
│ │ ├── data_sources.tf
│ │ ├── variables.tf
│ │ ├── locals.tf
│ │ ├── outputs.tf
│ │ ├── versions.tf
│ │ ├── vpc.tf
1. 폴더 구성
$ mkdir -p terraform-starter-moduling/modules/network
$ cd terraform-starter-moduling/
$ touch {main,backend,versions,provider}.tf
$ touch ./modules/network/{data_sources,variables,locals,outputs,versions,vpc}.tf
$ aws s3 mb s3://terraform-starter-moduling-bucket --region ap-northeast-2
make_bucket: terraform-starter-moduling-bucket
$ aws dynamodb create-table \
--table-name tf_state_moduling_table \
--attribute-definitions AttributeName=LockID,AttributeType=S \
--key-schema AttributeName=LockID,KeyType=HASH \
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
--region ap-northeast-2
2. version.tf 파일 구성
# modules/network/versions.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.62.0"
}
}
required_version = ">= 1.3.6"
}
3. data_sources.tf 파일 구성
# module/network/data_sources.tf
data "aws_availability_zones" "available" {
state = "available"
}
4. locals.tf 파일 구성
locals {
subnet_new_bits = 8
}
5. output.tf 파일 구성
# module/network/output.tf
output "main_vpc_id" {
value = aws_vpc.main.id
description = "The Id of the main VPC"
}
6. variables.tf 파일 구성
# module/network/variables.tf
variable "vpc_cidr" {
type = string
description = "The CIDR block for the VPC"
default = "10.0.0.0/16"
validation {
condition = can(regex("^([0-9]{1,3}\\.){3}[0-9]{1,3}($|/(16|24))$",var.vpc_cidr))
error_message = "Please ensure a valid CIDR has been entered with range /16 or /24."
}
}
variable default_tags {
type = object({
environment = string
owner = string
cost_centre = string
})
description = "Default set of tags to apply to resources"
default = {
environment = "development",
owner = "r&d",
cost_centre = "1234567890"
}
validation {
condition = length(var.default_tags.cost_centre) == 10
error_message = "Please ensure a valid 10 digit cost centre code has been entered."
}
}
variable subnet_count {
type = number
default = 2
}
7. vpc.tf 파일 구성
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
tags = merge(
{
"Name" = "Main"
},
var.default_tags
)
}
resource "aws_subnet" "public" {
count = var.subnet_count
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(var.vpc_cidr,local.subnet_new_bits,count.index)
tags = merge(
{
"Name" = "Public${count.index+1}"
},
var.default_tags
)
availability_zone = element(data.aws_availability_zones.available.names,count.index)
map_public_ip_on_launch = true
}
Main 코드 작성
1. backend.tf 파일 구성
# backend.tf
terraform {
backend "s3" {
bucket = "terraform-starter-moduling-bucket"
key = "terraform-starter-moduling/"
region = "ap-northeast-2"
dynamodb_table = "tf_state_moduling_table"
}
}
2. provider.tf 파일 구성
# provider.tf
provider "aws" {
region = "ap-northeast-2"
shared_credentials_file = "~/.aws/credentials"
profile = "default"
}
3. main.tf 파일 구성
모듈 구성은 Block 단위로 만들어서 사용할 수 있다. source는 실행하려는 모듈의 상대 경로를 입력하게 된다. 실행하는 모듈이 변수를 취급하고 있으면 vpc_cidr, default_tags, subnet_count처럼 모듈로 데이터를 전달할 수 있다.
# main.tf
module "vpc1" {
source = "./modules/network"
vpc_cidr = "10.10.0.0/16"
default_tags = {
environment = "development1",
owner = "r&d",
cost_centre = "1234567890"
}
subnet_count = 2
}
배포 및 결과 확인
1. Terraform 초기화 및 실행
$ terraform init
$ terraform plan --out tfplan
$ terraform apply tfplan
2. 두 번째 모듈 선언
module "vpc1" {
source = "./modules/network"
vpc_cidr = "10.10.0.0/16"
default_tags = {
environment = "development1",
owner = "r&d",
cost_centre = "1234567890"
}
subnet_count = 2
}
module "vpc2" {
source = "./modules/network"
vpc_cidr = "10.20.0.0/16"
default_tags = {
environment = "development2",
owner = "r&d",
cost_centre = "1234567890"
}
subnet_count = 4
}
3. Terraform 초기화 및 실행
$ terraform init
$ terraform plan --out tfplan
$ terraform apply tfplan
module.vpc1[0].aws_subnet.public[1]: Destroying... [id=subnet-00b62c735078083ed]
module.vpc1[0].aws_subnet.public[0]: Destroying... [id=subnet-0681a4aef56086385]
module.vpc2.aws_vpc.main: Creating...
module.vpc1.aws_vpc.main: Creating...
module.vpc1[0].aws_subnet.public[0]: Destruction complete after 0s
module.vpc1[0].aws_subnet.public[1]: Destruction complete after 0s
module.vpc1[0].aws_vpc.main: Destroying... [id=vpc-0895973aa883a2647]
module.vpc1[0].aws_vpc.main: Destruction complete after 1s
module.vpc2.aws_vpc.main: Creation complete after 1s [id=vpc-0dcc985afea4250fb]
module.vpc2.aws_subnet.public[0]: Creating...
module.vpc2.aws_subnet.public[2]: Creating...
module.vpc2.aws_subnet.public[3]: Creating...
module.vpc2.aws_subnet.public[1]: Creating...
module.vpc1.aws_vpc.main: Creation complete after 1s [id=vpc-019be906133fe0b4d]
module.vpc1.aws_subnet.public[1]: Creating...
module.vpc1.aws_subnet.public[0]: Creating...
module.vpc2.aws_subnet.public[0]: Still creating... [10s elapsed]
module.vpc2.aws_subnet.public[2]: Still creating... [10s elapsed]
module.vpc2.aws_subnet.public[3]: Still creating... [10s elapsed]
module.vpc2.aws_subnet.public[1]: Still creating... [10s elapsed]
module.vpc1.aws_subnet.public[1]: Still creating... [10s elapsed]
module.vpc1.aws_subnet.public[0]: Still creating... [10s elapsed]
module.vpc2.aws_subnet.public[0]: Creation complete after 11s [id=subnet-05bee4712747c6b06]
module.vpc2.aws_subnet.public[1]: Creation complete after 11s [id=subnet-054bd5f5762734ad0]
module.vpc1.aws_subnet.public[0]: Creation complete after 11s [id=subnet-04f13fd1543150886]
module.vpc2.aws_subnet.public[3]: Creation complete after 11s [id=subnet-012d32c1ccc6ea97a]
module.vpc2.aws_subnet.public[2]: Creation complete after 11s [id=subnet-0a7e41b8ca6c0af5e]
module.vpc1.aws_subnet.public[1]: Creation complete after 11s [id=subnet-03b64331d0aa898cb]
Apply complete! Resources: 8 added, 0 changed, 3 destroyed.반응형