brunch

You can make anything
by writing

C.S.Lewis

by Master Seo Nov 14. 2022

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

다음은 주말 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/




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


감사합니다.

매거진의 이전글 19탄-14. 테라폼-AWS-모듈 이론 2
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari