brunch
매거진 테라폼 AWS

19탄-15. 테라폼-AWS-모듈 실습

by Master Seo

다음은 주말 CloudNet 테라폼 스터디 내용 참고하여 정리한 부분입니다.

https://gasidaseo.notion.site/gasidaseo/CloudNet-Blog-c9dfa44a27ff431dafdd2edacc8a1863


<1> VPC 모듈 실습

<2> Local 실습 해보자. S3 웹사이트 예제

<3> 모듈 사용시 주의점



<1> VPC 모듈 실습


참고 사이트

https://developer.hashicorp.com/terraform/tutorials/modules/module-use



vpc module(v3.14.0) , ec2 module(v3.5.0)


1

cd

mkdir study

cd study


2

코드 다운로드

git clone https://github.com/hashicorp/learn-terraform-modules-use.git


cd learn-terraform-modules-use

tree


├── LICENSE

├── main.tf

├── outputs.tf

├── README.md

├── terraform.tf

└── variables.tf




3

서울리전으로 변경


sed -i -e 's/"us-west-2a", "us-west-2b", "us-west-2c"/"ap-northeast-2a", "ap-northeast-2c"/g' variables.tf


sed -i -e 's/us-west-2/ap-northeast-2/g' main.tf


sed -i -e 's/ami-0c5204531f799e0c6/ami-09cf633fe86e51bf0/g' main.tf


4

테라폼 init

모듈관련한 부분을 가져 온다.

tree로 확인


terraform init


tree .terraform -L 2

.terraform

├── modules

│ ├── ec2_instances

│ ├── modules.json

│ └── vpc

└── providers

└── registry.terraform.io



5

코드 내용 확인


[root@ip-172-31-61-209 learn-terraform-modules-use]# more *.tf

::::::::::::::

main.tf

::::::::::::::

provider "aws" {

region = "ap-northeast-2"

default_tags {

tags = {

hashicorp-learn = "module-use"

}

}

}

module "vpc" {

source = "terraform-aws-modules/vpc/aws"

version = "3.14.0"

name = var.vpc_name

cidr = var.vpc_cidr

azs = var.vpc_azs

private_subnets = var.vpc_private_subnets

public_subnets = var.vpc_public_subnets

enable_nat_gateway = var.vpc_enable_nat_gateway

tags = var.vpc_tags

}

module "ec2_instances" {

source = "terraform-aws-modules/ec2-instance/aws"

version = "3.5.0"

count = 2

name = "my-ec2-cluster"

ami = "ami-09cf633fe86e51bf0"

instance_type = "t2.micro"

vpc_security_group_ids = [module.vpc.default_security_group_id]

subnet_id = module.vpc.public_subnets[0]

tags = {

Terraform = "true"

Environment = "dev"

}

}



::::::::::::::

outputs.tf

::::::::::::::

output "vpc_public_subnets" {

description = "IDs of the VPC's public subnets"

value = module.vpc.public_subnets

}

output "ec2_instance_public_ips" {

description = "Public IP addresses of EC2 instances"

value = module.ec2_instances[*].public_ip

}



::::::::::::::

terraform.tf

::::::::::::::

terraform {

/* Uncomment this block to use Terraform Cloud for this tutorial

cloud {

organization = "organization-name"

workspaces {

name = "learn-terraform-module-use"

}

}

*/

required_providers {

aws = {

source = "hashicorp/aws"

version = "~> 4.4.0"

}

}

required_version = ">= 1.1.0"

}



::::::::::::::

variables.tf

::::::::::::::

variable "vpc_name" {

description = "Name of VPC"

type = string

default = "example-vpc"

}

variable "vpc_cidr" {

description = "CIDR block for VPC"

type = string

default = "10.0.0.0/16"

}

variable "vpc_azs" {

description = "Availability zones for VPC"

type = list(string)

default = ["ap-northeast-2a", "ap-northeast-2c"]

}

variable "vpc_private_subnets" {

description = "Private subnets for VPC"

type = list(string)

default = ["10.0.1.0/24", "10.0.2.0/24"]

}

variable "vpc_public_subnets" {

description = "Public subnets for VPC"

type = list(string)

default = ["10.0.101.0/24", "10.0.102.0/24"]

}

variable "vpc_enable_nat_gateway" {

description = "Enable NAT gateway for VPC"

type = bool

default = true

}

variable "vpc_tags" {

description = "Tags to apply to resources created by VPC module"

type = map(string)

default = {

Terraform = "true"

Environment = "dev"

}

}

[root@ip-172-31-61-209 learn-terraform-modules-use]#



변경해 테스트해보자.



6

배포

nat 는 비용이 나오므로 제외하고 배포하자.

인스턴스는 기본 2개 만들어진다.


# (옵션) NATGW 제거

export TF_VAR_vpc_enable_nat_gateway=false # macOS/Linux

set TF_VAR_vpc_enable_nat_gateway=false # windows


# plan & apply

terraform plan && terraform apply -auto-approve


Outputs:

ec2_instance_public_ips = [

"13.125.73.197",

"3.38.255.38",

]

vpc_public_subnets = [

"subnet-02f60311e4e985c68",

"subnet-0f59b5b9bdb55562c",

]


7

# 확인

terraform state list


[root@ip-172-31-61-209 learn-terraform-modules-use]# terraform state list

module.ec2_instances[0].aws_instance.this[0]

module.ec2_instances[1].aws_instance.this[0]

module.vpc.aws_internet_gateway.this[0]

module.vpc.aws_route.public_internet_gateway[0]

module.vpc.aws_route_table.private[0]

module.vpc.aws_route_table.private[1]

module.vpc.aws_route_table.public[0]

module.vpc.aws_route_table_association.private[0]

module.vpc.aws_route_table_association.private[1]

module.vpc.aws_route_table_association.public[0]

module.vpc.aws_route_table_association.public[1]

module.vpc.aws_subnet.private[0]

module.vpc.aws_subnet.private[1]

module.vpc.aws_subnet.public[0]

module.vpc.aws_subnet.public[1]

module.vpc.aws_vpc.this[0]





8

콘솔에서 확인하자.

vpc , ec2 확인하자.






<2> Local 실습 해보자. S3 웹사이트 예제


참고

https://developer.hashicorp.com/terraform/tutorials/modules/module-create



vpc module(v2.21.0) , ec2 module(v2.12.0), website s3 bucket


1

다운로드

# 신규 폴더에 clone

mkdir local

cd local

git clone https://github.com/hashicorp/learn-terraform-modules-create.git

cd learn-terraform-modules-create

tree

├── LICENSE

├── main.tf

├── modules

│ └── aws-s3-static-website-bucket

│ ├── LICENSE

│ ├── main.tf

│ ├── outputs.tf

│ ├── README.md

│ ├── variables.tf

│ └── www

│ ├── error.html

│ └── index.html

├── outputs.tf

├── README.md

└── variables.tf


2

서울 리전으로 변경

버킷 이름 변경


#

sed -i -e 's/"us-west-2a", "us-west-2b", "us-west-2c"/"ap-northeast-2a", "ap-northeast-2c"/g' variables.tf

sed -i -e 's/us-west-2/ap-northeast-2/g' main.tf

sed -i -e 's/ami-0c5204531f799e0c6/ami-09cf633fe86e51bf0/g' main.tf


# 버킷 이름 변경

NICKNAME=<각자 자신의 닉네임>

NICKNAME=masterseo

sed -i -e "s/robin-test-dec-17-2019/$NICKNAME-t101-s3/g" main.tf



3

# init

terraform init


# 폴더 확인

tree .terraform



# (옵션) NATGW 제거

export TF_VAR_vpc_enable_nat_gateway=false # macOS/Linux

set TF_VAR_vpc_enable_nat_gateway=false # windows


# plan & apply

terraform plan && terraform apply -auto-approve



Outputs:

ec2_instance_public_ips = [

"43.201.103.19",

"3.38.209.42",

]

vpc_public_subnets = [

"subnet-0fe0a2a5b460bf4bd",

"subnet-0f2b34e374a72c70e",

]

website_bucket_arn = "arn:aws:s3:::masterseo-t101-s3"

