3. 인스턴스 생성 (로드밸런서)
AWS 로드밸런서 생성
1. AWS 리전 지정
provider "aws" {
region = "us-east-2"
}2. 변수 지정
variable "server_port" {
description = "HTTP 서비스"
type = number
default = 8080
}
variable "alb_http_port" {
type = number
default = 80
}3. 보안 그룹 생성
## EC2 보안 그룹 생성
resource "aws_security_group" "instance" {
name = "terraform-example-instance"
# 인바운드 tcp 8080 트래픽 허용
ingress {
from_port = var.server_port
to_port = var.server_port
protocol = "tcp"
cidr_blocks = [ "0.0.0.0/0" ]
}
}
## ALB 보안 그룹 생성
## 80 포트에서 들어오는 요청을 허용하여 HTTP를 통해 로드밸런서에 접속
## 바깥으로 나가는 요청은 포트와 상관없이 허용하여 로드밸런서가 Health check를 수행하도록 한다.
resource "aws_security_group" "alb" {
name = "terraform-example-alb"
# 인바운드 HTTP 트래픽 허용
ingress {
from_port = var.alb_http_port
to_port = var.alv_http_port
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" ]
}
}4. Autoscaling 설정

AWS 계정에서 VPC의 서브넷 목록 불러오기
## AWS의 VPC 불러오기
data "aws_vpc" "default" {
default = true
}
## VPC 내 서브넷 조회
data "aws_subnet_ids" "default" {
vpc_id = data.aws_vpc.default.ide
}시작 구성 EC2 인스턴스 정의
## ASG로 생성할 인스턴스의 설정 정의
resource "aws_lanuch_configuration" "example" {
image_id = "ami-0a695f0d95cefc163" # 이미지 지정
instance_type = "t2.micro" # EC2 인스턴스 타입 지정
security_groups = [aws_security_group.instance.id] # EC2 보안그룹 지정
user_data = <<-EOF
# httpd 8080포트로 서비스 시작 스크립트
#!/bin/bash
echo "Hello, World" > index.html
nohup busybox httpd -f -p ${var.server_port} &
EOF
# ASG에서 시작 구성을 사용할 때 필요한 구문
# 테라폼은 AWS의 오브젝트의 값을 교체할 때, 값을 변경하지 못하는 오브젝트에 대해서는
# 기존 오브젝트를 삭제한 뒤 새로운 값으로 오브젝트르 생성한다.
# 교체되는 오브젝트가 먼저 생성된 뒤 이전 오브젝트를 삭제하는 정책
lifecycle {
create_before_destroy = true
}
}Autoscaling Group 생성
## ASG 생성
resource "aws_autoscaling_group" "example" {
lanuch_configuration = aws_lanuch_configuration.example.name
vpc_zone_identifier = data.aws_subnet_ids.default.ids
# EC2 인스턴스 목록을 ALB 대상 그룹으로 연결
# ASG가 대상 그룹의 상태 확인을 하여 인스턴스가 정상인지 여부를 판별하고
# 대상 그룹이 상태 불량으로 보고되면 인스턴스를 자동으로 교체하도록 지시한다.
target_groups_arns = [aws_lb_target_group.asg.arn]
health_check_type = "ELB"
min_size = 2
max_size = 10
tag {
key = "Name"
value = "Autoscaling-example"
propagate_at_launch = true
}
}5. 로드밸런서 배포


## ALB 리스너 정의
resource "aws_lb_listener" "http" {
load_balancer_arn = aws_lb.example.arn
port = 80
protocol = "HTTP"
# 기본 값으로 단순한 404 페이지 오류 반환
# 리스너 규칙과 일치하지 않는 요청에 대해 기본 응답으로 404 페이지를 보내도록 구성
default_action {
type = "fixed-response"
fixed_response {
content_type = "text/plain"
message_body = "404: page not found"
status_code = 404
}
}
}ALB 리스너 규칙 생성
리스너 규칙을 생성하여 위에서 생성한 부분을 연결
resource "aws_lb_listener_rule" "asg" {
listener_arn = aws_lb_listener.http.arn
priority = 100
condition {
path_pattern {
values = ["*"]
}
}
action {
type = "forward"
target_group_arn = aws_lb_target_group.asg.arn
}
}모든 경로와 일치하는 요청을 ASG가 포함된 대상 그룹으로 보내는 리스너 규칙
ALB DNS 이름 출력
output "alb_dns_name" {
value = aws_lb.example.dns_name
description = "로드밸런서 도메인 네임"
}terraform apply 시 생성한 로드밸런서의 DNS 이름이 출력된다.
6. 확인
terraform apply
PS C:\terraform_code> terraform plan
data.aws_vpc.default: Reading...
data.aws_vpc.default: Read complete after 2s [id=vpc-070ddb03df90391be]
data.aws_subnet_ids.default: Reading...
data.aws_subnet_ids.default: Read complete after 0s [id=vpc-070ddb03df90391be]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
+ create
Terraform will perform the following actions:
# aws_autoscaling_group.example will be created
+ resource "aws_autoscaling_group" "example" {
+ arn = (known after apply)
+ availability_zones = (known after apply)
+ default_cooldown = (known after apply)
+ desired_capacity = (known after apply)
+ force_delete = false
+ force_delete_warm_pool = false
+ health_check_grace_period = 300
+ health_check_type = "ELB"
+ id = (known after apply)
+ launch_configuration = (known after apply)
+ max_size = 10
+ metrics_granularity = "1Minute"
+ min_size = 2
+ name = (known after apply)
+ name_prefix = (known after apply)
+ protect_from_scale_in = false
+ service_linked_role_arn = (known after apply)
+ target_group_arns = (known after apply)
+ vpc_zone_identifier = [
+ "subnet-0753b66315e0af6e3",
+ "subnet-077820c8912f1f5c2",
+ "subnet-0df722400e6b54e2a",
]
+ wait_for_capacity_timeout = "10m"
+ tag {
+ key = "Name"
+ propagate_at_launch = true
+ value = "Autoscaling-example"
}
}
# aws_launch_configuration.example will be created
+ resource "aws_launch_configuration" "example" {
+ arn = (known after apply)
+ associate_public_ip_address = (known after apply)
+ ebs_optimized = (known after apply)
+ enable_monitoring = true
+ id = (known after apply)
+ image_id = "ami-0a695f0d95cefc163"
+ instance_type = "t2.micro"
+ key_name = (known after apply)
+ name = (known after apply)
+ name_prefix = (known after apply)
+ security_groups = (known after apply)
+ user_data = "a1323b251462faf59ee4c09a927f5250b15db09c"
}
# aws_lb.example will be created
+ resource "aws_lb" "example" {
+ arn = (known after apply)
+ arn_suffix = (known after apply)
+ desync_mitigation_mode = "defensive"
+ dns_name = (known after apply)
+ drop_invalid_header_fields = false
+ enable_deletion_protection = false
+ enable_http2 = true
+ enable_tls_version_and_cipher_suite_headers = false
+ enable_waf_fail_open = false
+ enable_xff_client_port = false
+ id = (known after apply)
+ idle_timeout = 60
+ internal = (known after apply)
+ ip_address_type = (known after apply)
+ load_balancer_type = "application"
+ name = "terraform-asg-example"
+ preserve_host_header = false
+ security_groups = (known after apply)
+ subnets = [
+ "subnet-0753b66315e0af6e3",
+ "subnet-077820c8912f1f5c2",
+ "subnet-0df722400e6b54e2a",
]
+ tags_all = (known after apply)
+ vpc_id = (known after apply)
+ xff_header_processing_mode = "append"
+ zone_id = (known after apply)
}
# aws_lb_listener.http will be created
+ resource "aws_lb_listener" "http" {
+ arn = (known after apply)
+ id = (known after apply)
+ load_balancer_arn = (known after apply)
+ port = 80
+ protocol = "HTTP"
+ ssl_policy = (known after apply)
+ tags_all = (known after apply)
+ default_action {
+ order = (known after apply)
+ type = "fixed-response"
+ fixed_response {
+ content_type = "text/plain"
+ message_body = "404: page not found"
+ status_code = "404"
}
}
}
# aws_lb_listener_rule.asg will be created
+ resource "aws_lb_listener_rule" "asg" {
+ arn = (known after apply)
+ id = (known after apply)
+ listener_arn = (known after apply)
+ priority = 100
+ tags_all = (known after apply)
+ action {
+ order = (known after apply)
+ target_group_arn = (known after apply)
+ type = "forward"
}
+ condition {
+ path_pattern {
+ values = [
+ "*",
]
}
}
}
# aws_lb_target_group.asg will be created
+ resource "aws_lb_target_group" "asg" {
+ arn = (known after apply)
+ arn_suffix = (known after apply)
+ connection_termination = false
+ deregistration_delay = "300"
+ id = (known after apply)
+ ip_address_type = (known after apply)
+ lambda_multi_value_headers_enabled = false
+ load_balancing_algorithm_type = (known after apply)
+ load_balancing_cross_zone_enabled = (known after apply)
+ name = "terraform-asg-example"
+ port = 8080
+ preserve_client_ip = (known after apply)
+ protocol = "HTTP"
+ protocol_version = (known after apply)
+ proxy_protocol_v2 = false
+ slow_start = 0
+ tags_all = (known after apply)
+ target_type = "instance"
+ vpc_id = "vpc-070ddb03df90391be"
+ health_check {
+ enabled = true
+ healthy_threshold = 2
+ interval = 15
+ matcher = "200"
+ path = "/"
+ port = "traffic-port"
+ protocol = "HTTP"
+ timeout = 3
+ unhealthy_threshold = 2
}
}
# aws_security_group.alb will be created
+ resource "aws_security_group" "alb" {
+ arn = (known after apply)
+ description = "Managed by Terraform"
+ egress = [
+ {
+ cidr_blocks = [
+ "0.0.0.0/0",
]
+ description = ""
+ from_port = 0
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "-1"
+ security_groups = []
+ self = false
+ to_port = 0
},
]
+ id = (known after apply)
+ ingress = [
+ {
+ cidr_blocks = [
+ "0.0.0.0/0",
]
+ description = ""
+ from_port = 80
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "tcp"
+ security_groups = []
+ self = false
+ to_port = 80
},
]
+ name = "terraform-example-alb"
+ name_prefix = (known after apply)
+ owner_id = (known after apply)
+ revoke_rules_on_delete = false
+ tags_all = (known after apply)
+ vpc_id = (known after apply)
}
# aws_security_group.instance will be created
+ resource "aws_security_group" "instance" {
+ arn = (known after apply)
+ description = "Managed by Terraform"
+ egress = (known after apply)
+ id = (known after apply)
+ ingress = [
+ {
+ cidr_blocks = [
+ "0.0.0.0/0",
]
+ description = ""
+ from_port = 8080
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "tcp"
+ security_groups = []
+ self = false
+ to_port = 8080
},
]
+ name = "terraform-example-instance"
+ name_prefix = (known after apply)
+ owner_id = (known after apply)
+ revoke_rules_on_delete = false
+ tags_all = (known after apply)
+ vpc_id = (known after apply)
}
Plan: 8 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ alb_dns_name = (known after apply)
╷
│ Warning: Deprecated Resource
│
│ with data.aws_subnet_ids.default,
│ on main.tf line 80, in data "aws_subnet_ids" "default":
│ 80: data "aws_subnet_ids" "default"{
│
│ The aws_subnet_ids data source has been deprecated and will be removed in a future version. Use the aws_subnets data source
│ instead: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnets
│
│ (and one more similar warning elsewhere)
╵
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run
"terraform apply" now.작성한 코드 점검
terraform apply
PS C:\terraform_code> terraform apply
[...]
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
[...]
Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
Outputs:
alb_dns_name = "terraform-asg-example-190757077.us-east-2.elb.amazonaws.com"웹 서버 접속

이 상태에서 인스턴스 중 하나를 종료시키면 ALB는 인스턴스가 다운되었음을 자동으로 감지하고 라우팅을 중지시킨다.
인스턴스가 종료된 후 얼마 지나지 않아 ASG는 2개 미만의 인스턴스가 실행 중임을 감지하고 자동으로 새 인스턴스를 시작하여 인스턴스를 복구한다.
7. 리소스 삭제
terraform destroy
테스트 완료 후 생성한 리소스 삭제
PS C:\terraform_code> terraform destroy
[...]
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
[...]
Destroy complete! Resources: 8 destroyed.Last updated