Ssoon

[7주차] 프로덕션 수준의 테라폼 코드 본문

Terraform 101 Study

[7주차] 프로덕션 수준의 테라폼 코드

구구달스 2022. 12. 6. 22:41
CloudNet@ 팀의 가시다님이 진행하는 Terraform 101 Study 07주차 정리입니다.

 

 

GitHub - kschoi728/T101: Terraform 101 Study

Terraform 101 Study. Contribute to kschoi728/T101 development by creating an account on GitHub.

github.com

프로덕션 수준 인프라 구축에는 많은 시간이 필요합니다.

 💠 데브 옵스 산업은 아직 초기 단게입니다. 이러한 기술들은 아직 충분히 성숙하지 않았습니다.

 💠 원래 하고 싶엇던 작업을 수행하기 전 해야 하는 많은 작업들에 취약합니다.

 💠 프로덕션 인프라를 준비하기 위해 수행해야 하는 작업의 체크 리스트가 너무 길기 때문입니다.

프로덕션 수준 인프라 모듈

 💠 소형 모듈

   ✔ 각각 한 가지 일을 하는 소형 모듈로 코드를 작성합니다.

   ✔ 각각 하나의 작업을 수행하는 여러 개의 독립형 module 로 리팩토링하는 것이 좋은 방법입니다.

더보기

     리팩터링(refactoring)은 소프트웨어 공학에서 '결과의 변경 없이 코드의 구조를 재조정함'을 뜻한다. 주로 가독성을 높이고 유지보수를 편하게 한다.

 

 

소형 module 3개로 리팩토링

 💠 오토스케일링 그룹 (ASG)

 modules/cluster/asg-rolling-deploy/main.tf

  • aws_launch_configuration
  • aws_autoscaling_group
  • aws_autoscaling_schedule
  • aws_security_group
  • aws_security_group_rule
  • aws_cloudwatch_metric_alarm

 modules/cluster/asg-rolling-deploy/variables.tf

  • cluster_name
  • ami
  • instance_type
  • min_size
  • max_size
  • enable_autoscaling
  • custom_tags
  • server_port

 💠 애플리케이션 로드 밸런서 (ALB)

 modules/networking/alb/mian.tf

  • aws_lb
  • aws_lb_listener
  • aws_security_group
  • aws_security_group_rule

 modules/networking/alb/variables.tf

  • alb_name
  • subnet_ids

합성 가능한 module

 💠 외부에서 상태를 읽는 대신 입력 매개 변수를 통해 전달하고, 외부에 상태를 쓰는 대신 출력 매개 변수를 통해 게산 결과를 반환합니다.

 💠 모든 것을 입력 변수를 통해 전달하고 모든 것을 출력 변수를 통해 반환하며 간단한 module 들을 조합해 더 복잡한 module 을 만들 수 있습니다.

 

💠 새로운 입력 변수 4개 추가

 modules/cluster/asg-rolling-deploy/variables.tf

  • subnet_ids 
    • asg-rolling-deploy module을 배포할 서브넷으로 지정합니다.
    • webserver-cluster 모듈은 기본 vpc 및 subnet에 배포하도록 하드 코딩
    • subnet_ids 변수를 노출해 어떤 vpc 나 subnet에서도 사용할 수 있게 허용
  • target_group_arns
  • health_check_type
    • asg 를 로드 밸런서와 통합하는 방식을 구성합니다.
    • webserver_cluster 모듈에는 alb가 내장되어 있지만 asg-rolling-deploy 모듈은 일반 모듈이므로 로드 밸런서 설정을 입력 변수로 노출하면 다양한 상황에서 ASG 를 사용할 수 있습니다.
  • user_data
    • 사용자 데이터 스크립트를 전달하기 위한 것입니다.
    • webserver-cluster 모듈에 하드 코딩된 사용자 데이터 스크립트는 hello,world 앱 배포에만 사용
    • 사용자 데이터 스크립트를 입력 변수로 사용하면 asg-rolling-deploy 모듈은 ASG 전체에 배포할 수 있습니다.

 modules/cluster/asg-rolling-deploy/main.tf

  • subnet_ids / target_group_arns / health_check_type 3가지 입력변수를 aws_autoscaling_group 리소스에 전달합니다
    • ALB 같은 이전에 하드 코딩된 리소스 및 데이터 소스를 참조하는 설정으로 대체합니다.
