수업 72일차 테라폼

유동우·2023년 1월 14일
1

terraform.tfstate : 상태파일 => 구축한 사람의 로컬컴퓨터에 저장됨

공유저장소 git을 쓰지않고

┌ s3 , 암호화
└ 다이나모DB

s3에 버킷을 만들어
terraform-state

global/S3 - main.tf , .tfstate
mysql상태
/stage/data-store/mysql - main.tf , .tfstate
/stage/workspace-example - main.tf

~/01-terraform/terraform-state/global/s3 에 tf init, tf apply

~/01-terraform/terraform-state에 mkdir file-layout-example , mkdir workspace-example

mv global file-layout-example

mv stage file-layout-example

cd workspace-example가서

vim main.tf

terraform {
required_version = ">= 1.0.0, < 2.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
backend "s3" {

 # 이전에 생성한 버킷 이름으로 변경
 bucket = "aws08-terraform-state"
 key    = "workspace-example/terraform.tfstate"
 region = "ap-northeast-2"
 # 이전에 생성한 다이나모DB 테이블 이름으로 변경
 dynamodb_table = "terraform-locks"
 encrypt        = true

}
}
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_instance" "example" {
ami = "ami-0ab04b3ccbadfae1f"
instance_type = "t2.micro"

tags 추가

tags = {
Name = "aws08-example"
}
}

tf init

tf apply

tf workspace list

terraform workspace new example1

tf init

tf apply하면 인스턴스가 2개가 러닝상태로됨

작업공간이 default와 example1 각각 다름

workspace

├ default - apply , destroy는 workspace-example에 저장

├ example1 - apply , destroy는 env: example1에 저장

└ example2 - apply , destroy는 env: example2에 저장

tf workspace select example1 // 작업할 공간 선택

tf workspace delete example2 // 작업한 공간 지우는 법

=====================================

■ 테라폼 모듈

~/01-terraform

mkdir terraform-module

cd terraform-module

cp -r ../terraform-state/file-layout-example/stage . // cp -r 하위 디렉토리 그대로복사하는 명령어 뒤는 경로

cp -r ../terraform-state/file-layout-example/global .

cp -r stage prod

mkdir modules

cd modules

ls ../stage

cp -r ../stage/services .

cd services/webserver-cluster

rm -rf .t*

vim main.tf 들어가서 provider 정의 제거

※ 파일 경로 정리

~/01-terraform/terraform-module
ls
global modules prod stage

terraform-module

├ modules - services - webserver-cluster => main.tf(provider삭제 , ami Ubuntu 20.04버젼으로 변경) , outputs.tf , variables.tf , user-data.sh


└ stage => data-store - mysql , services - webserver-cluster => main.tf(module추가,밑에꺼삭제) , outputs.tf , variables.tf , user-data.sh

※ stage/services/webserver-cluster vim main.tf

terraform {

테라폼 버전 지정

required_version = ">=1.0.0, <2.0.0"

공급자 버전 지정

required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}

provider "aws" {
region = "ap-northeast-2"
}

module "webserver_cluster" {
source = "../../../modules/services/webserver-cluster"
}
~

========================================================

modules/services/webserver-cluster

vim main.tf

terraform {

테라폼 버전 지정

required_version = ">=1.0.0, <2.0.0"

공급자 버전 지정

required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}

시작 템플릿 설정

resource "aws_launch_template" "example" {
name = "${var.cluster_name}-example"
image_id = "ami-06eea3cd85e2db8ce" # Ubuntu 20.04 version
instance_type = "var.instance_type"
key_name = "aws08-key"
vpc_security_group_ids = [aws_security_group.instance.id]

user_data = base64encode(data.template_file.web_output.rendered)

lifecycle {
create_before_destroy = true
}

}

오토스케일링 생성

resource "aws_autoscaling_group" "example" {
availability_zones = ["ap-northeast-2a", "ap-northeast-2c"]

name = "${var.cluster_name}-asg-example"
desired_capacity = var.des_size
min_size = var.min_size
max_size = var.max_size

target_group_arns = [aws_lb_target_group.asg.arn]
health_check_type = "ELB"

launch_template {
id = aws_launch_template.example.id
version = "$Latest"
}
tag {
key = "Name"
value = var.cluster_name
propagate_at_launch = true
}
}

로드밸런서

resource "aws_lb" "example" {
name = var.cluster_name
load_balancer_type = "application"
subnets = data.aws_subnets.default.ids
security_groups = [aws_security_group.alb.id]
}

로드밸런서 리스너

resource "aws_lb_listener" "http" {
load_balancer_arn = aws_lb.example.arn
port = 80
protocol = "HTTP"

기본값으로 단순한 404 페이지 오류를 반환한다.

default_action {
type = "fixed-response"
fixed_response {
content_type = "text/plain"
message_body = "404: page not found"
status_code = 404
}
}
}

로드 밸런서 리스너 룰 구성

resource "aws_lb_listener_rule" "asg" {
listener_arn = aws_lb_listener.http.arn
priority = 100

condition {
path_pattern {
values = ["*"]
}
}
action {
type = "forward"
target_group_arn = aws_lb_target_group.asg.arn
}
}

로드밸런서 대상그룹

resource "aws_lb_target_group" "asg" {
name = var.cluster_name
port = var.server_port
protocol = "HTTP"
vpc_id = data.aws_vpc.default.id

health_check {
path = "/"
protocol = "HTTP"
matcher = "200"
interval = 15
timeout = 3
healthy_threshold = 2
unhealthy_threshold = 2
}
}

보안그룹 - instance

resource "aws_security_group" "instance" {
name = "${var.cluster_name}-instance"
}

resource "aws_security_group_rule" "allow_http_inbound" {
type = "ingress"
security_group_id = aws_security_group.alb.id

 from_port   = var.server_port
 to_port     = var.server_port
 protocol    = local.tcp_protocol
 cidr_blocks = local.all_ips

}

보안 그룹 - ALB

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

resource "aws_security_group_rule" "allow_httpd_inbound" {
type = "ingress"
security_group_id = aws_security_group.alb.id

 from_port   = local.http_port            # 출발 포트
 to_port     = local.http_port            # 도착 포트
 protocol    = local.tcp_protocol         # 프로토콜
 cidr_blocks = local.all_ips              # 송신지

}

resource "aws_security_group_rule" "allow_all_outbound" {
type = "egress"
security_group_id \ aws=security_group.alb.id

 from_port   = local.any_port             # 출발 포트
 to_port     = local.any_port             # 도착 포트
 protocol    = local.any_protocol         # 프로토콜
 cidr_blocks = local.all_ips              # 송신지

}

data "terraform_remote_state" "db" {

backend = "s3"

config = {
bucket = var.db_remote-state_bucket
key = var.db_remote_state_key
region = "ap-northeast-2"
}
}

locals {
http_port = 80
any_port = 0
any_protocol = "-1"
tcp_protocol = "tcp"
all_ips = ["0.0.0.0/0"]
}

Default VPC 정보 가지고 오기

data "aws_vpc" "default" {
default = true
}

Subnet 정보 가지고 오기

data "aws_subnets" "default" {
filter {
name = "vpc-id"
values = [data.aws_vpc.default.id]
}
}

data "template_file" "web_output" {
template = file("${path.module}/user-data.sh")
vars = {
server_port = var.server_port
db_address = data.terraform_remote_state.db.outputs.address
db_port = data.terraform_remote_state.db.outputs.port
}
}

vim. variables.tf

---------------------------------------------------------------------------------------------------------------------

REQUIRED PARAMETERS

You must provide a value for each of these parameters.

---------------------------------------------------------------------------------------------------------------------

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
}

variable "instance_type" {
description = "The type of EC2 Instances to run (e.g. t2.micro)"
type = string
}

variable "des_size" {
description = "The desired capacity of EC2 Instance in the ASG"
type = number
}

variable "min_size" {
description = "The minimum number of EC2 Instances in the ASG"
type = number
}

variable "max_size" {
description = "The maximum number of EC2 Instances in the ASG"
type = number
}

---------------------------------------------------------------------------------------------------------------------

OPTIONAL PARAMETERS

These parameters have reasonable defaults.

---------------------------------------------------------------------------------------------------------------------

variable "server_port" {
description = "The port the server will use for HTTP requests"
type = number
default = 8080
}

vim outputs.tf

outputs.tf

output "alb_dns_name" {
value = aws_lb.example.dns_name
description = "The domain name of the load balancer"
}

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

output "alb_security_group_id" {
value = aws_security_group.alb.id
description = "The ID of the Security Group attached to the load balancer"
}

==================================================

stage/services/webserver-cluster

vim main.tf

terraform {

테라폼 버전 지정

required_version = ">=1.0.0, <2.0.0"

공급자 버전 지정

required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}

provider "aws" {
region = "ap-northeast-2"
}

module "webserver_cluster" {
source = "../../../modules/services/webserver-cluster"

cluster_name = var.cluster_name
db_remote_state_bucket = var.db_remote_state_bucket
db_remote_state_key = var.db_remote_state_key

instance_type = "t2.micro"
des_size = 1
min_size = 1
max_size = 2
}

resource "aws_security_group_rule" "allow_testing_inbound" {
type = "ingress"
security_group_id = module.webserver_cluster.alb_security_group_id

from_port = 12345
to_port = 12345
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]

}

vim variables.tf

---------------------------------------------------------------------------------------------------------------------

REQUIRED PARAMETERS

You must provide a value for each of these parameters.

---------------------------------------------------------------------------------------------------------------------

variable "db_remote_state_bucket" {
description = "The name of the S3 bucket used for the database's remote state storage"
type = string
}

variable "db_remote_state_key" {
description = "The name of the key in the S3 bucket used for the database's remote state storage"
type = string
}

---------------------------------------------------------------------------------------------------------------------

OPTIONAL PARAMETERS

These parameters have reasonable defaults.

---------------------------------------------------------------------------------------------------------------------

variable "cluster_name" {
description = "The name to use to namespace all the resources in the cluster"
type = string
default = "aws08-webservers-stage"
}

====================================================

prod/services/webserver-cluster

vim main.tf

terraform {

# 테라폼 버전 지정
required_version = ">=1.0.0, <2.0.0"

# 공급자 버전 지정
required_providers {
  aws = {
    source  = "hashicorp/aws"
    version = "~> 4.0"
  }
}

}

provider "aws" {
region = "ap-northeast-2"
}

module "webserver_cluster" {
source = "../../../modules/services/webserver-cluster"

   cluster_name            =   var.cluster_name
   db_remote_state_bucket  =   var.db_remote_state_bucket
   db_remote_state_key     =   var.db_remote_state_key

   instance_type = "m4.large"
   des_size  = 2
   min_size  = 2
   max_size  = 10

}

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 9 * * * "

  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 17 * * * "

   autoscaling_group_name = module.webserver_cluster.asg_name
 }

vim variables.tf

---------------------------------------------------------------------------------------------------------------------

REQUIRED PARAMETERS

You must provide a value for each of these parameters.

---------------------------------------------------------------------------------------------------------------------

variable "db_remote_state_bucket" {
description = "The name of the S3 bucket used for the database's remote state storage"
type = string
}

variable "db_remote_state_key" {
description = "The name of the key in the S3 bucket used for the database's remote state storage"
type = string
}

---------------------------------------------------------------------------------------------------------------------

OPTIONAL PARAMETERS

These parameters have reasonable defaults.

---------------------------------------------------------------------------------------------------------------------

variable "cluster_name" {
description = "The name to use to namespace all the resources in the cluster"
type = string
default = "aws08-webservers-prod"
}

vim outputs.tf

outputs.tf

output "alb_dns_name" {
value = aws_lb.example.dns_name
description = "The domain name of the load balancer"
}

================================================

cd ../../data-stores/mysql

vim main.tf

terraform {
required_version = ">= 1.0.0, < 2.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
backend "s3" {

 # 이전에 생성한 버킷 이름으로 변경
 bucket = "aws08-terraform-state"
 key    = "prod/data-stores/mysql/terraform.tfstate"
 region = "ap-northeast-2"
 # 이전에 생성한 다이나모DB 테이블 이름으로 변경
 dynamodb_table = "aws08-prod-terraform-locks"
 encrypt        = true

}
}

provider "aws" {
region = "ap-northeast-2"
}

RDS에 데이터베이스를 생성한다.