website_bucket_domain = "s3-website.ap-northeast-2.amazonaws.com"

website_bucket_name = "masterseo-t101-s3"



# 확인

terraform state list



4

s3를 static web 으로 만들자.

aws s3 cp 로 index.html 올리자.


#

aws s3 cp modules/aws-s3-static-website-bucket/www/ s3://$(terraform output -raw website_bucket_name)/ --recursive


upload: modules/aws-s3-static-website-bucket/www/index.html to s3://masterseo-t101-s3/index.html

upload: modules/aws-s3-static-website-bucket/www/error.html to s3://masterseo-t101-s3/error.html



# curl 혹은 웹 브라우저에서 S3 버킷 접속

curl -s http://$NICKNAME-t101-s3.s3-website.ap-northeast-2.amazonaws.com/

<!DOCTYPE html>

<html lang="en" dir="ltr">

<head>

<meta charset="utf-8">

<title>Static Website</title>

</head>

<body>

<p>Nothing to see here.</p>

</body>

</html>





5

확인

브라우저로 확인

http://masterseo-t101-s3.s3-website.ap-northeast-2.amazonaws.com/


40 s3-web.png



6

삭제

aws s3 rm s3://$(terraform output -raw website_bucket_name)/ --recursive


terraform destroy -auto-approve





<3> 모듈 사용시 주의점


1

별도의 폴더에 정의된 모듈에서 file 함수를 사용하기 위해서 경로 참조path reference 표현식 필요


- path.module : 표현식이 정의된 모듈의 파일 시스템 경로를 반환

- path.root : 루트 모듈의 파일 시스템 경로를 반환

- path.cwd : 현재 작업 중인 디렉터리의 파일 시스템 경로를 반환


user_data = templatefile("${path.module}/user-data.sh", {

server_port = var.server_port

db_address = data.terraform_remote_state.db.outputs.address

db_port = data.terraform_remote_state.db.outputs.port

})



2

'인라인 블록'과 '별도의 리소스'를 혼합 사용 시 서로 덮어쓰는 오류가 발생함!!!



3

[별도의 리소스] : aws_security_group 리소스와 aws_security_group_rule 리소스를 통해서 별도로 정의 사용을 권장한다.


별도의 리소스 사용 권장 이유?

스테이징 환경에서 테스트를 위해 추가로 포트를 노출 시, aws_security_group_rule 리소스를 stage/services/webserver-cluster/main.tf 에 추가.

인라인 블록으로 규칙을 정의한 경우에는 코드가 작동하지 않습니다



별도의 리소스

resource "aws_security_group" "alb" {

name = "${var.cluster_name}-alb"

}


resource "aws_security_group_rule" "allow_http_inbound" {

type = "ingress"

security_group_id = aws_security_group.alb.id


from_port = local.http_port

to_port = local.http_port

protocol = local.tcp_protocol

cidr_blocks = local.all_ips

}


resource "aws_security_group_rule" "allow_all_outbound" {

type = "egress"

security_group_id = aws_security_group.alb.id


from_port = local.any_port

to_port = local.any_port

protocol = local.any_protocol

cidr_blocks = local.all_ips

}



4

기타

[인라인 블록] : aws_security_group 리소스에 인라인 블록을 통해 인/아웃 규칙을 정의


스테이징 환경에서 테스트를 위해 추가로 포트를 노출 시, aws_security_group_rule 리소스를 stage/services/webserver-cluster/main.tf 에 추가

인라인 블록으로 규칙을 정의한 경우에는 코드가 작동하지 않습니다


resource "aws_security_group" "alb" {

name = "${var.cluster_name}-alb"


ingress {

from_port = local.http_port

to_port = local.http_port

protocol = local.tcp_protocol

cidr_blocks = local.all_ips

}


egress {

from_port = local.any_port

to_port = local.any_port

protocol = local.any_protocol

cidr_blocks = local.all_ips

}

}



다음

https://brunch.co.kr/@topasvga/2809







https://brunch.co.kr/@topasvga/2421

terraform.png


감사합니다.

keyword
매거진의 이전글19탄-14. 테라폼-AWS-모듈 이론 2