https://gasidaseo.notion.site/gasidaseo/CloudNet-Blog-c9dfa44a27ff431dafdd2edacc8a1863
개발과 프로덕션 환경에서 동일한 코드를 복사하여 사용하는 대신, 모듈로 동일하게 재사용
1
모듈의 저장소 소스
https://developer.hashicorp.com/terraform/language/modules/sources
로컬 패스, 테라폼 레지스트리, 깃허브 , 비트버킷 , s3 버킷 , GCS 버킷등 다영한 저장소 소스를 사용할수 있다!!!
2
테라폼 레지스트리의 모듈 부분 자료 참고
https://registry.terraform.io/
3
모듈 소스 참고
https://github.com/terraform-aws-modules
1
mkdir test
cd test
2
cat <<EOT > iamuser.tf
provider "aws" {
region = "ap-northeast-2"
}
locals {
name = "mytest"
team = {
group = "dev"
}
}
resource "aws_iam_user" "myiamuser1" {
name = "\${local.name}1"
tags = local.team
}
resource "aws_iam_user" "myiamuser2" {
name = "\${local.name}2"
tags = local.team
}
EOT
3
terraform init && terraform plan && terraform apply -auto-approve
4
# iam 사용자 확인
aws iam list-users | jq
mytest1
mytest2 확인
# 삭제
terraform destroy -auto-approve
1
스테이징 웹서버 클러스터를 모듈로 이동해보자.
2
디렉터리 구조
modules -services-webserver-cluster ------------ variables.tf , output.tf , main.tf , user-data.sh
stage -services -webserver-cluster
global----s3----------outputs.tf , main.tf
3
modules -services-webserver-cluster ------------ main.tf 안에는 provider를 제거한다.
모듈 안에는 provider를 제거한다.
프로바이더가 중복될 수 있어서 제거한다.
4
모듈 형식 ?
module "<NAME>" {
source = "<SOURCE>"
[CONFIG ...]
}
5
스테이징에서?
provider "aws" {
region = "us-east-2"
}
module "webserver_cluster" {
source = "../../../modules/services/webserver-cluster"
}
6
production에서?
provider "aws" {
region = "us-east-2"
}
module "webserver_cluster" {
source = "../../../modules/services/webserver-cluster"
}
7
teraform init 필수
공급자와 모듈을 가져와야 한다.
8
적용 시 실패한다!!
스테이징과 프로덕션에서 만들어지는 이름이 같아진다. 그래서 실패한다.
이름이 하드코딩되어 있어서 중복 이름이라 실패한다.
해결?
모듈에 입력 매개변수를 만들어 중복 이름이 안되도록 하자.
9
modules/services/webserver-cluster/variables.tf 에 새로운 입력 변수 3개를 추가
variable "cluster_name" {
description = "The name to use for all the cluster resources"
type = string
}
variable "db_remote_state_bucket" {
description = "The name of the S3 bucket for the database's remote state"
type = string
}
variable "db_remote_state_key" {
description = "The path for the database's remote state in S3"
type = string
}
10
modules/services/webserver-cluster/main.tf 에 하드 코딩된 이름 대신 var.cluster_name 을 사용
resource "aws_security_group" "alb" {
name = "${var.cluster_name}-alb"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
그외 태그등 AWS 리소스도 하드 코딩되어 중복되지 않게 변경 :
ex) 인스턴스 tag 리소스 : "${var.cluster_name}-instance"
11
terrroform_remote_state 데이터소스 업데이트 : bucket 과 key 매개 변수 수정
data "terraform_remote_state" "db" {
backend = "s3"
config = {
bucket = var.db_remote_state_bucket
key = var.db_remote_state_key
region = "us-east-2"
}
}
[스테이징 환경] stage/services/webserver-cluster/main.tf 에서 아래와 같이 새로운 입력 변수를 설정
module "webserver_cluster" {
source = "../../../modules/services/webserver-cluster"
cluster_name = "webservers-stage"
db_remote_state_bucket = "(YOUR_BUCKET_NAME)"
db_remote_state_key = "stage/data-stores/mysql/terraform.tfstate"
}
12
[프로덕션 환경] prod/services/webserver-cluster/main.tf 에서 아래와 같이 새로운 입력 변수를 설정
module "webserver_cluster" {
source = "../../../modules/services/webserver-cluster"
cluster_name = "webservers-prod"
db_remote_state_bucket = "(YOUR_BUCKET_NAME)"
db_remote_state_key = "prod/data-stores/mysql/terraform.tfstate"
}
13
이후 modules/services/webserver-cluster/main.tf 에서 시작 구성을 업데이트
resource "aws_launch_configuration" "example" {
image_id = "ami-0fb653ca2d3203ac1"
instance_type = var.instance_type
security_groups = [aws_security_group.instance.id]
user_data = templatefile("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
})
# Required when using a launch configuration with an auto scaling group.
lifecycle {
create_before_destroy = true
}
}
14
ASG에 업데이트
resource "aws_autoscaling_group" "example" {
launch_configuration = aws_launch_configuration.example.name
vpc_zone_identifier = data.aws_subnets.default.ids
target_group_arns = [aws_lb_target_group.asg.arn]
health_check_type = "ELB"
min_size = var.min_size
max_size = var.max_size
tag {
key = "Name"
value = var.cluster_name
propagate_at_launch = true
}
}
15
[스테이징 환경] 에서 stage/services/webserver-cluster/main.tf 에 설정
module "webserver_cluster" {
source = "../../../modules/services/webserver-cluster"
cluster_name = "webservers-stage"
db_remote_state_bucket = "(YOUR_BUCKET_NAME)"
db_remote_state_key = "stage/data-stores/mysql/terraform.tfstate"
instance_type = "t2.micro"
min_size = 2
max_size = 2
}
16
[프로덕션 환경] 에서 prod/services/webserver-cluster/main.tf 에 설정
module "webserver_cluster" {
source = "../../../modules/services/webserver-cluster"
cluster_name = "webservers-prod"
db_remote_state_bucket = "(YOUR_BUCKET_NAME)"
db_remote_state_key = "prod/data-stores/mysql/terraform.tfstate"
instance_type = "m4.large"
min_size = 2
max_size = 10
}
1
현재 보안 그룹
resource "aws_security_group" "alb" {
name = "${var.cluster_name}-alb"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
2
지역변수 활용
locals {
http_port = 80
any_port = 0
any_protocol = "-1"
tcp_protocol = "tcp"
all_ips = ["0.0.0.0/0"]
}
3
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
}
<5> 출력
1
프로덕션] 환경의 ASG에 스케줄 기반 증감 정책 : 매일 오전 8시 10대 증가 → 매일 오후 9시 2대로 감소.
resource "aws_autoscaling_schedule" "scale_out_during_business_hours" {
scheduled_action_name = "scale-out-during-business-hours"
min_size = 2
max_size = 10
desired_capacity = 10
recurrence = "0 8 * * *"
}
resource "aws_autoscaling_schedule" "scale_in_at_night" {
scheduled_action_name = "scale-in-at-night"
min_size = 2
max_size = 10
desired_capacity = 2
recurrence = "0 21 * * *"
}
2
모듈에서 ASG 이름을 출력 변수로 설정 : /modules/services/webserver-cluster/outputs.tf
output "asg_name" {
value = aws_autoscaling_group.example.name
description = "The name of the Auto Scaling Group"
모듈에서 오토스케일링 그룹의 이름을 출력으로 만든다.
3
프로덕트에서 오토 스케일링 그룹 이름을 가져와 써야 한다.
# 사용 구문
module.<MODULE_NAME>.<OUTPUT_NAME>
# 다음과 같이 사용
module.frontend.asg_name
4
ASG 코드 내용에 추가 : prod/services/webserver-cluster/main.tf
resource "aws_autoscaling_schedule" "scale_out_during_business_hours" {
scheduled_action_name = "scale-out-during-business-hours"
min_size = 2
max_size = 10
desired_capacity = 10
recurrence = "0 8 * * *"
autoscaling_group_name = module.webserver_cluster.asg_name
}
resource "aws_autoscaling_schedule" "scale_in_at_night" {
scheduled_action_name = "scale-in-at-night"
min_size = 2
max_size = 10
desired_capacity = 2
recurrence = "0 21 * * *"
autoscaling_group_name = module.webserver_cluster.asg_name
}
다음
https://brunch.co.kr/@topasvga/2808
https://brunch.co.kr/@topasvga/2421
감사합니다.