테라폼(Terraform) 사용 가이드 7: AutoScailingGroup과 LoadBalancer을 생성하고 연결하기

2023. 12. 7. 18:33·DevOps/테라폼(Terraform)
반응형
 
 
 

이번 포스트에서는 테라폼으로 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 설정이 없는 경우

  1. Terraform 코드에서 Auto Scaling Group의 desired_capacity를 3으로 설정했다고 가정한다.
  2. 누군가 AWS 콘솔에서 이 값을 5로 변경한다.
  3. Terraform을 다시 실행할 때, Terraform은 현재 AWS 상태(5)와 Terraform 코드(3) 간의 차이를 감지한다.
  4. Terraform은 이 차이를 해소하기 위해 AWS 상태를 Terraform 코드에 명시된 상태(3)로 돌려놓는다. 즉, AWS 콘솔에서 변경된 desired_capacity 5를 무시하고 다시 3으로 설정한다.

 

ignore_changes 설정이 있는 경우

  1. 마찬가지로 Terraform 코드에서 desired_capacity를 3으로 설정했다고 가정한다.
  2. Terraform 코드에는 ignore_changes 설정이 추가되어 desired_capacity 변경사항을 무시한다.
  3. AWS 콘솔에서 누군가 desired_capacity를 5로 변경한다.
  4. Terraform을 다시 실행할 때, ignore_changes 설정 때문에 Terraform은 AWS 상태(5)와 Terraform 코드(3) 간의 차이를 무시한다.
  5. 즉, 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 '님의 블로그도 한번 봐주세요 :)
 

하다보니 재미있는 개발

하다 보니 재미있는 개발에 빠져있는 중입니다. 문의사항: ysoil8811@gmail.com

yijoon009.tistory.com

 

반응형

'DevOps > 테라폼(Terraform)' 카테고리의 다른 글

실전! 테라폼 정복기 2편 - vpc, subnet 설정과 인프라 구축  (0) 2023.12.16
실전! 테라폼 정복기 1편 - 테라폼(Terraform) 모듈화  (2) 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
'DevOps/테라폼(Terraform)' 카테고리의 다른 글
  • 실전! 테라폼 정복기 2편 - vpc, subnet 설정과 인프라 구축
  • 실전! 테라폼 정복기 1편 - 테라폼(Terraform) 모듈화
  • 테라폼(Terraform) 사용 가이드 6: 테라폼으로 IAM 정책 생성/관리하기
  • 테라폼(Terraform) 사용 가이드 5: variable/output(입출력 변수) 사용하기
Stark97
Stark97
문의사항 또는 커피챗 요청은 링크드인 메신저를 보내주세요! : https://www.linkedin.com/in/writedev/
  • Stark97
    오늘도 개발중입니다
    Stark97
  • 전체
    오늘
    어제
    • 분류 전체보기 (248) N
      • 개발지식 (20)
        • 스레드(Thread) (8)
        • WEB, DB, GIT (3)
        • 디자인패턴 (8)
      • JAVA (21)
      • Spring (88)
        • Spring 기초 지식 (35)
        • Spring 설정 (6)
        • JPA (7)
        • Spring Security (17)
        • Spring에서 Java 활용하기 (8)
        • 테스트 코드 (15)
      • 아키텍처 (6)
      • MSA (15)
      • DDD (12) N
      • gRPC (9)
      • Apache Kafka (18)
      • DevOps (23)
        • nGrinder (4)
        • Docker (1)
        • k8s (1)
        • 테라폼(Terraform) (12)
      • AWS (32)
        • ECS, ECR (14)
        • EC2 (2)
        • CodePipeline, CICD (8)
        • SNS, SQS (5)
        • RDS (2)
      • notion&obsidian (3)
      • 채팅 서비스 (0)
      • AI 탐험대 (1)
      • 팀 Pulse (0)
  • 링크

    • notion기록
    • 깃허브
    • 링크드인
  • hELLO· Designed By정상우.v4.10.0
Stark97
테라폼(Terraform) 사용 가이드 7: AutoScailingGroup과 LoadBalancer을 생성하고 연결하기
상단으로

티스토리툴바