brunch

You can make anything
by writing

C.S.Lewis

by Master Seo Nov 14. 2022

19탄-14. 테라폼-AWS-모듈 이론 2

다음은 주말 CloudNet 테라폼 스터디 내용 참고하여  정리한 부분입니다.

https://gasidaseo.notion.site/gasidaseo/CloudNet-Blog-c9dfa44a27ff431dafdd2edacc8a1863


<1> 모듈 소스 

<2> local로 2명의 iam user를 만들어 보자

<3> 모듈 이론

<4> 모듈에 지역변수 활용

<5> 출력



<1> 모듈 소스 


개발과 프로덕션 환경에서 동일한 코드를 복사하여 사용하는 대신, 모듈로 동일하게 재사용


1

모듈의 저장소 소스

https://developer.hashicorp.com/terraform/language/modules/sources


로컬 패스, 테라폼 레지스트리, 깃허브 , 비트버킷 , s3  버킷 , GCS 버킷등 다영한 저장소 소스를 사용할수 있다!!!


2

테라폼 레지스트리의 모듈 부분 자료 참고

https://registry.terraform.io/


3

모듈 소스 참고

https://github.com/terraform-aws-modules




<2> local로 2명의 iam user를 만들어 보자


1

mkdir  test

cd test


2

cat <<EOT > iamuser.tf

provider "aws" {

  region = "ap-northeast-2"

}


locals {

  name = "mytest"

  team = {

    group = "dev"

  }

}


resource "aws_iam_user" "myiamuser1" {

  name = "\${local.name}1"

  tags = local.team

}


resource "aws_iam_user" "myiamuser2" {

  name = "\${local.name}2"

  tags = local.team

}

EOT



3

terraform init && terraform plan && terraform apply -auto-approve


4

# iam 사용자 확인

aws iam list-users | jq


mytest1

mytest2  확인




# 삭제

terraform destroy -auto-approve





<3> 모듈 이론


1

스테이징 웹서버 클러스터를 모듈로 이동해보자.


2

디렉터리 구조


modules -services-webserver-cluster ------------ variables.tf  , output.tf , main.tf , user-data.sh


stage -services -webserver-cluster 


global----s3----------outputs.tf , main.tf



3

modules -services-webserver-cluster ------------ main.tf 안에는  provider를 제거한다.


모듈 안에는 provider를 제거한다.

프로바이더가 중복될 수 있어서 제거한다.


4

모듈  형식  ?


module "<NAME>" {

  source = "<SOURCE>"


  [CONFIG ...]

}


5

스테이징에서?


provider "aws" {

  region = "us-east-2"

}


module "webserver_cluster" {

  source = "../../../modules/services/webserver-cluster"

}


6

production에서?


provider "aws" {

  region = "us-east-2"

}


module "webserver_cluster" {

  source = "../../../modules/services/webserver-cluster"

}



7

teraform init  필수

공급자와 모듈을 가져와야 한다.



8

적용 시 실패한다!!

스테이징과 프로덕션에서 만들어지는 이름이 같아진다.  그래서  실패한다.

이름이 하드코딩되어 있어서 중복 이름이라 실패한다.


해결?

모듈에 입력 매개변수를 만들어 중복 이름이 안되도록 하자.


9

modules/services/webserver-cluster/variables.tf 에 새로운 입력 변수 3개를 추가


variable "cluster_name" {

  description = "The name to use for all the cluster resources"

  type        = string

}


variable "db_remote_state_bucket" {

  description = "The name of the S3 bucket for the database's remote state"

  type        = string

}


variable "db_remote_state_key" {

  description = "The path for the database's remote state in S3"

  type        = string

}


10

modules/services/webserver-cluster/main.tf 에 하드 코딩된 이름 대신 var.cluster_name 을 사용 



resource "aws_security_group" "alb" {

  name = "${var.cluster_name}-alb"


  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"]

  }

}


그외 태그등  AWS 리소스도 하드 코딩되어 중복되지 않게 변경 :

ex) 인스턴스 tag 리소스 : "${var.cluster_name}-instance"



11

terrroform_remote_state 데이터소스 업데이트 : bucket 과 key 매개 변수 수정


data "terraform_remote_state" "db" {

  backend = "s3"

  config = {

    bucket = var.db_remote_state_bucket

    key    = var.db_remote_state_key

    region = "us-east-2"

  }

}



[스테이징 환경] stage/services/webserver-cluster/main.tf 에서 아래와 같이 새로운 입력 변수를 설정


module "webserver_cluster" {

  source = "../../../modules/services/webserver-cluster"


  cluster_name           = "webservers-stage"

  db_remote_state_bucket = "(YOUR_BUCKET_NAME)"

  db_remote_state_key    = "stage/data-stores/mysql/terraform.tfstate"

}


12

[프로덕션 환경] prod/services/webserver-cluster/main.tf 에서 아래와 같이 새로운 입력 변수를 설정


module "webserver_cluster" {

  source = "../../../modules/services/webserver-cluster"


  cluster_name           = "webservers-prod"

