목표
테라폼으로 auto scaling group, Application Load Balancer을 생성합니다.
요구사항
- Auto Scaling Group은 4번째 과제를 사용하되 user data에 httpd(80/tcp)를 실행합니다.
- http://ALB:80으로 요청하면 Auto Scaling Group이 관리하는 EC2 Instance로 부하분산 해야 합니다.
- vpc는 전글(https://malwareanalysis.tistory.com/438)에 생성한 리소스를 사용합니다.
- route table은 전글(https://malwareanalysis.tistory.com/441)에서 생성한 리소스를 사용합니다.
- security group은 전글(https://malwareanalysis.tistory.com/443)에 생성한 리소스를 사용합니다.
- Auto Scaling Group은 전글(https://malwareanalysis.tistory.com/443)에서 생성한 리소스를 사용합니다.
상세내용
auto scaling과 alb연결은 하이레벨 수준에서는 아래그림과 같습니다. auto scaling이 관리하는 EC2 Instance를 alb가 자동으로 인식하여 트래픽을 부하분산합니다.
테라폼 코드로 위 흐름을 구현하려면 세부과정을 알아야합니다. ALB는 외부 요청을 받는 Listener와 Target group으로 구성됩니다. 그리고 Auto Scaling group이 Target group으로 연결하면 구성이 끝납니다.
Auto scaling group에서 Targer group연결할때는 Load balancing과 Health checks필드를 설정합니다.
코드작성
gitbub링크: https://github.com/sungwook-practice/terraform-study/tree/main/week2/alb
vpc.tf, sg.tf, asg.tf, alb.tf파일로 분리했습니다. ami는 data block을 사용했습니다.
- vpc.tf
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_vpc" "akbun-vpc" {
cidr_block = "10.10.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "t101-study"
}
}
resource "aws_subnet" "akbun-subnet1" {
vpc_id = aws_vpc.akbun-vpc.id
cidr_block = "10.10.1.0/24"
availability_zone = "ap-northeast-2a"
tags = {
Name = "t101-subnet1"
}
}
resource "aws_subnet" "akbun-subnet2" {
vpc_id = aws_vpc.akbun-vpc.id
cidr_block = "10.10.2.0/24"
availability_zone = "ap-northeast-2c"
tags = {
Name = "t101-subnet2"
}
}
resource "aws_internet_gateway" "akbun-igw" {
vpc_id = aws_vpc.akbun-vpc.id
tags = {
Name = "t101-igw"
}
}
# route table 생성
resource "aws_route_table" "akbun-rt" {
vpc_id = aws_vpc.akbun-vpc.id
tags = {
Name = "t101-rt"
}
}
# route table과 subnet 연결
resource "aws_route_table_association" "akubun-rt-association1" {
subnet_id = aws_subnet.akbun-subnet1.id
route_table_id = aws_route_table.akbun-rt.id
}
# route table과 subnet 연결
resource "aws_route_table_association" "akubun-rt-association2" {
subnet_id = aws_subnet.akbun-subnet2.id
route_table_id = aws_route_table.akbun-rt.id
}
# route 규칙 추가
resource "aws_route" "mydefaultroute" {
route_table_id = aws_route_table.akbun-rt.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.akbun-igw.id
}
- sg.tf
resource "aws_security_group" "akbun-mysg" {
vpc_id = aws_vpc.akbun-vpc.id
name = "T101 SG"
description = "T101 Study SG"
}
resource "aws_security_group_rule" "mysginbound" {
type = "ingress"
from_port = 0
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.akbun-mysg.id
}
resource "aws_security_group_rule" "mysgoutbound" {
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.akbun-mysg.id
}
- alb.tf
외부에서 HTTP프로토콜 80/tcp를 요청하면 target group으로 포워딩 될 수 있도록 규칙을 추가했습니다.
resource "aws_lb" "akbun-alb" {
name = "t101-alb"
load_balancer_type = "application"
subnets = [aws_subnet.akbun-subnet1.id, aws_subnet.akbun-subnet2.id]
security_groups = [aws_security_group.akbun-mysg.id]
tags = {
Name = "t101-alb"
}
}
resource "aws_lb_listener" "myhttp" {
load_balancer_arn = aws_lb.akbun-alb.arn
port = 80
protocol = "HTTP"
# By default, return a simple 404 page
default_action {
type = "fixed-response"
fixed_response {
content_type = "text/plain"
message_body = "404: page not found - T101 Study"
status_code = 404
}
}
}
resource "aws_lb_target_group" "akbun-tg" {
name = "t101-alb-tg"
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.akbun-vpc.id
health_check {
path = "/"
protocol = "HTTP"
matcher = "200-299"
interval = 5
timeout = 3
healthy_threshold = 2
unhealthy_threshold = 2
}
}
resource "aws_lb_listener_rule" "akbun-albrule" {
listener_arn = aws_lb_listener.myhttp.arn
priority = 100
condition {
path_pattern {
values = ["*"]
}
}
action {
type = "forward"
target_group_arn = aws_lb_target_group.akbun-tg.arn
}
}
output "akbunalb_dns" {
value = aws_lb.akbun-alb.dns_name
description = "The DNS Address of the ALB"
}
- asg.tf
health 방식을 ELB로 설정하고 target group을 테라폼 코드에서 생성한 target group을 설정했습니다. 그리고 EC2 Instance최소 갯수를 2개로 설정했습니다. user_data는 인스턴스 정보를 출력하는 웹 애플리케이션을 실행합니다.
resource "aws_autoscaling_group" "akbun-asg" {
name = "myasg"
launch_configuration = aws_launch_configuration.akbun-launchconfig.name
vpc_zone_identifier = [aws_subnet.akbun-subnet1.id, aws_subnet.akbun-subnet2.id]
# ELB 연결
health_check_type = "ELB"
target_group_arns = [aws_lb_target_group.akbun-tg.arn]
min_size = 2
max_size = 4
tag {
key = "Name"
value = "terraform-asg"
propagate_at_launch = true
}
}
resource "aws_launch_configuration" "akbun-launchconfig" {
name_prefix = "t101-lauchconfig-"
image_id = data.aws_ami.my_amazonlinux2.id
instance_type = "t2.nano"
security_groups = [aws_security_group.akbun-mysg.id]
associate_public_ip_address = true
user_data = <<-EOF
#!/bin/bash
wget https://busybox.net/downloads/binaries/1.31.0-defconfig-multiarch-musl/busybox-x86_64
mv busybox-x86_64 busybox
chmod +x busybox
RZAZ=$(curl http://169.254.169.254/latest/meta-data/placement/availability-zone-id)
IID=$(curl 169.254.169.254/latest/meta-data/instance-id)
LIP=$(curl 169.254.169.254/latest/meta-data/local-ipv4)
echo "<h1>RegionAz($RZAZ) : Instance ID($IID) : Private IP($LIP) : Web Server</h1>" > index.html
nohup ./busybox httpd -f -p 80 &
EOF
# Required when using a launch configuration with an auto scaling group.
lifecycle {
create_before_destroy = true
}
}
- data.tf
data "aws_ami" "my_amazonlinux2" {
most_recent = true
filter {
name = "owner-alias"
values = ["amazon"]
}
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-ebs"]
}
owners = ["amazon"]
}
코드 반영
terraform apply명령어로 테라폼 코드를 aws에 반영합니다.
terraform apply
로드밸런서가 잘 생성되었는지 확인합니다. 그리고 Listeners탭에서 테라폼 코드가 추가한 규칙을 클릭합니다.
규칙 중 모든 요청이 Target Group으로 포워딩되는지 확인합니다.
Auto Scaling Group에서 Target Group과 연결이 잘 되었는지 확인합니다.
Target Group에서 Auto Scaling이 관리하는 EC2 Instance가 보이는지 확인합니다. 테라폼 코드에서 min_size를 2개로 설정했으므로 EC2 Instance가 총 2개입니다.
자 이제 ALB로 요청하면 Auto Scaling Group이 관리하는 EC2 Instance로 부하 분산되는지 확인해봅시다. curl과 sort, uniq명령어로 부하 분산이 되는지 쉽게 확인할 수 있습니다. 거의 50:50 비율로 2개의 EC2 Instance로 부하 분산이 잘 되었습니다.
ALBDNS=$(terraform output -raw akbunalb_dns)
for i in {1..100}; do curl -s http://$ALBDNS/ ; done | sort | uniq -c | sort -nr
'연재 시리즈' 카테고리의 다른 글
테라폼 시리즈 21편. 상태파일 민감정보 (0) | 2022.11.03 |
---|---|
테라폼 시리즈 20편. 협업을 위한 테라폼 관리 (0) | 2022.10.29 |
테라폼 시리즈 18편. auto scaling group생성 (0) | 2022.10.28 |
테라폼 시리즈 17편. security group 생성 (0) | 2022.10.28 |
테라폼 시리즈 16편. route table 생성 (0) | 2022.10.26 |