resource "aws_autoscaling_group" "example" {
  name = "${var.cluster_name}-${aws_launch_configuration.example.name}"
  launch_configuration = aws_launch_configuration.example.name
  vpc_zone_identifier = var.subnet_ids
  target_group_arns = var.target_group_arns
  health_check_type = var.health_check_type
  • user_data 변수를 aws_launch_configuration 리소스로 전달합니다.
    • asg-rollig-deploy 모듈에 복사하지 않은 template_file 데이터 소스에 대한 참조를 대체합니다.
resource "aws_launch_configuration" "example" {
  image_id        = var.ami
  instance_type   = var.instance_type
  security_groups = [aws_security_group.instance.id]
  user_data       = var.user_data

 

💠 출력 변수 추가

 modules/cluster/asg-rolling-deploy/outputs.tf

  • 출력 변수를 추가합니다.
  • 이 데이터를 출력하면 모듈의 소비자가이러한 출력을 사용하여 보안 그룹에 사용자 정의 규칙을 추가하는 등 새로운 동작을 추가할 수 있습니다. > 모듈의 재사용성을 높입니다.
output "asg_name" {
  value       = aws_autoscaling_group.example.name
  description = "The name of the Auto Scaling Group"
}

output "instance_security_group_id" {
  value       = aws_security_group.instance.id
  description = "The ID of the EC2 Instance Security Group"
}

 

 modules/cluster/asg-rolling-deploy/outputs.tf

  • 동일하게 출력 변수를 추가합니다.
output "alb_dns_name" {
  value       = aws_lb.example.dns_name
  description = "The domain name of the load balancer"
}

output "alb_http_listener_arn" {
  value       = aws_lb_listener.http.arn
  description = "The ARN of the HTTP listener"
}

output "alb_security_group_id" {
  value       = aws_security_group.alb.id
  description = "The ALB Security Group ID"
}

 

💠 모듈 생성

asg-rolling-deploy 및 alb 모듈을 사용하여 'Hello,World!"앱을 배포할 수 있는 hello-world-app module 을 생성합니다.

 modules/services/hello-world-app/main.tf

 

앞에서 생성한 asg-rolling-deploy module 을 hello-world-app 모듈에 추가합니다.

module "asg" {
  source = "../../cluster/asg-rolling-deploy"

  cluster_name  = "hello-world-${var.environment}"
  ami           = var.ami
  user_data     = data.template_file.user_data.rendered
  instance_type = var.instance_type

  min_size           = var.min_size
  max_size           = var.max_size
  enable_autoscaling = var.enable_autoscaling

  subnet_ids        = data.aws_subnet_ids.default.ids
  target_group_arns = [aws_lb_target_group.asg.arn]
  health_check_type = "ELB"
  
  custom_tags = var.custom_tags
}

앞에서 생성한 alb modulehello-world-app 모듈에 추가합니다.

module "alb" {
  source = "../../networking/alb"

  alb_name   = "hello-world-${var.environment}"
  subnet_ids = data.aws_subnet_ids.default.ids
}

 

💠 ALB 대상 그룹 및 리스너 규칙 구성

 modules/services/hello-world-app/main.tf

name 에서 enviroment 입력 변수를 사용하도록 설정합니다.

cluster_name  = "hello-world-${var.environment}"

module "asg" {
  source = "../../cluster/asg-rolling-deploy"

  cluster_name  = "hello-world-${var.environment}"
  ami           = var.ami
  user_data     = data.template_file.user_data.rendered
  instance_type = var.instance_type
  ...

aws_lb_listener_rule 리소스의 listener_arn 매개 변수가 alb module 의 alb_http_listener_arn 출력을 가르키도록 설정합니다.

listener_arn = module.alb.alb_http_listener_arn

resource "aws_lb_listener_rule" "asg" {
  listener_arn = module.alb.alb_http_listener_arn
  priority     = 100

  condition {
    path_pattern {
      values = ["*"]
    }
  }
...

 

💠 출력 변수 추가

 modules/services/hello-world-app/outputs.tf

output "alb_dns_name" {
  value       = module.alb.alb_dns_name
  description = "The domain name of the load balancer"
}

output "asg_name" {
  value       = module.asg.asg_name
  description = "The name of the Auto Scaling Group"
}

output "instance_security_group_id" {
  value       = module.asg.instance_security_group_id
  description = "The ID of the EC2 Instance Security Group"
}

 

 

 

module 세분화 패턴

 💠 일반 모듈

   ✔ asg-rolling-deploy 및 alb 같은 모듈은 코드의 기본 구성 요소이며 다양하게 재사용이 가능합니다.

 💠 사용 사례별 모듈  

   ✔ hello-world-app 과 같은 모듈은 여러 개의 일반 모듈을 결합하여 특정 사례에 사용할 수 있습니다. 

 
Comments