이번 포스트에서는 테라폼으로 AutoScailing을 적용시켜 보자
📌 서론
Auto Scailing Group을 테라폼으로 사용하려면 어떻게 해야 할까? 이번 포스트를 통해 테라폼으로 ASG를 생성하고 로드 밸런서까지 연결시켜 보자
1. Auto Scailing Group이란?
AWS Auto Scaling Group의 개념
- AWS Auto Scaling Group (ASG)은 AWS 클라우드 환경에서 중요한 역할을 하는 서비스다. ASG를 이용하면 동일한 설정을 가진 EC2 인스턴스들을 그룹으로 묶어, 이들의 숫자를 자동으로 조절할 수 있다. 이는 애플리케이션의 부하에 따라 필요한 컴퓨팅 리소스를 유연하게 관리하는 데 도움을 준다.
ASG의 작동 원리
- ASG는 미리 정의된 조건에 따라 EC2 인스턴스의 수를 자동으로 늘리거나 줄인다. 예를 들어, 웹사이트의 트래픽이 증가할 때 자동으로 인스턴스를 추가하여 처리 능력을 강화하고, 트래픽이 감소하면 불필요한 인스턴스를 제거하여 비용을 절감할 수 있다.
운영 비용의 최적화
- ASG의 가장 큰 장점 중 하나는 운영 비용의 최적화다. 실시간 트래픽과 같은 동적인 요구에 맞춰 인스턴스를 자동으로 조절함으로써, 항상 최적의 리소스를 유지할 수 있다. 이는 높은 트래픽 시간에는 충분한 리소스를 제공하고, 낮은 트래픽 시간에는 비용을 절약할 수 있게 해 준다.
높은 가용성과 확장성
- ASG는 높은 가용성과 확장성을 제공한다. 특정 인스턴스가 기동에 실패하거나 "health check"를 통과하지 못하면, ASG는 자동으로 새 인스턴스를 시작하여 서비스 중단을 최소화한다. 또한, 다양한 지역(region) 및 가용 영역에 걸쳐 인스턴스를 분산시킬 수 있어, 지리적 재해에 대한 복원력도 강화된다.
사용 사례와 장점
- ASG는 웹 서버, 백엔드 서비스, 배치 처리 작업 등 다양한 용도로 활용된다. 또한, 정해진 일정에 따라 인스턴스의 수를 조절할 수도 있어, 예측 가능한 트래픽 변동 패턴에 효과적으로 대응할 수 있다. 이는 더욱 효율적인 리소스 관리와 안정적인 서비스 운영을 가능하게 한다.
2. VPC와 서브넷(subnet) 구성하기
VPC와 서브넷 구성하기
- 이 Terraform 구성은 새로운 가상 사설 네트워크, 즉 VPC를 만드는 것이다. 이 VPC 안에는 공용 서브넷(public subnet)이 포함되어 있다. 우리는 여기에 'vpc 모듈'을 사용해서 VPC를 구성한다. 이 모듈을 사용하면 VPC와 관련된 여러 설정을 쉽게 할 수 있다.
VPC 모듈의 정의
- 아래의 코드에서 module "vpc" 부분은 Terraform에서 제공하는 VPC 모듈을 불러온다. 이 모듈을 이용해 VPC를 만들어준다.
- cidr은 내가 만들 VPC의 IP 주소 범위를 정의하는 것이다. 여기서는 10.0.0.0/16이라고 설정해 줬다.
- azs와 public_subnets는 AWS의 가용 영역(azs)과 공용 서브넷의 CIDR 블록을 설정하는 부분이다.
- enable_nat_gateway와 enable_vpn_gateway는 각각 NAT 게이트웨이와 VPN 게이트웨이를 활성화하는 데 쓰인다.
- tags는 이 리소스에 추가 정보를 달아주는 라벨이다. 예를 들면 환경이나 프로젝트 이름을 나타낸다.
# VPC 모듈 정의
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "2.77.0" # 적절한 버전 사용
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b"]
public_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
enable_nat_gateway = true
enable_vpn_gateway = true
tags = {
"Environment" = "dev"
"Project" = "MyProject"
}
}
VPC ID 출력
- output "vpc_id" 부분은 만들어진 VPC의 ID를 다른 리소스들이 참조할 수 있게 출력해 주는 것이다. 이렇게 하면 다른 리소스, 예를 들어 aws_lb_target_group, 에서 이 VPC ID를 필요로 할 때 module.vpc.vpc_id를 사용해서 참조할 수 있다.
# VPC ID 출력
output "vpc_id" {
value = module.vpc.vpc_id
}
3. 보안 그룹(Security groups) 설정하기
EC2 인스턴스용 보안 그룹 설정
- 이 설정은 Auto Scaling Group의 EC2 인스턴스에 적용될 보안 그룹을 정의한다. 주로 웹 트래픽을 허용하기 위해 80번 포트를 개방한다.
resource "aws_security_group" "terramino_instance" {
name = "learn-asg-terramino-instance"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
security_groups = [aws_security_group.terramino_lb.id]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
vpc_id = module.vpc.vpc_id
}
로드 밸런서용 보안 그룹
- 이 그룹은 로드 밸런서에 적용되며, 마찬가지로 80번 포트에서 들어오는 트래픽을 허용한다.
resource "aws_security_group" "terramino_lb" {
name = "learn-asg-terramino-lb"
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"]
}
vpc_id = module.vpc.vpc_id
}
이 두 보안 그룹의 중요한 차이점은, EC2 인스턴스용 보안 그룹(aws_security_group.terramino_instance)은 로드 밸런서용 보안 그룹(aws_security_group.terramino_lb)과 연결된 곳에서만 들어오는 트래픽을 허용한다는 점이다.즉, 로드 밸런서를 통과하는 트래픽만이 EC2 인스턴스에 도달할 수 있도록 설정된 것이다. 이는 보안을 강화하고 불필요한 트래픽을 필터링하는 데 중요한 역할을 한다.
Terraform에서 모듈로 선언된 VPC ID 가져오기
# VPC 모듈 정의
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "2.77.0" # 적절한 버전 사용
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b"]
public_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
enable_nat_gateway = true
enable_vpn_gateway = true
tags = {
"Environment" = "dev"
"Project" = "MyProject"
}
}
VPC ID 출력
- 모듈이 VPC를 만들면, 그 VPC의 ID를 어떻게 알 수 있을까? 바로 output을 사용해서다. output "vpc_id" 부분은 모듈이 만든 VPC의 ID를 Terraform 출력으로 보여주는 것이다. 이렇게 하면, 모듈이 만든 VPC ID를 다른 Terraform 코드에서 쉽게 참조할 수 있다.
# VPC ID 출력
output "vpc_id" {
value = module.vpc.vpc_id
}
모듈 출력값 활용
- 이제, 다른 Terraform 파일에서 이 VPC ID를 사용하고 싶다면, module.vpc.vpc_id라고 써서 접근한다. 여기서 module.vpc는 내가 만든 VPC 모듈을 가리키고, vpc_id는 그 VPC의 ID를 의미한다.
내부 속성 직접 참조
- 마지막으로, Terraform 모듈은 내부에서 만들어진 리소스의 속성들을 외부에서 바로 참조할 수 있게 해 준다. 예를 들어, module.vpc.public_subnets는 모듈이 만든 공용 서브넷 ID들을 말한다. 이런 속성들은 모듈 내부에서 생성되고 관리되기 때문에, 별도의 output 없이도 바로 참조할 수 있다.
4. EC2 lauch configuration 작성하기
EC2 Launch Configuration 작성
- AWS Auto Scaling Group이 새로운 EC2 인스턴스를 시작할 때 참조하는 설정을 aws_launch_configuration 리소스로 정의한다. 이 구성에는 인스턴스 이름 접두사, 사용할 AMI, 인스턴스 타입, 사용자 데이터 스크립트 및 보안 그룹이 포함된다.
resource "aws_launch_configuration" "terramino" {
name_prefix = "terraform-asg-"
image_id = data.aws_ami.amazon-linux.id
instance_type = "t2.micro"
user_data = file("user-data.sh")
security_groups = [aws_security_group.terramino_instance.id]
lifecycle {
create_before_destroy = true
}
}
주요 구성 요소 설명
- 인스턴스 이름 접두사(name_prefix)
- 사용할 Amazon Linux AMI(image_id)
- 인스턴스 타입(instance_type) -> 인스턴스의 타입을 작성한다 ex) t2.micro
- 사용자 데이터 스크립트(user_data) -> 인스턴스가 시작될 때 필요한 설정을 자동으로 처리해 준다.
- 보안 그룹(security_groups) -> 예를 들면 80번 포트로 들어오는 트래픽을 허용한다.
lifecycle 블록의 중요성 이해하기
- lifecycle 블록 내의 create_before_destroy 옵션은 이 리소스의 업데이트 방식을 제어한다. 통상적으로 Terraform은 변경 사항을 적용하기 위해 기존 리소스를 먼저 파괴하고 새 리소스를 생성한다. 하지만 create_before_destroy = true를 설정하면 이 순서가 뒤바뀌어, 새 리소스가 먼저 생성되고 이후에 기존 리소스가 파괴된다.
- 이 설정은 특히 중요한 업데이트가 진행될 때 서비스의 중단을 최소화한다. 예를 들어, 새로운 인스턴스 타입으로의 업그레이드나 AMI 변경 등이 있을 때, 새 설정이 완전히 구성되고 작동하는 것을 확인한 후에 기존 설정을 제거함으로써 안정성을 보장한다.
aws_launch_configuration 작성 시 주의사항
- 테라폼을 사용할 때 aws_launch_configuration 같은 리소스는 특별한 처리가 필요하다. 이 리소스는 한 번 만들어진 후에는 직접적으로 수정이 불가능하다. 예를 들어, 리소스 설정을 바꾸고 terraform apply 명령어를 실행해도 기존에 만들어진 리소스는 업데이트되지 않는다. 이런 특성 때문에 위에서 설명한 lifecycle 옵션을 사용하는 것이 중요하다.
lifecycle {
create_before_destroy = true
}
5. Auto Scaling group 설정
ASG의 정의 및 목적
- Auto Scaling Group (ASG)은 동일한 구성을 가진 EC2 인스턴스들을 논리적으로 그룹화한 것이다. ASG를 사용하면, 동적으로 확장 및 축소가 가능하며, 이로 인해 동일한 서비스를 제공하는 인스턴스 그룹을 효율적으로 관리할 수 있다.
- vpc_zone_identifier에는 module로 선언해 준 vpc의 public subnets를 참조하도록 해서 위에서 선언해 준 VPC의 public subnet에서 ASG이 인스턴스를 시작하도록 설정한다.
resource "aws_autoscaling_group" "terramino" {
min_size = 1
max_size = 3
desired_capacity = 1
launch_configuration = aws_launch_configuration.terramino.name
vpc_zone_identifier = module.vpc.public_subnets
}
주요 구성 요소
min_size 및 max_size
- 이 값들은 ASG 내에서 허용되는 인스턴스의 최소 및 최대 수를 정의한다. 이를 통해 ASG의 크기를 동적으로 조절할 수 있다.
desired_capacity
- 이는 ASG에서 유지하고자 하는 인스턴스 수를 지정한다.
launch_configuration
- 각 인스턴스를 시작할 때 사용될 구성을 명시한다. (위에서 정의한 launch_configuration을 여기서 참조한다.)
vpc_zone_identifier
- ASG가 새 인스턴스를 시작할 서브넷을 지정한다. (위에서 정의한 VPC 모듈의 public subnet을 여기서 참조한다.)
- 모듈값에서 public subnet을 가져다 사용하는데 이 내용은 위의 3-3번의 "내부 속성 직접 참조"를 다시 읽어보면 이해가 쉬울 것이다.
ASG 리소스에 lifecycle 추가하기
- Terraform의 ignore_changes 설정은 특정 리소스의 속성에 대해 외부 변경사항을 무시하도록 설정하는 데 사용된다. 이 설정의 주된 목적은 Terraform이 관리하는 인프라에 대한 수동 변경사항이 Terraform의 계획(plan)과 적용(apply) 과정에 영향을 주지 않도록 하는 것이다.
- "ignore_changes" 설정은 주로 외부에서 (예: AWS 콘솔에서) 수동으로 변경된 설정을 말한다. 즉, "desired_capacity"나 "target_group_arns"가 AWS 콘솔이나 다른 도구를 통해 변경되더라도 Terraform은 이러한 변경을 무시하고, Terraform 코드에 명시된 원래 설정을 유지한다. Terraform 코드 자체를 변경하는 경우에는 "ignore_changes" 설정과 관계없이 코드에 따라 리소스가 업데이트된다.
resource "aws_autoscaling_group" "terramino" {
min_size = 1
max_size = 3
desired_capacity = 1
launch_configuration = aws_launch_configuration.terramino.name
vpc_zone_identifier = module.vpc.public_subnets
lifecycle {
ignore_changes = [desired_capacity, target_group_arns]
}
}
ignore_changes를 예시를 통해 알아보자
ignore_changes 설정이 없는 경우
- Terraform 코드에서 Auto Scaling Group의 desired_capacity를 3으로 설정했다고 가정한다.
- 누군가 AWS 콘솔에서 이 값을 5로 변경한다.
- Terraform을 다시 실행할 때, Terraform은 현재 AWS 상태(5)와 Terraform 코드(3) 간의 차이를 감지한다.
- Terraform은 이 차이를 해소하기 위해 AWS 상태를 Terraform 코드에 명시된 상태(3)로 돌려놓는다. 즉, AWS 콘솔에서 변경된 desired_capacity 5를 무시하고 다시 3으로 설정한다.
ignore_changes 설정이 있는 경우
- 마찬가지로 Terraform 코드에서 desired_capacity를 3으로 설정했다고 가정한다.
- Terraform 코드에는 ignore_changes 설정이 추가되어 desired_capacity 변경사항을 무시한다.
- AWS 콘솔에서 누군가 desired_capacity를 5로 변경한다.
- Terraform을 다시 실행할 때, ignore_changes 설정 때문에 Terraform은 AWS 상태(5)와 Terraform 코드(3) 간의 차이를 무시한다.
- 즉, Terraform은 AWS 상태를 그대로 두고 코드의 상태(3)를 변경하지 않는다. AWS 콘솔에서 desired_capacity가 5로 설정되어 있어도 Terraform은 이를 무시하고 3으로 유지하지만, 실제 AWS 상태는 5로 유지된다.
이 차이는 Terraform이 인프라의 상태를 관리하는 방식에 따라 달라진다. ignore_changes 설정이 없으면 Terraform은 AWS 상태를 코드와 일치시키려고 시도한다. 반면 ignore_changes 설정이 있으면 Terraform은 해당 속성의 외부 변경사항을 무시하고, 코드 상의 설정을 유지하지만, 실제 AWS 상태는 변경된 상태로 유지한다.
6. Load balancer resources 설정하기
로드 밸런서 타겟 그룹 설정 (aws_lb_target_group)
- 타겟 그룹은 로드 밸런서가 트래픽을 전달할 EC2 인스턴스들을 지정한다. 여기서는 로드 밸런서가 어떤 인스턴스에게 트래픽을 보낼지 결정하는 역할을 한다.
resource "aws_lb_target_group" "hashicups" {
name = "learn-asg-hashicups"
port = 80
protocol = "HTTP"
vpc_id = module.vpc.vpc_id
}
애플리케이션 로드 밸런서 생성 (aws_lb)
- 로드 밸런서는 네트워크 트래픽을 여러 서버에 분산시키는 역할을 한다. 로드 밸런서는 타겟 그룹을 사용해서 트래픽을 적절한 인스턴스에 분산시킨다.
resource "aws_lb" "terramino" {
name = "learn-asg-terramino-lb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.terramino_lb.id]
subnets = module.vpc.public_subnets
}
로드 밸런서 리스너 설정 (aws_lb_listener)
- 리스너는 로드 밸런서가 특정 포트(예: 80)에서 들어오는 요청을 어떻게 처리할지 결정한다. 리스너는 로드 밸런서로 들어오는 요청을 타겟 그룹으로 전달하는 규칙을 설정한다. (6-1, 6-2번에서 선언해 준 타겟 그룹과 로드 밸런서가 이곳에서 사용된다)
resource "aws_lb_listener" "terramino" {
load_balancer_arn = aws_lb.terramino.arn
port = "80"
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.terramino.arn
}
}
7. AutoScailingGroup과 LoadBalancer 연결하기
오토스케일링 그룹(ASG)을 로드 밸런서의 타겟 그룹과 연결하는 이유
- AWS에서 오토스케일링 그룹(ASG)을 로드 밸런서의 타겟 그룹과 연결하는 건 마치 효율적으로 사람들을 관리하고, 일을 분배하는 팀과 같다. 각각의 역할을 쉽게 이해하기 위해 이렇게 비유해 볼 수 있다.
LoadBalancer (로드 밸런서) = 팀장
- 팀장(LB)은 팀에 들어오는 일(트래픽)을 관리한다. 그런데 팀장은 직접 일을 누구에게 줄지 결정하지 않는다. 대신, 일을 '타겟 그룹'이라는 특정 팀에 넘긴다. 이 팀에는 일을 할 준비가 된 팀원들(서버)이 있다.
ASG (오토스케일링 그룹) = 팀원들 관리하는 부서
- 팀원 관리 부서(ASG)는 팀원들의 수를 조절한다. 일이 많아지면, 이 부서는 더 많은 팀원들을 '타겟 그룹'에 추가한다. 반대로 일이 줄어들면, 일부 팀원들을 '타겟 그룹'에서 제거한다.
Target Group (타겟 그룹) = 일을 할 팀원들
- 이 타겟 그룹에 속한 팀원들(EC2 인스턴스)은 로드 밸런서(LB)로부터 들어오는 네트워크 트래픽을 처리한다. 로드 밸런서는 들어오는 요청(트래픽)을 이 타겟 그룹에 있는 인스턴스들에게 고르게 분배한다.
ASG와 타겟 그룹의 연결 = 부서에서 팀원들에게 일 배정
- 부서(ASG)는 적절한 팀원들(타겟 그룹)에게 일을 배정하는 역할을 한다. 이렇게 하면 일의 양에 따라 팀원들이 일을 하거나 쉴 수 있다.
간소화된 관리
- 팀장(LB)은 일을 나누는 일만 하고, 팀원들의 수를 조절하는 일은 팀원 관리 부서(ASG)가 맡는다. 이렇게 역할이 분담되면 모든 일이 더 효율적으로 진행된다.
요약하자면, ASG를 타겟 그룹과 연결하는 것은 트래픽 분산, 서버 관리, 가용성 및 확장성을 효율적으로 관리하기 위한 방식입니다. "로드 밸런서 리스너"는 트래픽을 어떻게 처리할지 결정하는 역할을 하며, "ASG"와 "타겟 그룹"의 연결은 동적 인스턴스 관리와 트래픽 분산을 가능하게 한다.
오토스케일링 그룹과 타겟 그룹 연결하기
- 마지막으로, aws_autoscaling_attachment 리소스를 사용하여 오토스케일링 그룹을 타겟 그룹에 연결한다. 이 설정으로 AWS는 인스턴스 수명 주기 동안 자동으로 타겟 그룹에 인스턴스를 추가하거나 제거할 수 있습니다.
resource "aws_autoscaling_attachment" "terramino" {
autoscaling_group_name = aws_autoscaling_group.terramino.id
alb_target_group_arn = aws_lb_target_group.terramino.arn
}
이 포스트는 Team chillwave에서 사이드 프로젝트 중 적용했던 부분을 다시 공부하며 기록한 것입니다.
시간이 괜찮다면 팀원 '평양냉면7 '님의 블로그도 한번 봐주세요 :)
'AWS > 테라폼(Terraform)' 카테고리의 다른 글
실전! 테라폼 정복기 2편 - vpc, subnet 설정과 인프라 구축 (0) | 2023.12.16 |
---|---|
실전! 테라폼 정복기 1편 - 테라폼(Terraform) 모듈화 (1) | 2023.12.09 |
테라폼(Terraform) 사용 가이드 6: 테라폼으로 IAM 정책 생성/관리하기 (1) | 2023.12.05 |
테라폼(Terraform) 사용 가이드 5: variable/output(입출력 변수) 사용하기 (1) | 2023.12.05 |
테라폼(Terraform) 사용 가이드 4: 생성된 AWS EC2 인스턴스 파괴하기 (0) | 2023.12.05 |