resource "aws_db_instance" "example" {
identifier_prefix = "aws08-prod-terraform-example"
engine = "mysql"
allocated_storage = 10 # 스토리지는 10GB
instance_class = "db.t2.micro" # vCPU 1개, 1GB 메모리
skip_final_snapshot = true

name = var.db_name
username = var.db_username
password = var.db_password
}

vim variables.tf

variable "db_username" {
description = "The username for the database"
type = string
sensitive = true
}
variable "db_password" {
description = "The password for the database"
type = string
sensitive = true
}
variable "db_name" {
description = "The name to use for the database"
type = string
default = "aws08_example_database_prod"
}

vim outputs.tf

output "address" {
value = aws_db_instance.example.address
description = "Connect to the database at this endpoint"
}
output "port" {
value = aws_db_instance.example.port
description = "The port the database is listening on"
}

stage/data-stores/mysql

vim main.tf

terraform {
required_version = ">= 1.0.0, < 2.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
backend "s3" {

 # 이전에 생성한 버킷 이름으로 변경
 bucket = "aws08-terraform-state"
 key    = "stage/data-stores/mysql/terraform.tfstate"
 region = "ap-northeast-2"
 # 이전에 생성한 다이나모DB 테이블 이름으로 변경
 dynamodb_table = "aws08-stage-terraform-locks"
 encrypt        = true

}
}

provider "aws" {
region = "ap-northeast-2"
}

RDS에 데이터베이스를 생성한다.

resource "aws_db_instance" "example" {
identifier_prefix = "aws08-stage-terraform-example"
engine = "mysql"
allocated_storage = 10 # 스토리지는 10GB
instance_class = "db.t2.micro" # vCPU 1개, 1GB 메모리
skip_final_snapshot = true

name = var.db_name
username = var.db_username
password = var.db_password
}

vim variables.tf

variable "db_username" {
description = "The username for the database"
type = string
sensitive = true
}
variable "db_password" {
description = "The password for the database"
type = string
sensitive = true
}
variable "db_name" {
description = "The name to use for the database"
type = string
default = "aws08_example_database_stage"
}

vim outputs.tf

output "address" {
value = aws_db_instance.example.address
description = "Connect to the database at this endpoint"
}
output "port" {
value = aws_db_instance.example.port
description = "The port the database is listening on"
}

stage/services/webserver-cluster

vim variables.tf

----------------------------------------------------------------------------- ----------------------------------------

REQUIRED PARAMETERS

You must provide a value for each of these parameters.

----------------------------------------------------------------------------- ----------------------------------------

variable "db_remote_state_bucket" {
description = "The name of the S3 bucket used for the database's remote state storage"
type = string
default = "aws08-terraform-state"
}

variable "db_remote_state_key" {
description = "The name of the key in the S3 bucket used for the database's r emote state storage"
type = string
default = "stage/data-stores/mysql/terraform.tfstate"
}

----------------------------------------------------------------------------- ----------------------------------------

OPTIONAL PARAMETERS

These parameters have reasonable defaults.

----------------------------------------------------------------------------- ----------------------------------------

variable "cluster_name" {
description = "The name to use to namespace all the resources in the cluster"
type = string
default = "aws08-webservers-stage"
}

prod/services/webserver-cluster

vim variables.tf

----------------------------------------------------------------------------- ----------------------------------------

REQUIRED PARAMETERS

You must provide a value for each of these parameters.

----------------------------------------------------------------------------- ----------------------------------------

variable "db_remote_state_bucket" {
description = "The name of the S3 bucket used for the database's remote state storage"
type = string
default = "aws08-terraform-state"
}

variable "db_remote_state_key" {
description = "The name of the key in the S3 bucket used for the database's r emote state storage"
type = string
default = "prod/data-stores/mysql/terraform.tfstate"
}

----------------------------------------------------------------------------- ----------------------------------------

OPTIONAL PARAMETERS

These parameters have reasonable defaults.

----------------------------------------------------------------------------- ----------------------------------------

variable "cluster_name" {
description = "The name to use to namespace all the resources in the cluster"
type = string
default = "aws08-webservers-prod"
}

profile
클라우드 엔지니어가 되고싶은 클린이

0개의 댓글