  db_remote_state_bucket = "(YOUR_BUCKET_NAME)"

  db_remote_state_key    = "prod/data-stores/mysql/terraform.tfstate"

}



13

이후 modules/services/webserver-cluster/main.tf 에서 시작 구성을 업데이트


resource "aws_launch_configuration" "example" {

  image_id        = "ami-0fb653ca2d3203ac1"

  instance_type   = var.instance_type

  security_groups = [aws_security_group.instance.id]


  user_data = templatefile("user-data.sh", {

    server_port = var.server_port

    db_address  = data.terraform_remote_state.db.outputs.address

    db_port     = data.terraform_remote_state.db.outputs.port

  })


  # Required when using a launch configuration with an auto scaling group.

  lifecycle {

    create_before_destroy = true

  }

}


14

ASG에 업데이트


resource "aws_autoscaling_group" "example" {

  launch_configuration = aws_launch_configuration.example.name

  vpc_zone_identifier  = data.aws_subnets.default.ids

  target_group_arns    = [aws_lb_target_group.asg.arn]

  health_check_type    = "ELB"


  min_size = var.min_size

  max_size = var.max_size


  tag {

    key                 = "Name"

    value               = var.cluster_name

    propagate_at_launch = true

  }

}


15

[스테이징 환경] 에서 stage/services/webserver-cluster/main.tf 에 설정


module "webserver_cluster" {

  source = "../../../modules/services/webserver-cluster"

  cluster_name           = "webservers-stage"

  db_remote_state_bucket = "(YOUR_BUCKET_NAME)"

  db_remote_state_key    = "stage/data-stores/mysql/terraform.tfstate"

  instance_type = "t2.micro"

  min_size      = 2

  max_size      = 2

}



16

[프로덕션 환경] 에서 prod/services/webserver-cluster/main.tf 에 설정


module "webserver_cluster" {

  source = "../../../modules/services/webserver-cluster"

  cluster_name           = "webservers-prod"

  db_remote_state_bucket = "(YOUR_BUCKET_NAME)"

  db_remote_state_key    = "prod/data-stores/mysql/terraform.tfstate"

  instance_type = "m4.large"

  min_size      = 2

  max_size      = 10

}





<4> 모듈에 지역변수 활용



1

현재 보안 그룹 


resource "aws_security_group" "alb" {

  name = "${var.cluster_name}-alb"


  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"]

  }

}



2

지역변수 활용


locals {

  http_port    = 80

  any_port     = 0

  any_protocol = "-1"

  tcp_protocol = "tcp"

  all_ips      = ["0.0.0.0/0"]

}


3

resource "aws_security_group" "alb" {

  name = "${var.cluster_name}-alb"  

  ingress {

    from_port   = local.http_port

    to_port     = local.http_port

    protocol    = local.tcp_protocol

    cidr_blocks = local.all_ips

  }


  egress {

    from_port   = local.any_port

    to_port     = local.any_port

    protocol    = local.any_protocol

    cidr_blocks = local.all_ips

  }



<5> 출력


1

프로덕션] 환경의 ASG에 스케줄 기반 증감 정책 : 매일 오전 8시 10대 증가 → 매일 오후 9시 2대로 감소.


resource "aws_autoscaling_schedule" "scale_out_during_business_hours" {

  scheduled_action_name = "scale-out-during-business-hours"

  min_size              = 2

  max_size              = 10

  desired_capacity      = 10

  recurrence            = "0 8 * * *"

}


resource "aws_autoscaling_schedule" "scale_in_at_night" {

  scheduled_action_name = "scale-in-at-night"

  min_size              = 2

  max_size              = 10

  desired_capacity      = 2

  recurrence            = "0 21 * * *"

}


2

모듈에서 ASG 이름을 출력 변수로 설정 : /modules/services/webserver-cluster/outputs.tf

output "asg_name" {

  value       = aws_autoscaling_group.example.name

  description = "The name of the Auto Scaling Group"


모듈에서 오토스케일링 그룹의 이름을 출력으로 만든다.




3

프로덕트에서  오토 스케일링 그룹 이름을 가져와 써야 한다.


# 사용 구문

module.<MODULE_NAME>.<OUTPUT_NAME>


# 다음과 같이 사용

module.frontend.asg_name



4

ASG 코드 내용에 추가 : prod/services/webserver-cluster/main.tf

resource "aws_autoscaling_schedule" "scale_out_during_business_hours" {

  scheduled_action_name = "scale-out-during-business-hours"

  min_size              = 2

  max_size              = 10

  desired_capacity      = 10

  recurrence            = "0 8 * * *"


  autoscaling_group_name = module.webserver_cluster.asg_name

}


resource "aws_autoscaling_schedule" "scale_in_at_night" {

  scheduled_action_name = "scale-in-at-night"

  min_size              = 2

  max_size              = 10

  desired_capacity      = 2

  recurrence            = "0 21 * * *"


  autoscaling_group_name = module.webserver_cluster.asg_name

}




다음

https://brunch.co.kr/@topasvga/2808







https://brunch.co.kr/@topasvga/2421

감사합니다.


브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari